diff --git a/code/__DEFINES/dye_keys.dm b/code/__DEFINES/dye_keys.dm
index 133f9c47d3..a01dcacc18 100644
--- a/code/__DEFINES/dye_keys.dm
+++ b/code/__DEFINES/dye_keys.dm
@@ -4,6 +4,7 @@
#define DYE_REGISTRY_SNEAKERS "sneakers"
#define DYE_REGISTRY_FANNYPACK "fannypack"
#define DYE_REGISTRY_BEDSHEET "bedsheet"
+#define DYE_LAWYER_SPECIAL "lawyer_special"
#define DYE_RED "red"
#define DYE_ORANGE "orange"
@@ -16,6 +17,7 @@
#define DYE_RAINBOW "rainbow"
#define DYE_MIME "mime"
#define DYE_COSMIC "cosmic"
+#define DYE_SYNDICATE "syndicate"
#define DYE_QM "qm"
#define DYE_LAW "law"
#define DYE_CAPTAIN "captain"
@@ -26,3 +28,5 @@
#define DYE_CMO "cmo"
#define DYE_REDCOAT "redcoat"
#define DYE_CLOWN "clown"
+#define DYE_CHAP "chap"
+#define DYE_CENTCOM "centcom"
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index fc1706a948..0704947dda 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -116,6 +116,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define CRAYON_FONT "Comic Sans MS"
#define PRINTER_FONT "Times New Roman"
#define SIGNFONT "Times New Roman"
+#define CHARCOAL_FONT "Candara"
#define RESIZE_DEFAULT_SIZE 1
diff --git a/code/datums/components/honkspam.dm b/code/datums/components/honkspam.dm
new file mode 100644
index 0000000000..73b5e3335a
--- /dev/null
+++ b/code/datums/components/honkspam.dm
@@ -0,0 +1,22 @@
+// This used to be in paper.dm, it was some snowflake code that was
+// used ONLY on april's fool. I moved it to a component so it could be
+// used in other places
+
+/datum/component/honkspam
+ dupe_mode = COMPONENT_DUPE_UNIQUE
+ var/spam_flag = FALSE
+
+/datum/component/honkspam/Initialize()
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+ RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact)
+
+/datum/component/honkspam/proc/reset_spamflag()
+ spam_flag = FALSE
+
+/datum/component/honkspam/proc/interact(mob/user)
+ if(!spam_flag)
+ spam_flag = TRUE
+ var/obj/item/parent_item = parent
+ playsound(parent_item.loc, 'sound/items/bikehorn.ogg', 50, TRUE)
+ addtimer(CALLBACK(src, .proc/reset_spamflag), 2 SECONDS)
diff --git a/code/datums/components/label.dm b/code/datums/components/label.dm
new file mode 100644
index 0000000000..c6d0c595eb
--- /dev/null
+++ b/code/datums/components/label.dm
@@ -0,0 +1,87 @@
+/**
+ The label component.
+
+ This component is used to manage labels applied by the hand labeler.
+
+ Atoms can only have one instance of this component, and therefore only one label at a time.
+ This is to avoid having names like "Backpack (label1) (label2) (label3)". This is annoying and abnoxious to read.
+
+ When a player clicks the atom with a hand labeler to apply a label, this component gets applied to it.
+ If the labeler is off, the component will be removed from it, and the label will be removed from its name.
+ */
+/datum/component/label
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ /// The name of the label the player is applying to the parent.
+ var/label_name
+
+/datum/component/label/Initialize(_label_name)
+ if(!isatom(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ label_name = _label_name
+ apply_label()
+
+/datum/component/label/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackby)
+ RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/Examine)
+
+/datum/component/label/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_PARENT_ATTACKBY, COMSIG_PARENT_EXAMINE))
+
+/**
+ This proc will fire after the parent is hit by a hand labeler which is trying to apply another label.
+ Since the parent already has a label, it will remove the old one from the parent's name, and apply the new one.
+*/
+/datum/component/label/InheritComponent(datum/component/label/new_comp , i_am_original, _label_name)
+ remove_label()
+ if(new_comp)
+ label_name = new_comp.label_name
+ else
+ label_name = _label_name
+ apply_label()
+
+/**
+ This proc will trigger when any object is used to attack the parent.
+
+ If the attacking object is not a hand labeler, it will return.
+ If the attacking object is a hand labeler it will restore the name of the parent to what it was before this component was added to it, and the component will be deleted.
+
+ Arguments:
+ * source: The parent.
+ * attacker: The object that is hitting the parent.
+ * user: The mob who is wielding the attacking object.
+*/
+/datum/component/label/proc/OnAttackby(datum/source, obj/item/attacker, mob/user)
+ // If the attacking object is not a hand labeler or its mode is 1 (has a label ready to apply), return.
+ // The hand labeler should be off (mode is 0), in order to remove a label.
+ var/obj/item/hand_labeler/labeler = attacker
+ if(!istype(labeler) || labeler.mode)
+ return
+
+ remove_label()
+ playsound(parent, 'sound/items/poster_ripped.ogg', 20, TRUE)
+ to_chat(user, "You remove the label from [parent].")
+ qdel(src) // Remove the component from the object.
+
+/**
+ This proc will trigger when someone examines the parent.
+ It will attach the text found in the body of the proc to the `examine_list` and display it to the player examining the parent.
+
+ Arguments:
+ * source: The parent.
+ * user: The mob exmaining the parent.
+ * examine_list: The current list of text getting passed from the parent's normal examine() proc.
+*/
+/datum/component/label/proc/Examine(datum/source, mob/user, list/examine_list)
+ examine_list += "It has a label with some words written on it. Use a hand labeler to remove it."
+
+/// Applies a label to the name of the parent in the format of: "parent_name (label)"
+/datum/component/label/proc/apply_label()
+ var/atom/owner = parent
+ owner.name += " ([label_name])"
+
+/// Removes the label from the parent's name
+/datum/component/label/proc/remove_label()
+ var/atom/owner = parent
+ owner.name = replacetext(owner.name, "([label_name])", "") // Remove the label text from the parent's name, wherever it's located.
+ owner.name = trim(owner.name) // Shave off any white space from the beginning or end of the parent's name.
diff --git a/code/modules/NTNet/netdata.dm b/code/modules/NTNet/netdata.dm
index 857869fc21..2a3a85f706 100644
--- a/code/modules/NTNet/netdata.dm
+++ b/code/modules/NTNet/netdata.dm
@@ -11,23 +11,6 @@
var/list/passkey
-// Process data before sending it
-/datum/netdata/proc/pre_send(datum/component/ntnet_interface/interface)
- // Decrypt the passkey.
- if(autopasskey)
- if(data["encrypted_passkey"] && !passkey)
- var/result = XorEncrypt(hextostr(data["encrypted_passkey"], TRUE), SScircuit.cipherkey)
- if(length(result) > 1)
- passkey = json_decode(XorEncrypt(hextostr(data["encrypted_passkey"], TRUE), SScircuit.cipherkey))
-
- // Encrypt the passkey.
- if(!data["encrypted_passkey"] && passkey)
- data["encrypted_passkey"] = strtohex(XorEncrypt(json_encode(passkey), SScircuit.cipherkey))
-
- // If there is no sender ID, set the default one.
- if(!sender_id && interface)
- sender_id = interface.hardware_id
-
/datum/netdata/proc/standard_format_data(primary, secondary, passkey)
data["data"] = primary
data["data_secondary"] = secondary
diff --git a/code/modules/NTNet/network.dm b/code/modules/NTNet/network.dm
index d86ad792fe..2a2820d289 100644
--- a/code/modules/NTNet/network.dm
+++ b/code/modules/NTNet/network.dm
@@ -206,7 +206,7 @@
for(var/datum/ntnet_conversation/chan in chat_channels)
if(chan.id == id)
return chan
-
+
// Resets the IDS alarm
/datum/ntnet/proc/resetIDS()
intrusion_detection_alarm = FALSE
diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm
index e7bdbc6d52..712ee4c867 100644
--- a/code/modules/asset_cache/asset_list_items.dm
+++ b/code/modules/asset_cache/asset_list_items.dm
@@ -105,11 +105,11 @@
"stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png',
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
- "stamp-law" = 'icons/stamp_icons/large_stamp-law.png'
- // "stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png',
- // "stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png',
- // "stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png',
- // "stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png'
+ "stamp-law" = 'icons/stamp_icons/large_stamp-law.png',
+ "stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png',
+ "stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png',
+ "stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png',
+ "stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png'
)
diff --git a/code/modules/modular_computers/computers/_modular_computer_shared.dm b/code/modules/modular_computers/computers/_modular_computer_shared.dm
index 8ca93e8347..f0583a9af1 100644
--- a/code/modules/modular_computers/computers/_modular_computer_shared.dm
+++ b/code/modules/modular_computers/computers/_modular_computer_shared.dm
@@ -44,18 +44,20 @@
. += "It has a slot installed for an intelliCard."
var/obj/item/computer_hardware/card_slot/card_slot = get_modular_computer_part(MC_CARD)
+ var/obj/item/computer_hardware/card_slot/card_slot2 = get_modular_computer_part(MC_CARD2)
+ var/multiple_slots = istype(card_slot) && istype(card_slot2)
if(card_slot)
- if(card_slot.stored_card || card_slot.stored_card2)
+ if(card_slot.stored_card || card_slot2.stored_card)
var/obj/item/card/id/first_ID = card_slot.stored_card
- var/obj/item/card/id/second_ID = card_slot.stored_card2
+ var/obj/item/card/id/second_ID = card_slot2.stored_card
var/multiple_cards = istype(first_ID) && istype(second_ID)
if(user_is_adjacent)
- . += "It has two slots for identification cards installed[multiple_cards ? " which contain [first_ID] and [second_ID]" : ", one of which contains [first_ID ? first_ID : second_ID]"]."
+ . += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed[multiple_cards ? " which contain [first_ID] and [second_ID]" : ", one of which contains [first_ID ? first_ID : second_ID]"]."
else
- . += "It has two slots for identification cards installed, [multiple_cards ? "both of which appear" : "and one of them appears"] to be occupied."
+ . += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed, [multiple_cards ? "both of which appear" : "and one of them appears"] to be occupied."
. += "Alt-click [src] to eject the identification card[multiple_cards ? "s":""]."
else
- . += "It has two slots installed for identification cards."
+ . += "It has [multiple_slots ? "two slots" : "a slot"] installed for identification cards."
var/obj/item/computer_hardware/printer/printer_slot = get_modular_computer_part(MC_PRINT)
if(printer_slot)
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index 67c04de13f..4313f4fa98 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -4,6 +4,12 @@
/obj/item/modular_computer
name = "modular microcomputer"
desc = "A small portable microcomputer."
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "laptop-open"
+ light_on = FALSE
+ integrity_failure = 0.5
+ max_integrity = 100
+ armor = list("melee" = 0, "bullet" = 20, "laser" = 20, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0)
var/enabled = 0 // Whether the computer is turned on.
var/screen_on = 1 // Whether the computer is active/opened/it's screen is on.
@@ -22,8 +28,6 @@
// must have it's own DMI file. Icon states must be called exactly the same in all files, but may look differently
// If you create a program which is limited to Laptops and Consoles you don't have to add it's icon_state overlay for Tablets too, for example.
- icon = 'icons/obj/computer.dmi'
- icon_state = "laptop-open"
var/icon_state_unpowered = null // Icon state when the computer is turned off.
var/icon_state_powered = null // Icon state when the computer is turned on.
var/icon_state_menu = "menu" // Icon state overlay when the computer is turned on, but no program is loaded that would override the screen.
@@ -31,20 +35,16 @@
var/max_hardware_size = 0 // Maximal hardware w_class. Tablets/PDAs have 1, laptops 2, consoles 4.
var/steel_sheet_cost = 5 // Amount of steel sheets refunded when disassembling an empty frame of this computer.
- integrity_failure = 0.5
- max_integrity = 100
- armor = list("melee" = 0, "bullet" = 20, "laser" = 20, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0)
-
- // Important hardware (must be installed for computer to work)
-
- // Optional hardware (improves functionality, but is not critical for computer to work)
-
- var/list/all_components = list() // List of "connection ports" in this computer and the components with which they are plugged
+ /// List of "connection ports" in this computer and the components with which they are plugged
+ var/list/all_components = list()
+ /// Lazy List of extra hardware slots that can be used modularly.
+ var/list/expansion_bays
+ /// Number of total expansion bays this computer has available.
+ var/max_bays = 0
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/light_on = FALSE //If that light is enabled
var/comp_light_luminosity = 3 //The brightness of that light
var/comp_light_color //The color of that light
@@ -71,80 +71,15 @@
physical = null
return ..()
-
-/obj/item/modular_computer/proc/add_verb(var/path)
- switch(path)
- if(MC_CARD)
- verbs += /obj/item/modular_computer/proc/eject_id
- if(MC_SDD)
- verbs += /obj/item/modular_computer/proc/eject_disk
- if(MC_AI)
- verbs += /obj/item/modular_computer/proc/eject_card
-
-/obj/item/modular_computer/proc/remove_verb(path)
- switch(path)
- if(MC_CARD)
- verbs -= /obj/item/modular_computer/proc/eject_id
- if(MC_SDD)
- verbs -= /obj/item/modular_computer/proc/eject_disk
- if(MC_AI)
- verbs -= /obj/item/modular_computer/proc/eject_card
-
-// Eject ID card from computer, if it has ID slot with card inside.
-/obj/item/modular_computer/proc/eject_id()
- set name = "Eject ID"
- set category = "Object"
- set src in view(1)
-
- if(issilicon(usr))
- return
- var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
- if(usr.canUseTopic(src, BE_CLOSE))
- card_slot.try_eject(null, usr)
-
-// Eject ID card from computer, if it has ID slot with card inside.
-/obj/item/modular_computer/proc/eject_card()
- set name = "Eject Intellicard"
- set category = "Object"
-
- if(issilicon(usr))
- return
- var/obj/item/computer_hardware/ai_slot/ai_slot = all_components[MC_AI]
- if(usr.canUseTopic(src, BE_CLOSE))
- ai_slot.try_eject(null, usr,1)
-
-
-// Eject ID card from computer, if it has ID slot with card inside.
-/obj/item/modular_computer/proc/eject_disk()
- set name = "Eject Data Disk"
- set category = "Object"
-
- if(issilicon(usr))
- return
-
- if(usr.canUseTopic(src, BE_CLOSE))
- var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD]
- if(uninstall_component(portable_drive, usr))
- portable_drive.verb_pickup()
-
/obj/item/modular_computer/AltClick(mob/user)
..()
if(issilicon(user))
return
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]
- var/obj/item/computer_hardware/ai_slot/ai_slot = all_components[MC_AI]
- var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD]
- if(portable_drive)
- if(uninstall_component(portable_drive, user))
- portable_drive.verb_pickup()
- else
- if(card_slot && card_slot.try_eject(null, user))
- return
- if(ai_slot)
- ai_slot.try_eject(null, user)
-
+ return (card_slot2?.try_eject(user) || card_slot?.try_eject(user)) //Try the secondary one first.
// Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs.
/obj/item/modular_computer/GetAccess()
@@ -160,19 +95,25 @@
return ..()
/obj/item/modular_computer/RemoveID()
+ 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]
- if(!card_slot)
- return
- return card_slot.RemoveID()
+ return (card_slot2?.try_eject() || card_slot?.try_eject()) //Try the secondary one first.
/obj/item/modular_computer/InsertID(obj/item/inserting_item)
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
- if(!card_slot)
+ var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
+ if(!(card_slot || card_slot2))
+ //to_chat(user, "There isn't anywhere you can fit a card into on this computer.")
return FALSE
+
var/obj/item/card/inserting_id = inserting_item.RemoveID()
if(!inserting_id)
return FALSE
- return card_slot.try_insert(inserting_id)
+
+ if((card_slot?.try_insert(inserting_id)) || (card_slot2?.try_insert(inserting_id)))
+ return TRUE
+ //to_chat(user, "This computer doesn't have an open card slot.")
+ return FALSE
/obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location)
var/mob/M = usr
@@ -189,7 +130,7 @@
return
if(enabled)
ui_interact(user)
- else if(IsAdminGhost(user))
+ else if(isAdminGhostAI(user))
var/response = alert(user, "This computer is turned off. Would you like to turn it on?", "Admin Override", "Yes", "No")
if(response == "Yes")
turn_on(user)
diff --git a/code/modules/modular_computers/computers/item/computer_components.dm b/code/modules/modular_computers/computers/item/computer_components.dm
index 3c94a66384..8668b279cf 100644
--- a/code/modules/modular_computers/computers/item/computer_components.dm
+++ b/code/modules/modular_computers/computers/item/computer_components.dm
@@ -6,6 +6,14 @@
to_chat(user, "This component is too large for \the [src]!")
return FALSE
+ if(H.expansion_hw)
+ if(LAZYLEN(expansion_bays) >= max_bays)
+ to_chat(user, "All of the computer's expansion bays are filled.")
+ return FALSE
+ if(LAZYACCESS(expansion_bays, H.device_type))
+ to_chat(user, "The computer immediately ejects /the [H] and flashes an error: \"Hardware Address Conflict\".")
+ return FALSE
+
if(all_components[H.device_type])
to_chat(user, "This computer's hardware slot is already occupied by \the [all_components[H.device_type]].")
return FALSE
@@ -20,6 +28,8 @@
if(user && !user.transferItemToLoc(H, src))
return FALSE
+ if(H.expansion_hw)
+ LAZYSET(expansion_bays, H.device_type, H)
all_components[H.device_type] = H
to_chat(user, "You install \the [H] into \the [src].")
@@ -32,7 +42,9 @@
/obj/item/modular_computer/proc/uninstall_component(obj/item/computer_hardware/H, mob/living/user = null)
if(H.holder != src) // Not our component at all.
return FALSE
+ if(H.expansion_hw)
+ LAZYREMOVE(expansion_bays, H.device_type)
all_components.Remove(H.device_type)
to_chat(user, "You remove \the [H] from \the [src].")
@@ -43,6 +55,7 @@
if(enabled && !use_power())
shutdown_computer()
update_icon()
+ return TRUE
// Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null
diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm
index fd017e2b0f..4a985b93c1 100644
--- a/code/modules/modular_computers/computers/item/computer_ui.dm
+++ b/code/modules/modular_computers/computers/item/computer_ui.dm
@@ -44,6 +44,33 @@
/obj/item/modular_computer/ui_data(mob/user)
var/list/data = get_header_data()
data["device_theme"] = device_theme
+
+ data["login"] = list()
+ var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
+ if(cardholder)
+ 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,
+ )
+
+ data["removable_media"] = list()
+ if(all_components[MC_SDD])
+ data["removable_media"] += "removable storage disk"
+ var/obj/item/computer_hardware/ai_slot/intelliholder = all_components[MC_AI]
+ if(intelliholder?.stored_card)
+ data["removable_media"] += "intelliCard"
+ var/obj/item/computer_hardware/card_slot/secondarycardholder = all_components[MC_CARD2]
+ if(secondarycardholder?.stored_card)
+ data["removable_media"] += "secondary RFID card"
+
data["programs"] = list()
var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
for(var/datum/computer_file/program/P in hard_drive.stored_files)
@@ -157,6 +184,36 @@
light_color = new_color
update_light()
return TRUE
+
+ if("PC_Eject_Disk")
+ var/param = params["name"]
+ var/mob/user = usr
+ switch(param)
+ if("removable storage disk")
+ var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD]
+ if(!portable_drive)
+ return
+ if(uninstall_component(portable_drive, usr))
+ user.put_in_hands(portable_drive)
+ playsound(src, 'sound/machines/card_slide.ogg', 50)
+ if("intelliCard")
+ var/obj/item/computer_hardware/ai_slot/intelliholder = all_components[MC_AI]
+ if(!intelliholder)
+ return
+ if(intelliholder.try_eject(user))
+ playsound(src, 'sound/machines/card_slide.ogg', 50)
+ if("ID")
+ var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
+ if(!cardholder)
+ return
+ cardholder.try_eject(user)
+ if("secondary RFID card")
+ var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD2]
+ if(!cardholder)
+ return
+ cardholder.try_eject(user)
+
+
else
return
diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm
index 5927d57a0b..ef83140a8f 100644
--- a/code/modules/modular_computers/computers/item/laptop.dm
+++ b/code/modules/modular_computers/computers/item/laptop.dm
@@ -12,6 +12,7 @@
hardware_flag = PROGRAM_LAPTOP
max_hardware_size = 2
w_class = WEIGHT_CLASS_NORMAL
+ max_bays = 4
// No running around with open laptops in hands.
item_flags = SLOWS_WHILE_IN_HAND
diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm
index c79d7a9361..0d7b567877 100644
--- a/code/modules/modular_computers/computers/item/processor.dm
+++ b/code/modules/modular_computers/computers/item/processor.dm
@@ -8,6 +8,7 @@
icon_state_unpowered = null
icon_state_menu = null
hardware_flag = 0
+ max_bays = 4
var/obj/machinery/modular_computer/machinery_computer = null
@@ -18,7 +19,7 @@
machinery_computer = null
. = ..()
-/obj/item/modular_computer/processor/New(comp) //intentional new probably
+/obj/item/modular_computer/processor/New(comp)
..()
STOP_PROCESSING(SSobj, src) // Processed by its machine
@@ -56,23 +57,5 @@
machinery_computer.update_icon()
return
-/obj/item/modular_computer/processor/add_verb(path)
- switch(path)
- if(MC_CARD)
- machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_id
- if(MC_SDD)
- machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_disk
- if(MC_AI)
- machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_card
-
-/obj/item/modular_computer/processor/remove_verb(path)
- switch(path)
- if(MC_CARD)
- machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_id
- if(MC_SDD)
- machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_disk
- if(MC_AI)
- machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_card
-
/obj/item/modular_computer/processor/attack_ghost(mob/user)
ui_interact(user)
diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm
index 41a256467f..67e8118c7a 100644
--- a/code/modules/modular_computers/computers/item/tablet.dm
+++ b/code/modules/modular_computers/computers/item/tablet.dm
@@ -5,10 +5,11 @@
icon_state_unpowered = "tablet"
icon_state_powered = "tablet"
icon_state_menu = "menu"
- //worn_icon_state = "tablet"
+ // worn_icon_state = "tablet"
hardware_flag = PROGRAM_TABLET
max_hardware_size = 1
w_class = WEIGHT_CLASS_SMALL
+ max_bays = 3
steel_sheet_cost = 1
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
has_light = TRUE //LED flashlight!
diff --git a/code/modules/modular_computers/computers/item/tablet_presets.dm b/code/modules/modular_computers/computers/item/tablet_presets.dm
index 7cca8ea5b4..d4945d04de 100644
--- a/code/modules/modular_computers/computers/item/tablet_presets.dm
+++ b/code/modules/modular_computers/computers/item/tablet_presets.dm
@@ -26,10 +26,20 @@
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(hard_drive)
+ install_component(new /obj/item/computer_hardware/card_slot)
install_component(new /obj/item/computer_hardware/network_card)
install_component(new /obj/item/computer_hardware/printer/mini)
hard_drive.store_file(new /datum/computer_file/program/bounty)
- //hard_drive.store_file(new /datum/computer_file/program/shipping)
+ hard_drive.store_file(new /datum/computer_file/program/shipping)
+
+/obj/item/modular_computer/tablet/preset/advanced/atmos/Initialize() //This will be defunct and will be replaced when NtOS PDAs are done
+ . = ..()
+ install_component(new /obj/item/computer_hardware/sensorpackage)
+
+/obj/item/modular_computer/tablet/preset/advanced/command/Initialize()
+ . = ..()
+ install_component(new /obj/item/computer_hardware/sensorpackage)
+ install_component(new /obj/item/computer_hardware/card_slot/secondary)
/// Given by the syndicate as part of the contract uplink bundle - loads in the Contractor Uplink.
/obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink/Initialize()
diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm
index 9d29b23e76..12b2f6d25a 100644
--- a/code/modules/modular_computers/computers/machinery/console_presets.dm
+++ b/code/modules/modular_computers/computers/machinery/console_presets.dm
@@ -1,6 +1,6 @@
/obj/machinery/modular_computer/console/preset
// Can be changed to give devices specific hardware
- var/_has_id_slot = FALSE
+ var/_has_second_id_slot = FALSE
var/_has_printer = FALSE
var/_has_battery = FALSE
var/_has_ai = FALSE
@@ -11,8 +11,9 @@
return
cpu.install_component(new /obj/item/computer_hardware/processor_unit)
- if(_has_id_slot)
- cpu.install_component(new /obj/item/computer_hardware/card_slot)
+ cpu.install_component(new /obj/item/computer_hardware/card_slot)
+ if(_has_second_id_slot)
+ cpu.install_component(new /obj/item/computer_hardware/card_slot/secondary)
if(_has_printer)
cpu.install_component(new /obj/item/computer_hardware/printer)
if(_has_battery)
@@ -59,7 +60,7 @@
console_department = "Command"
name = "command console"
desc = "A stationary computer. This one comes preloaded with command programs."
- _has_id_slot = TRUE
+ _has_second_id_slot = TRUE
_has_printer = TRUE
/obj/machinery/modular_computer/console/preset/command/install_programs()
@@ -73,7 +74,7 @@
console_department = "Identification"
name = "identification console"
desc = "A stationary computer. This one comes preloaded with identification modification programs."
- _has_id_slot = TRUE
+ _has_second_id_slot = TRUE
_has_printer = TRUE
/obj/machinery/modular_computer/console/preset/id/install_programs()
diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm
index 6f016ad147..0e6f4d161a 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -75,30 +75,6 @@
add_overlay("bsod")
add_overlay("broken")
-// Eject ID card from computer, if it has ID slot with card inside.
-/obj/machinery/modular_computer/proc/eject_id()
- set name = "Eject ID"
- set category = "Object"
-
- if(cpu)
- cpu.eject_id()
-
-// Eject ID card from computer, if it has ID slot with card inside.
-/obj/machinery/modular_computer/proc/eject_disk()
- set name = "Eject Data Disk"
- set category = "Object"
-
- if(cpu)
- cpu.eject_disk()
-
-/obj/machinery/modular_computer/proc/eject_card()
- set name = "Eject Intellicard"
- set category = "Object"
- set src in view(1)
-
- if(cpu)
- cpu.eject_card()
-
/obj/machinery/modular_computer/AltClick(mob/user)
if(cpu)
cpu.AltClick(user)
@@ -136,7 +112,7 @@
return
. = ..()
-/obj/machinery/modular_computer/attackby(var/obj/item/W as obj, mob/user)
+/obj/machinery/modular_computer/attackby(obj/item/W as obj, mob/user)
if(cpu && !(flags_1 & NODECONSTRUCT_1))
return cpu.attackby(W, user)
return ..()
@@ -169,5 +145,4 @@
// "Brute" damage mostly damages the casing.
/obj/machinery/modular_computer/bullet_act(obj/item/projectile/Proj)
if(cpu)
- return cpu.bullet_act(Proj)
- return ..()
+ cpu.bullet_act(Proj)
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index 12e5ef6e95..6d6a48d567 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -25,8 +25,6 @@
var/ntnet_status = 1
/// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
var/usage_flags = PROGRAM_ALL
- /// Optional string that describes what NTNet server/system this program connects to. Used in default logging.
- var/network_destination = null
/// Whether the program can be downloaded from NTNet. Set to 0 to disable.
var/available_on_ntnet = 1
/// Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable.
@@ -82,10 +80,18 @@
/datum/computer_file/program/proc/process_tick()
return 1
-// Check if the user can run program. Only humans can operate computer. Automatically called in run_program()
-// User has to wear their ID for ID Scan to work.
-// Can also be called manually, with optional parameter being access_to_check to scan the user's ID
-/datum/computer_file/program/proc/can_run(mob/user, loud = FALSE, access_to_check, transfer = FALSE)
+/**
+ *Check if the user can run program. Only humans can operate computer. Automatically called in run_program()
+ *ID must be inserted into a card slot to be read. If the program is not currently installed (as is the case when
+ *NT Software Hub is checking available software), a list can be given to be used instead.
+ *Arguments:
+ *user is a ref of the mob using the device.
+ *loud is a bool deciding if this proc should use to_chats
+ *access_to_check is an access level that will be checked against the ID
+ *transfer, if TRUE and access_to_check is null, will tell this proc to use the program's transfer_access in place of access_to_check
+ *access can contain a list of access numbers to check against. If access is not empty, it will be used istead of checking any inserted ID.
+*/
+/datum/computer_file/program/proc/can_run(mob/user, loud = FALSE, access_to_check, transfer = FALSE, var/list/access)
// Defaults to required_access
if(!access_to_check)
if(transfer && transfer_access)
@@ -104,29 +110,24 @@
if(issilicon(user))
return TRUE
- if(ishuman(user))
+ if(!length(access))
var/obj/item/card/id/D
var/obj/item/computer_hardware/card_slot/card_slot
- if(computer && card_slot)
+ if(computer)
card_slot = computer.all_components[MC_CARD]
- D = card_slot.GetID()
- var/mob/living/carbon/human/h = user
- var/obj/item/card/id/I = h.get_idcard(TRUE)
+ D = card_slot?.GetID()
- if(!I && !D)
+ if(!D)
if(loud)
to_chat(user, "\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.")
return FALSE
+ access = D.GetAccess()
- if(I)
- if(access_to_check in I.GetAccess())
- return TRUE
- else if(D)
- if(access_to_check in D.GetAccess())
- return TRUE
- if(loud)
- to_chat(user, "\The [computer] flashes an \"Access Denied\" warning.")
- return 0
+ if(access_to_check in access)
+ return TRUE
+ if(loud)
+ to_chat(user, "\The [computer] flashes an \"Access Denied\" warning.")
+ return FALSE
// This attempts to retrieve header data for UIs. If implementing completely new device of different type than existing ones
// always include the device here in this proc. This proc basically relays the request to whatever is running the program.
@@ -139,8 +140,12 @@
// When implementing new program based device, use this to run the program.
/datum/computer_file/program/proc/run_program(mob/living/user)
if(can_run(user, 1))
- if(requires_ntnet && network_destination)
- generate_network_log("Connection opened to [network_destination].")
+ if(requires_ntnet)
+ var/obj/item/card/id/ID
+ var/obj/item/computer_hardware/card_slot/card_holder = computer.all_components[MC_CARD]
+ if(card_holder)
+ ID = card_holder.GetID()
+ generate_network_log("Connection opened -- Program ID: [filename] User:[ID?"[ID.registered_name]":"None"]")
program_state = PROGRAM_STATE_ACTIVE
return 1
return 0
@@ -162,8 +167,12 @@
// Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client.
/datum/computer_file/program/proc/kill_program(forced = FALSE)
program_state = PROGRAM_STATE_KILLED
- if(network_destination)
- generate_network_log("Connection to [network_destination] closed.")
+ if(requires_ntnet)
+ var/obj/item/card/id/ID
+ var/obj/item/computer_hardware/card_slot/card_holder = computer.all_components[MC_CARD]
+ if(card_holder)
+ ID = card_holder.GetID()
+ generate_network_log("Connection closed -- Program ID: [filename] User:[ID?"[ID.registered_name]":"None"]")
return 1
/datum/computer_file/program/ui_interact(mob/user, datum/tgui/ui)
diff --git a/code/modules/modular_computers/file_system/program_events.dm b/code/modules/modular_computers/file_system/program_events.dm
index 3c1daa5af3..1cb74a227b 100644
--- a/code/modules/modular_computers/file_system/program_events.dm
+++ b/code/modules/modular_computers/file_system/program_events.dm
@@ -2,7 +2,7 @@
// Always include a parent call when overriding an event.
// Called when the ID card is removed from computer. ID is removed AFTER this proc.
-/datum/computer_file/program/proc/event_idremoved(background, slot)
+/datum/computer_file/program/proc/event_idremoved(background)
return
// Called when the computer fails due to power loss. Override when program wants to specifically react to power loss.
diff --git a/code/modules/modular_computers/file_system/programs/airestorer.dm b/code/modules/modular_computers/file_system/programs/airestorer.dm
index 364ad79737..7ae6dd203a 100644
--- a/code/modules/modular_computers/file_system/programs/airestorer.dm
+++ b/code/modules/modular_computers/file_system/programs/airestorer.dm
@@ -1,8 +1,8 @@
/datum/computer_file/program/aidiag
filename = "aidiag"
- filedesc = "AI Integrity Restorer"
+ filedesc = "NT FRK"
program_icon_state = "generic"
- extended_desc = "This program is capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot."
+ extended_desc = "Firmware Restoration Kit, capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot."
size = 12
requires_ntnet = FALSE
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
@@ -48,7 +48,7 @@
if(computer.all_components[MC_AI])
var/obj/item/computer_hardware/ai_slot/ai_slot = computer.all_components[MC_AI]
if(ai_slot && ai_slot.stored_card)
- ai_slot.try_eject(0,usr)
+ ai_slot.try_eject(usr)
return TRUE
/datum/computer_file/program/aidiag/process_tick()
@@ -71,14 +71,19 @@
ai_slot.locked = FALSE
restoring = FALSE
return
- ai_slot.locked =TRUE
+ ai_slot.locked = TRUE
A.adjustOxyLoss(-5, 0)//, FALSE)
A.adjustFireLoss(-5, 0)//, FALSE)
A.adjustToxLoss(-5, 0)
A.adjustBruteLoss(-5, 0)
+
+ // Please don't forget to update health, otherwise the below if statements will probably always fail.
A.updatehealth()
+
if(A.health >= 0 && A.stat == DEAD)
A.revive(full_heal = FALSE, admin_revive = FALSE)
+ cardhold.update_icon()
+
// Finished restoring
if(A.health >= 100)
ai_slot.locked = FALSE
diff --git a/code/modules/modular_computers/file_system/programs/alarm.dm b/code/modules/modular_computers/file_system/programs/alarm.dm
index 577fad83d0..55dea600e3 100644
--- a/code/modules/modular_computers/file_system/programs/alarm.dm
+++ b/code/modules/modular_computers/file_system/programs/alarm.dm
@@ -1,11 +1,10 @@
/datum/computer_file/program/alarm_monitor
filename = "alarmmonitor"
- filedesc = "Alarm Monitor"
+ filedesc = "Canary"
ui_header = "alarm_green.gif"
program_icon_state = "alert-green"
- extended_desc = "This program provides visual interface for station's alarm system."
+ extended_desc = "This program provides visual interface for a station's alarm system."
requires_ntnet = 1
- network_destination = "alarm monitoring network"
size = 5
tgui_id = "NtosStationAlertConsole"
var/has_alert = 0
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm b/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm
index 3accb8e02d..aa361d4544 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm
@@ -14,7 +14,7 @@
var/assigned = FALSE
var/first_load = TRUE
-/datum/computer_file/program/contract_uplink/run_program(var/mob/living/user)
+/datum/computer_file/program/contract_uplink/run_program(mob/living/user)
. = ..(user)
/datum/computer_file/program/contract_uplink/ui_act(action, params)
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
index 2ba3d69fe6..4f1c488b9e 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
@@ -10,7 +10,7 @@
tgui_id = "NtosRevelation"
var/armed = 0
-/datum/computer_file/program/revelation/run_program(var/mob/living/user)
+/datum/computer_file/program/revelation/run_program(mob/living/user)
. = ..(user)
if(armed)
activate()
diff --git a/code/modules/modular_computers/file_system/programs/arcade.dm b/code/modules/modular_computers/file_system/programs/arcade.dm
index 2503073f9a..87a3f1ec94 100644
--- a/code/modules/modular_computers/file_system/programs/arcade.dm
+++ b/code/modules/modular_computers/file_system/programs/arcade.dm
@@ -1,10 +1,9 @@
/datum/computer_file/program/arcade
- filename = "arcade"
- filedesc = "Nanotrasen Micro Arcade"
+ filename = "dsarcade"
+ filedesc = "Donksoft Micro Arcade"
program_icon_state = "arcade"
extended_desc = "This port of the classic game 'Outbomb Cuban Pete', redesigned to run on tablets, with thrilling graphics and chilling storytelling."
requires_ntnet = FALSE
- network_destination = "arcade network"
size = 6
tgui_id = "NtosArcade"
@@ -25,7 +24,7 @@
/datum/computer_file/program/arcade/proc/game_check(mob/user)
sleep(5)
- //user?.mind?.adjust_experience(/datum/skill/gaming, 1) No gaming(TM) Yet
+ // user?.mind?.adjust_experience(/datum/skill/gaming, 1)
if(boss_hp <= 0)
heads_up = "You have crushed [boss_name]! Rejoice!"
playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10)
@@ -34,7 +33,7 @@
if(istype(computer))
computer.update_icon()
ticket_count += 1
- //user?.mind?.adjust_experience(/datum/skill/gaming, 50)
+ // user?.mind?.adjust_experience(/datum/skill/gaming, 50)
sleep(10)
else if(player_hp <= 0 || player_mp <= 0)
heads_up = "You have been defeated... how will the station survive?"
@@ -43,7 +42,7 @@
program_icon_state = "arcade_off"
if(istype(computer))
computer.update_icon()
- //user?.mind?.adjust_experience(/datum/skill/gaming, 10)
+ // user?.mind?.adjust_experience(/datum/skill/gaming, 10)
sleep(10)
/datum/computer_file/program/arcade/proc/enemy_check(mob/user)
@@ -98,8 +97,8 @@
if(computer)
printer = computer.all_components[MC_PRINT]
- //var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming)
- //var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER)
+ // var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming)
+ // var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER)
switch(action)
if("Attack")
var/attackamt = 0 //Spam prevention.
@@ -119,8 +118,8 @@
if(pause_state == FALSE)
healamt = rand(6,8)// + rand(0, gamerSkill)
var/maxPointCost = 3
- //if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN)
- // maxPointCost = 2
+ // if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN)
+ // maxPointCost = 2
healcost = rand(1, maxPointCost)
pause_state = TRUE
heads_up = "You heal for [healamt] damage."
diff --git a/code/modules/modular_computers/file_system/programs/atmosscan.dm b/code/modules/modular_computers/file_system/programs/atmosscan.dm
index 2df751bebd..ebb2770f2e 100644
--- a/code/modules/modular_computers/file_system/programs/atmosscan.dm
+++ b/code/modules/modular_computers/file_system/programs/atmosscan.dm
@@ -1,29 +1,41 @@
/datum/computer_file/program/atmosscan
filename = "atmosscan"
- filedesc = "Atmospheric Scanner"
+ filedesc = "AtmoZphere"
program_icon_state = "air"
extended_desc = "A small built-in sensor reads out the atmospheric conditions around the device."
- network_destination = "atmos scan"
size = 4
tgui_id = "NtosAtmos"
+/datum/computer_file/program/atmosscan/run_program(mob/living/user)
+ . = ..()
+ if (!.)
+ return
+ if(!computer?.get_modular_computer_part(MC_SENSORS)) //Giving a clue to users why the program is spitting out zeros.
+ to_chat(user, "\The [computer] flashes an error: \"hardware\\sensorpackage\\startup.bin -- file not found\".")
+
+
/datum/computer_file/program/atmosscan/ui_data(mob/user)
var/list/data = get_header_data()
var/list/airlist = list()
var/turf/T = get_turf(ui_host())
- if(T)
+ var/obj/item/computer_hardware/sensorpackage/sensors = computer?.get_modular_computer_part(MC_SENSORS)
+ if(T && sensors?.check_functionality())
var/datum/gas_mixture/environment = T.return_air()
- var/list/env_gases = environment.get_gases()
+ var/list/env_gases = environment.gases
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
data["AirPressure"] = round(pressure,0.1)
- data["AirTemp"] = round(environment.return_temperature()-T0C)
+ data["AirTemp"] = round(environment.temperature-T0C)
if (total_moles)
for(var/id in env_gases)
- var/gas_level = environment.get_moles(id)/total_moles
+ var/gas_level = env_gases[id][MOLES]/total_moles
if(gas_level > 0)
- airlist += list(list("name" = "[GLOB.meta_gas_names[id]]", "percentage" = round(gas_level*100, 0.01)))
+ airlist += list(list("name" = "[env_gases[id][GAS_META][META_GAS_NAME]]", "percentage" = round(gas_level*100, 0.01)))
data["AirData"] = airlist
+ else
+ data["AirPressure"] = 0
+ data["AirTemp"] = 0
+ data["AirData"] = list(list())
return data
/datum/computer_file/program/atmosscan/ui_act(action, list/params)
diff --git a/code/modules/modular_computers/file_system/programs/borg_monitor.dm b/code/modules/modular_computers/file_system/programs/borg_monitor.dm
index c2160a0e92..d1bf7dbab3 100644
--- a/code/modules/modular_computers/file_system/programs/borg_monitor.dm
+++ b/code/modules/modular_computers/file_system/programs/borg_monitor.dm
@@ -1,12 +1,11 @@
/datum/computer_file/program/borg_monitor
- filename = "cyborgmonitor"
- filedesc = "Cyborg Remote Monitoring"
+ filename = "siliconnect"
+ filedesc = "SiliConnect"
ui_header = "borg_mon.gif"
program_icon_state = "generic"
extended_desc = "This program allows for remote monitoring of station cyborgs."
requires_ntnet = TRUE
transfer_access = ACCESS_ROBOTICS
- network_destination = "cyborg remote monitoring"
size = 5
tgui_id = "NtosCyborgRemoteMonitor"
@@ -81,8 +80,8 @@
return ID.registered_name
/datum/computer_file/program/borg_monitor/syndicate
- filename = "scyborgmonitor"
- filedesc = "Mission-Specific Cyborg Remote Monitoring"
+ filename = "roboverlord"
+ filedesc = "Roboverlord"
ui_header = "borg_mon.gif"
program_icon_state = "generic"
extended_desc = "This program allows for remote monitoring of mission-assigned cyborgs."
@@ -90,7 +89,6 @@
available_on_ntnet = FALSE
available_on_syndinet = TRUE
transfer_access = null
- network_destination = "cyborg remote monitoring"
tgui_id = "NtosCyborgRemoteMonitorSyndicate"
/datum/computer_file/program/borg_monitor/syndicate/evaluate_borg(mob/living/silicon/robot/R)
diff --git a/code/modules/modular_computers/file_system/programs/bounty_board.dm b/code/modules/modular_computers/file_system/programs/bounty_board.dm
index 46fde84f65..2e7d3cc87f 100644
--- a/code/modules/modular_computers/file_system/programs/bounty_board.dm
+++ b/code/modules/modular_computers/file_system/programs/bounty_board.dm
@@ -4,7 +4,6 @@
program_icon_state = "bountyboard"
extended_desc = "A multi-platform network for placing requests across the station, with payment across the network being possible.."
requires_ntnet = TRUE
- network_destination = "bounty board interface"
size = 10
tgui_id = "NtosRequestKiosk"
///Reference to the currently logged in user.
diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm
index 842d6e2588..6d45914add 100644
--- a/code/modules/modular_computers/file_system/programs/card.dm
+++ b/code/modules/modular_computers/file_system/programs/card.dm
@@ -7,8 +7,8 @@
#define CARDCON_DEPARTMENT_COMMAND "Command"
/datum/computer_file/program/card_mod
- filename = "cardmod"
- filedesc = "ID Card Modification"
+ filename = "plexagonidwriter"
+ filedesc = "Plexagon Access Management"
program_icon_state = "id"
extended_desc = "Program for programming employee ID cards to access parts of the station."
transfer_access = ACCESS_HEADS
@@ -98,17 +98,19 @@
return TRUE
var/obj/item/computer_hardware/card_slot/card_slot
+ var/obj/item/computer_hardware/card_slot/card_slot2
var/obj/item/computer_hardware/printer/printer
if(computer)
card_slot = computer.all_components[MC_CARD]
+ card_slot2 = computer.all_components[MC_CARD2]
printer = computer.all_components[MC_PRINT]
- if(!card_slot)
+ if(!card_slot || !card_slot2)
return
var/mob/user = usr
- var/obj/item/card/id/user_id_card = user.get_idcard(FALSE)
+ var/obj/item/card/id/user_id_card = card_slot.stored_card
- var/obj/item/card/id/id_card = card_slot.stored_card
+ var/obj/item/card/id/target_id_card = card_slot2.stored_card
switch(action)
if("PRG_authenticate")
@@ -129,14 +131,14 @@
return
var/contents = {"
Access Report
Prepared By: [user_id_card && user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]
- For: [id_card.registered_name ? id_card.registered_name : "Unregistered"]
+ For: [target_id_card.registered_name ? target_id_card.registered_name : "Unregistered"]
- Assignment: [id_card.assignment]
+ Assignment: [target_id_card.assignment]
Access:
"}
var/known_access_rights = get_all_accesses()
- for(var/A in id_card.access)
+ for(var/A in target_id_card.access)
if(A in known_access_rights)
contents += " [get_access_desc(A)]"
@@ -148,43 +150,40 @@
computer.visible_message("\The [computer] prints out a paper.")
return TRUE
if("PRG_eject")
- if(!computer || !card_slot)
+ if(!computer || !card_slot2)
return
- if(id_card)
- GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
- card_slot.try_eject(TRUE, user)
+ if(target_id_card)
+ GLOB.data_core.manifest_modify(target_id_card.registered_name, target_id_card.assignment)
+ return card_slot2.try_eject(user)
else
var/obj/item/I = user.get_active_held_item()
if(istype(I, /obj/item/card/id))
- if(!user.transferItemToLoc(I, computer))
- return
- card_slot.stored_card = I
- playsound(computer, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
- return TRUE
+ return card_slot2.try_insert(I)
+ return FALSE
if("PRG_terminate")
if(!computer || !authenticated)
return
if(minor)
- if(!(id_card.assignment in head_subordinates) && id_card.assignment != "Assistant")
+ if(!(target_id_card.assignment in head_subordinates) && target_id_card.assignment != "Assistant")
return
- id_card.access -= get_all_centcom_access() + get_all_accesses()
- id_card.assignment = "Unassigned"
- id_card.update_label()
+ target_id_card.access -= get_all_centcom_access() + get_all_accesses()
+ target_id_card.assignment = "Unassigned"
+ target_id_card.update_label()
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return TRUE
if("PRG_edit")
- if(!computer || !authenticated || !id_card)
+ if(!computer || !authenticated || !target_id_card)
return
var/new_name = params["name"]
if(!new_name)
return
- id_card.registered_name = new_name
- id_card.update_label()
+ target_id_card.registered_name = new_name
+ target_id_card.update_label()
playsound(computer, "terminal_type", 50, FALSE)
return TRUE
if("PRG_assign")
- if(!computer || !authenticated || !id_card)
+ if(!computer || !authenticated || !target_id_card)
return
var/target = params["assign_target"]
if(!target)
@@ -193,8 +192,8 @@
if(target == "Custom")
var/custom_name = params["custom_name"]
if(custom_name)
- id_card.assignment = custom_name
- id_card.update_label()
+ target_id_card.assignment = custom_name
+ target_id_card.update_label()
else
if(minor && !(target in head_subordinates))
return
@@ -212,10 +211,10 @@
to_chat(user, "No class exists for this job: [target]")
return
new_access = job.get_access()
- id_card.access -= get_all_centcom_access() + get_all_accesses()
- id_card.access |= new_access
- id_card.assignment = target
- id_card.update_label()
+ target_id_card.access -= get_all_centcom_access() + get_all_accesses()
+ target_id_card.access |= new_access
+ target_id_card.assignment = target
+ target_id_card.update_label()
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
if("PRG_access")
@@ -223,22 +222,22 @@
return
var/access_type = text2num(params["access_target"])
if(access_type in (is_centcom ? get_all_centcom_access() : get_all_accesses()))
- if(access_type in id_card.access)
- id_card.access -= access_type
+ if(access_type in target_id_card.access)
+ target_id_card.access -= access_type
else
- id_card.access |= access_type
+ target_id_card.access |= access_type
playsound(computer, "terminal_type", 50, FALSE)
return TRUE
if("PRG_grantall")
if(!computer || !authenticated || minor)
return
- id_card.access |= (is_centcom ? get_all_centcom_access() : get_all_accesses())
+ target_id_card.access |= (is_centcom ? get_all_centcom_access() : get_all_accesses())
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
if("PRG_denyall")
if(!computer || !authenticated || minor)
return
- id_card.access.Cut()
+ target_id_card.access.Cut()
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return TRUE
if("PRG_grantregion")
@@ -247,7 +246,7 @@
var/region = text2num(params["region"])
if(isnull(region))
return
- id_card.access |= get_region_accesses(region)
+ target_id_card.access |= get_region_accesses(region)
playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
return TRUE
if("PRG_denyregion")
@@ -256,7 +255,7 @@
var/region = text2num(params["region"])
if(isnull(region))
return
- id_card.access -= get_region_accesses(region)
+ target_id_card.access -= get_region_accesses(region)
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return TRUE
@@ -321,17 +320,17 @@
/datum/computer_file/program/card_mod/ui_data(mob/user)
var/list/data = get_header_data()
- var/obj/item/computer_hardware/card_slot/card_slot
+ var/obj/item/computer_hardware/card_slot/card_slot2
var/obj/item/computer_hardware/printer/printer
if(computer)
- card_slot = computer.all_components[MC_CARD]
+ card_slot2 = computer.all_components[MC_CARD2]
printer = computer.all_components[MC_PRINT]
data["station_name"] = station_name()
if(computer)
- data["have_id_slot"] = !!card_slot
+ data["have_id_slot"] = !!(card_slot2)
data["have_printer"] = !!printer
else
data["have_id_slot"] = FALSE
@@ -340,7 +339,7 @@
data["authenticated"] = authenticated
if(computer)
- var/obj/item/card/id/id_card = card_slot.stored_card
+ var/obj/item/card/id/id_card = card_slot2.stored_card
data["has_id"] = !!id_card
data["id_name"] = id_card ? id_card.name : "-----"
if(id_card)
diff --git a/code/modules/modular_computers/file_system/programs/cargobounty.dm b/code/modules/modular_computers/file_system/programs/cargobounty.dm
index d9bc65c98d..74ac44ade3 100644
--- a/code/modules/modular_computers/file_system/programs/cargobounty.dm
+++ b/code/modules/modular_computers/file_system/programs/cargobounty.dm
@@ -5,7 +5,6 @@
extended_desc = "A basic interface for supply personnel to check and claim bounties."
requires_ntnet = TRUE
transfer_access = ACCESS_CARGO
- network_destination = "cargo claims interface"
size = 10
tgui_id = "NtosBountyConsole"
///cooldown var for printing paper sheets.
diff --git a/code/modules/modular_computers/file_system/programs/cargoship.dm b/code/modules/modular_computers/file_system/programs/cargoship.dm
index 3ba08a3719..db8d6d9f82 100644
--- a/code/modules/modular_computers/file_system/programs/cargoship.dm
+++ b/code/modules/modular_computers/file_system/programs/cargoship.dm
@@ -1,9 +1,8 @@
/datum/computer_file/program/shipping
filename = "shipping"
- filedesc = "Nanotrasen Shipping Scanner"
+ filedesc = "GrandArk Exporter"
program_icon_state = "shipping"
extended_desc = "A combination printer/scanner app that enables modular computers to print barcodes for easy scanning and shipping."
- network_destination = "ship scanner"
size = 6
tgui_id = "NtosShipping"
///Account used for creating barcodes.
diff --git a/code/modules/modular_computers/file_system/programs/crewmanifest.dm b/code/modules/modular_computers/file_system/programs/crewmanifest.dm
index a1503ce3a8..4f2688d8f1 100644
--- a/code/modules/modular_computers/file_system/programs/crewmanifest.dm
+++ b/code/modules/modular_computers/file_system/programs/crewmanifest.dm
@@ -1,10 +1,10 @@
/datum/computer_file/program/crew_manifest
- filename = "crewmani"
- filedesc = "Crew Manifest"
+ filename = "plexagoncrew"
+ filedesc = "Plexagon Crew List"
program_icon_state = "id"
extended_desc = "Program for viewing and printing the current crew manifest"
transfer_access = ACCESS_HEADS
- requires_ntnet = FALSE
+ requires_ntnet = TRUE
size = 4
tgui_id = "NtosCrewManifest"
diff --git a/code/modules/modular_computers/file_system/programs/jobmanagement.dm b/code/modules/modular_computers/file_system/programs/jobmanagement.dm
index bccc6e4dbe..b88b793b66 100644
--- a/code/modules/modular_computers/file_system/programs/jobmanagement.dm
+++ b/code/modules/modular_computers/file_system/programs/jobmanagement.dm
@@ -1,10 +1,10 @@
/datum/computer_file/program/job_management
- filename = "job_manage"
- filedesc = "Job Manager"
+ filename = "plexagoncore"
+ filedesc = "Plexagon HR Core"
program_icon_state = "id"
extended_desc = "Program for viewing and changing job slot avalibility."
transfer_access = ACCESS_HEADS
- requires_ntnet = 0
+ requires_ntnet = TRUE
size = 4
tgui_id = "NtosJobManager"
diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm
index 6401d6207f..8fbcfd0b01 100644
--- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm
+++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm
@@ -1,14 +1,14 @@
/datum/computer_file/program/ntnetdownload
- filename = "ntndownloader"
- filedesc = "Software Download Tool"
+ filename = "ntsoftwarehub"
+ filedesc = "NT Software Hub"
program_icon_state = "generic"
extended_desc = "This program allows downloads of software from official NT repositories"
- unsendable = 1
- undeletable = 1
+ unsendable = TRUE
+ undeletable = TRUE
size = 4
- requires_ntnet = 1
+ requires_ntnet = TRUE
requires_ntnet_feature = NTNET_SOFTWAREDOWNLOAD
- available_on_ntnet = 0
+ available_on_ntnet = FALSE
ui_header = "downloader_finished.gif"
tgui_id = "NtosNetDownloader"
@@ -125,6 +125,8 @@
if(!istype(my_computer))
return
+ var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
+ var/list/access = card_slot?.GetAccess()
var/list/data = get_header_data()
@@ -146,7 +148,7 @@
for(var/A in main_repo)
var/datum/computer_file/program/P = A
// Only those programs our user can run will show in the list
- if(!P.can_run(user,transfer = 1) || hard_drive.find_file_by_name(P.filename))
+ if(!P.can_run(user,transfer = 1, access = access) || hard_drive.find_file_by_name(P.filename))
continue
all_entries.Add(list(list(
"filename" = P.filename,
diff --git a/code/modules/modular_computers/file_system/programs/ntmonitor.dm b/code/modules/modular_computers/file_system/programs/ntmonitor.dm
index 7d6d89f32c..bbbde14780 100644
--- a/code/modules/modular_computers/file_system/programs/ntmonitor.dm
+++ b/code/modules/modular_computers/file_system/programs/ntmonitor.dm
@@ -1,6 +1,6 @@
/datum/computer_file/program/ntnetmonitor
- filename = "ntmonitor"
- filedesc = "NTNet Diagnostics and Monitoring"
+ filename = "wirecarp"
+ filedesc = "WireCarp" //wireshark.
program_icon_state = "comm_monitor"
extended_desc = "This program monitors stationwide NTNet network, provides access to logging systems, and allows for configuration changes"
size = 12
diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
index df9b02d8ec..f03ff3f8fd 100644
--- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
+++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
@@ -6,7 +6,6 @@
size = 8
requires_ntnet = 1
requires_ntnet_feature = NTNET_COMMUNICATION
- network_destination = "NTNRC server"
ui_header = "ntnrc_idle.gif"
available_on_ntnet = 1
tgui_id = "NtosNetChat"
diff --git a/code/modules/modular_computers/file_system/programs/powermonitor.dm b/code/modules/modular_computers/file_system/programs/powermonitor.dm
index bd11474858..e87a731a40 100644
--- a/code/modules/modular_computers/file_system/programs/powermonitor.dm
+++ b/code/modules/modular_computers/file_system/programs/powermonitor.dm
@@ -1,15 +1,14 @@
//normal computer version is located in code\modules\power\monitor.dm, /obj/machinery/computer/monitor
/datum/computer_file/program/power_monitor
- filename = "powermonitor"
- filedesc = "Power Monitor"
+ filename = "ampcheck"
+ filedesc = "AmpCheck"
program_icon_state = "power_monitor"
extended_desc = "This program connects to sensors around the station to provide information about electrical systems"
ui_header = "power_norm.gif"
transfer_access = ACCESS_ENGINE
usage_flags = PROGRAM_CONSOLE
requires_ntnet = 0
- network_destination = "power monitoring system"
size = 9
tgui_id = "NtosPowerMonitor"
diff --git a/code/modules/modular_computers/file_system/programs/radar.dm b/code/modules/modular_computers/file_system/programs/radar.dm
index 9b0e09ef99..216365d6ea 100644
--- a/code/modules/modular_computers/file_system/programs/radar.dm
+++ b/code/modules/modular_computers/file_system/programs/radar.dm
@@ -7,7 +7,6 @@
transfer_access = null
available_on_ntnet = FALSE
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET
- network_destination = "tracking program"
size = 5
tgui_id = "NtosRadar"
///List of trackable entities. Updated by the scan() proc.
@@ -207,7 +206,7 @@
///A program that tracks crew members via suit sensors
/datum/computer_file/program/radar/lifeline
- filename = "Lifeline"
+ filename = "lifeline"
filedesc = "Lifeline"
extended_desc = "This program allows for tracking of crew members via their suit sensors."
requires_ntnet = TRUE
@@ -252,9 +251,9 @@
//Nuke Disk Finder App//
////////////////////////
-///A program that tracks crew members via suit sensors
+///A program that tracks nukes and nuclear accessories
/datum/computer_file/program/radar/fission360
- filename = "Fission360"
+ filename = "fission360"
filedesc = "Fission360"
program_icon_state = "radarsyndicate"
extended_desc = "This program allows for tracking of nuclear authorization disks and warheads."
@@ -276,8 +275,6 @@
objects = list()
for(var/i in GLOB.nuke_list)
var/obj/machinery/nuclearbomb/nuke = i
- if(!trackable(nuke))
- continue
var/list/nukeinfo = list(
ref = REF(nuke),
@@ -285,9 +282,8 @@
)
objects += list(nukeinfo)
var/obj/item/disk/nuclear/disk = locate() in GLOB.poi_list
- if(trackable(disk))
- var/list/nukeinfo = list(
- ref = REF(disk),
- name = disk.name,
- )
- objects += list(nukeinfo)
+ var/list/nukeinfo = list(
+ ref = REF(disk),
+ name = "Nuke Auth. Disk",
+ )
+ objects += list(nukeinfo)
diff --git a/code/modules/modular_computers/file_system/programs/robocontrol.dm b/code/modules/modular_computers/file_system/programs/robocontrol.dm
index 8644ce09b4..c0b82b9c95 100644
--- a/code/modules/modular_computers/file_system/programs/robocontrol.dm
+++ b/code/modules/modular_computers/file_system/programs/robocontrol.dm
@@ -1,12 +1,11 @@
/datum/computer_file/program/robocontrol
- filename = "robocontrol"
- filedesc = "Bot Remote Controller"
+ filename = "botkeeper"
+ filedesc = "Botkeeper"
program_icon_state = "robot"
extended_desc = "A remote controller used for giving basic commands to non-sentient robots."
transfer_access = ACCESS_ROBOTICS
requires_ntnet = TRUE
- network_destination = "robotics control network"
size = 12
tgui_id = "NtosRoboControl"
///Number of simple robots on-station.
@@ -78,7 +77,7 @@
return
if(id_card)
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
- card_slot.try_eject(TRUE, current_user)
+ card_slot.try_eject(current_user)
else
playsound(get_turf(ui_host()) , 'sound/machines/buzz-sigh.ogg', 25, FALSE)
return
diff --git a/code/modules/modular_computers/file_system/programs/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/sm_monitor.dm
index 32ad102871..564f952b54 100644
--- a/code/modules/modular_computers/file_system/programs/sm_monitor.dm
+++ b/code/modules/modular_computers/file_system/programs/sm_monitor.dm
@@ -1,12 +1,11 @@
/datum/computer_file/program/supermatter_monitor
- filename = "smmonitor"
- filedesc = "Supermatter Monitoring"
+ filename = "ntcims"
+ filedesc = "NT CIMS"
ui_header = "smmon_0.gif"
program_icon_state = "smmon_0"
- extended_desc = "This program connects to specially calibrated supermatter sensors to provide information on the status of supermatter-based engines."
+ extended_desc = "Crystal Integrity Monitoring System, connects to specially calibrated supermatter sensors to provide information on the status of supermatter-based engines."
requires_ntnet = TRUE
transfer_access = ACCESS_CONSTRUCTION
- network_destination = "supermatter monitoring system"
size = 5
tgui_id = "NtosSupermatterMonitor"
var/last_status = SUPERMATTER_INACTIVE
@@ -70,7 +69,7 @@
data["active"] = TRUE
data["SM_integrity"] = active.get_integrity()
data["SM_power"] = active.power
- data["SM_ambienttemp"] = air.return_temperature()
+ data["SM_ambienttemp"] = air.temperature
data["SM_ambientpressure"] = air.return_pressure()
//data["SM_EPR"] = round((air.total_moles / air.group_multiplier) / 23.1, 0.01)
var/list/gasdata = list()
diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm
index b33442f99b..81555340b2 100644
--- a/code/modules/modular_computers/hardware/_hardware.dm
+++ b/code/modules/modular_computers/hardware/_hardware.dm
@@ -10,9 +10,11 @@
// Computer that holds this hardware, if any.
var/power_usage = 0 // If the hardware uses extra power, change this.
- var/enabled = 1 // If the hardware is turned off set this to 0.
- var/critical = 0 // Prevent disabling for important component, like the CPU.
- var/can_install = 1 // Prevents direct installation of removable media.
+ var/enabled = TRUE // If the hardware is turned off set this to 0.
+ var/critical = FALSE // Prevent disabling for important component, like the CPU.
+ var/can_install = TRUE // Prevents direct installation of removable media.
+ var/expansion_hw = FALSE // Hardware that fits into expansion bays.
+ var/removable = TRUE // Whether the hardware is removable or not.
var/damage = 0 // Current damage level
var/max_damage = 100 // Maximal damage level.
var/damage_malfunction = 20 // "Malfunction" threshold. When damage exceeds this value the hardware piece will semi-randomly fail and do !!FUN!! things
@@ -20,7 +22,7 @@
var/malfunction_probability = 10// Chance of malfunction when the component is damaged
var/device_type
-/obj/item/computer_hardware/New(var/obj/L)
+/obj/item/computer_hardware/New(obj/L)
..()
pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
@@ -56,7 +58,7 @@
return TRUE
// Called on multitool click, prints diagnostic information to the user.
-/obj/item/computer_hardware/proc/diagnostics(var/mob/user)
+/obj/item/computer_hardware/proc/diagnostics(mob/user)
to_chat(user, "Hardware Integrity Test... (Corruption: [damage]/[max_damage]) [damage > damage_failure ? "FAIL" : damage > damage_malfunction ? "WARN" : "PASS"]")
// Handles damage checks
@@ -73,7 +75,7 @@
return TRUE // Good to go.
-/obj/item/computer_hardware/examine(var/mob/user)
+/obj/item/computer_hardware/examine(mob/user)
. = ..()
if(damage > damage_failure)
. += "It seems to be severely damaged!"
diff --git a/code/modules/modular_computers/hardware/ai_slot.dm b/code/modules/modular_computers/hardware/ai_slot.dm
index 0ad157afcb..c874d786a0 100644
--- a/code/modules/modular_computers/hardware/ai_slot.dm
+++ b/code/modules/modular_computers/hardware/ai_slot.dm
@@ -5,6 +5,7 @@
icon_state = "card_mini"
w_class = WEIGHT_CLASS_SMALL
device_type = MC_AI
+ expansion_hw = TRUE
var/obj/item/aicard/stored_card = null
var/locked = FALSE
@@ -19,12 +20,6 @@
if(stored_card)
. += "There appears to be an intelliCard loaded. There appears to be a pinhole protecting a manual eject button. A screwdriver could probably press it."
-/obj/item/computer_hardware/ai_slot/on_install(obj/item/modular_computer/M, mob/living/user = null)
- M.add_verb(device_type)
-
-/obj/item/computer_hardware/ai_slot/on_remove(obj/item/modular_computer/M, mob/living/user = null)
- M.remove_verb(device_type)
-
/obj/item/computer_hardware/ai_slot/try_insert(obj/item/I, mob/living/user = null)
if(!holder)
return FALSE
@@ -44,7 +39,7 @@
return TRUE
-/obj/item/computer_hardware/ai_slot/try_eject(slot=0,mob/living/user = null,forced = 0)
+/obj/item/computer_hardware/ai_slot/try_eject(mob/living/user = null,forced = FALSE)
if(!stored_card)
to_chat(user, "There is no card in \the [src].")
return FALSE
diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm
index 6e3193abfd..0668248315 100644
--- a/code/modules/modular_computers/hardware/battery_module.dm
+++ b/code/modules/modular_computers/hardware/battery_module.dm
@@ -21,7 +21,7 @@
/obj/item/computer_hardware/battery/handle_atom_del(atom/A)
if(A == battery)
- try_eject(0, null, TRUE)
+ try_eject(forced = TRUE)
. = ..()
/obj/item/computer_hardware/battery/try_insert(obj/item/I, mob/living/user = null)
@@ -48,7 +48,7 @@
return TRUE
-/obj/item/computer_hardware/battery/try_eject(slot=0, mob/living/user = null, forced = 0)
+/obj/item/computer_hardware/battery/try_eject(mob/living/user = null, forced = FALSE)
if(!battery)
to_chat(user, "There is no power cell connected to \the [src].")
return FALSE
diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm
index 18b423a42e..c243bf7db1 100644
--- a/code/modules/modular_computers/hardware/card_slot.dm
+++ b/code/modules/modular_computers/hardware/card_slot.dm
@@ -7,13 +7,10 @@
device_type = MC_CARD
var/obj/item/card/id/stored_card = null
- var/obj/item/card/id/stored_card2 = null
/obj/item/computer_hardware/card_slot/handle_atom_del(atom/A)
if(A == stored_card)
- try_eject(1, null, TRUE)
- if(A == stored_card2)
- try_eject(2, null, TRUE)
+ try_eject(null, TRUE)
. = ..()
/obj/item/computer_hardware/card_slot/Destroy()
@@ -21,37 +18,25 @@
return ..()
/obj/item/computer_hardware/card_slot/GetAccess()
- if(stored_card && stored_card2) // Best of both worlds
- return (stored_card.GetAccess() | stored_card2.GetAccess())
- else if(stored_card)
- return stored_card.GetAccess()
- else if(stored_card2)
- return stored_card2.GetAccess()
- return ..()
+ var/list/total_access
+ if(stored_card)
+ total_access = stored_card.GetAccess()
+ var/obj/item/computer_hardware/card_slot/card_slot2 = holder?.all_components[MC_CARD2] //Best of both worlds
+ if(card_slot2?.stored_card)
+ total_access |= card_slot2.stored_card.GetAccess()
+ return total_access
/obj/item/computer_hardware/card_slot/GetID()
if(stored_card)
return stored_card
- else if(stored_card2)
- return stored_card2
return ..()
/obj/item/computer_hardware/card_slot/RemoveID()
if(stored_card)
. = stored_card
- if(!try_eject(1))
+ if(!try_eject())
return null
return
- if(stored_card2)
- . = stored_card2
- if(!try_eject(2))
- return null
-
-/obj/item/computer_hardware/card_slot/on_install(obj/item/modular_computer/M, mob/living/user = null)
- M.add_verb(device_type)
-
-/obj/item/computer_hardware/card_slot/on_remove(obj/item/modular_computer/M, mob/living/user = null)
- M.remove_verb(device_type)
/obj/item/computer_hardware/card_slot/try_insert(obj/item/I, mob/living/user = null)
if(!holder)
@@ -60,8 +45,7 @@
if(!istype(I, /obj/item/card/id))
return FALSE
- if(stored_card && stored_card2)
- to_chat(user, "You try to insert \the [I] into \the [src], but its slots are occupied.")
+ if(stored_card)
return FALSE
if(user)
if(!user.transferItemToLoc(I, src))
@@ -69,11 +53,8 @@
else
I.forceMove(src)
- if(!stored_card)
- stored_card = I
- else
- stored_card2 = I
- to_chat(user, "You insert \the [I] into \the [src].")
+ stored_card = I
+ to_chat(user, "You insert \the [I] into \the [expansion_hw ? "secondary":"primary"] [src].")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
if(ishuman(user))
var/mob/living/carbon/human/H = user
@@ -82,53 +63,58 @@
return TRUE
-/obj/item/computer_hardware/card_slot/try_eject(slot=0, mob/living/user = null, forced = 0)
- if(!stored_card && !stored_card2)
+/obj/item/computer_hardware/card_slot/try_eject(mob/living/user = null, forced = FALSE)
+ if(!stored_card)
to_chat(user, "There are no cards in \the [src].")
return FALSE
- var/ejected = 0
- if(stored_card && (!slot || slot == 1))
- if(user)
- user.put_in_hands(stored_card)
- else
- stored_card.forceMove(drop_location())
- stored_card = null
- ejected++
+ if(user)
+ user.put_in_hands(stored_card)
+ else
+ stored_card.forceMove(drop_location())
+ stored_card = null
- if(stored_card2 && (!slot || slot == 2))
- if(user)
- user.put_in_hands(stored_card2)
- else
- stored_card2.forceMove(drop_location())
- stored_card2 = null
- ejected++
+ if(holder)
+ if(holder.active_program)
+ holder.active_program.event_idremoved(0)
- if(ejected)
- if(holder)
- if(holder.active_program)
- holder.active_program.event_idremoved(0, slot)
-
- for(var/I in holder.idle_threads)
- var/datum/computer_file/program/P = I
- P.event_idremoved(1, slot)
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- H.sec_hud_set_ID()
- to_chat(user, "You remove the card[ejected>1 ? "s" : ""] from \the [src].")
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
- return TRUE
- return FALSE
+ for(var/p in holder.idle_threads)
+ var/datum/computer_file/program/computer_program = p
+ computer_program.event_idremoved(1)
+ if(ishuman(user))
+ var/mob/living/carbon/human/human_user = user
+ human_user.sec_hud_set_ID()
+ to_chat(user, "You remove the card from \the [src].")
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
+ return TRUE
/obj/item/computer_hardware/card_slot/attackby(obj/item/I, mob/living/user)
if(..())
return
if(I.tool_behaviour == TOOL_SCREWDRIVER)
- to_chat(user, "You press down on the manual eject button with \the [I].")
- try_eject(0,user)
- return
+ if(stored_card)
+ to_chat(user, "You press down on the manual eject button with \the [I].")
+ try_eject(user)
+ return
+ swap_slot()
+ to_chat(user, "You adjust the connecter to fit into [expansion_hw ? "an expansion bay" : "the primary ID bay"].")
+
+/**
+ *Swaps the card_slot hardware between using the dedicated card slot bay on a computer, and using an expansion bay.
+*/
+/obj/item/computer_hardware/card_slot/proc/swap_slot()
+ expansion_hw = !expansion_hw
+ if(expansion_hw)
+ device_type = MC_CARD2
+ else
+ device_type = MC_CARD
/obj/item/computer_hardware/card_slot/examine(mob/user)
. = ..()
- if(stored_card || stored_card2)
+ . += "The connector is set to fit into [expansion_hw ? "an expansion bay" : "a computer's primary ID bay"], but can be adjusted with a screwdriver."
+ if(stored_card)
. += "There appears to be something loaded in the card slots."
+
+/obj/item/computer_hardware/card_slot/secondary
+ device_type = MC_CARD2
+ expansion_hw = TRUE
diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm
index b8b9624388..e5c133de20 100644
--- a/code/modules/modular_computers/hardware/hard_drive.dm
+++ b/code/modules/modular_computers/hardware/hard_drive.dm
@@ -22,14 +22,14 @@
. = ..()
. += "It has [max_capacity] GQ of storage capacity."
-/obj/item/computer_hardware/hard_drive/diagnostics(var/mob/user)
+/obj/item/computer_hardware/hard_drive/diagnostics(mob/user)
..()
// 999 is a byond limit that is in place. It's unlikely someone will reach that many files anyway, since you would sooner run out of space.
to_chat(user, "NT-NFS File Table Status: [stored_files.len]/999")
to_chat(user, "Storage capacity: [used_capacity]/[max_capacity]GQ")
// Use this proc to add file to the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks.
-/obj/item/computer_hardware/hard_drive/proc/store_file(var/datum/computer_file/F)
+/obj/item/computer_hardware/hard_drive/proc/store_file(datum/computer_file/F)
if(!F || !istype(F))
return 0
@@ -52,7 +52,7 @@
return 1
// Use this proc to remove file from the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks.
-/obj/item/computer_hardware/hard_drive/proc/remove_file(var/datum/computer_file/F)
+/obj/item/computer_hardware/hard_drive/proc/remove_file(datum/computer_file/F)
if(!F || !istype(F))
return 0
@@ -78,7 +78,7 @@
used_capacity = total_size
// Checks whether file can be stored on the hard drive. We can only store unique files, so this checks whether we wouldn't get a duplicity by adding a file.
-/obj/item/computer_hardware/hard_drive/proc/can_store_file(var/datum/computer_file/F)
+/obj/item/computer_hardware/hard_drive/proc/can_store_file(datum/computer_file/F)
if(!F || !istype(F))
return 0
@@ -101,7 +101,7 @@
// Tries to find the file by filename. Returns null on failure
-/obj/item/computer_hardware/hard_drive/proc/find_file_by_name(var/filename)
+/obj/item/computer_hardware/hard_drive/proc/find_file_by_name(filename)
if(!check_functionality())
return null
diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm
index fe1b1879cb..04bf494fe4 100644
--- a/code/modules/modular_computers/hardware/network_card.dm
+++ b/code/modules/modular_computers/hardware/network_card.dm
@@ -11,7 +11,7 @@
device_type = MC_NET
var/static/ntnet_card_uid = 1
-/obj/item/computer_hardware/network_card/diagnostics(var/mob/user)
+/obj/item/computer_hardware/network_card/diagnostics(mob/user)
..()
to_chat(user, "NIX Unique ID: [identification_id]")
to_chat(user, "NIX User Tag: [identification_string]")
@@ -22,7 +22,7 @@
if(ethernet)
to_chat(user, "OpenEth (Physical Connection) - Physical network connection port")
-/obj/item/computer_hardware/network_card/New(var/l)
+/obj/item/computer_hardware/network_card/New(l)
..()
identification_id = ntnet_card_uid++
@@ -31,7 +31,7 @@
return "[identification_string] (NID [identification_id])"
// 0 - No signal, 1 - Low signal, 2 - High signal. 3 - Wired Connection
-/obj/item/computer_hardware/network_card/proc/get_signal(var/specific_action = 0)
+/obj/item/computer_hardware/network_card/proc/get_signal(specific_action = 0)
if(!holder) // Hardware is not installed in anything. No signal. How did this even get called?
return 0
diff --git a/code/modules/modular_computers/hardware/portable_disk.dm b/code/modules/modular_computers/hardware/portable_disk.dm
index b5a957be04..89b0382e86 100644
--- a/code/modules/modular_computers/hardware/portable_disk.dm
+++ b/code/modules/modular_computers/hardware/portable_disk.dm
@@ -8,12 +8,8 @@
max_capacity = 16
device_type = MC_SDD
-/obj/item/computer_hardware/hard_drive/portable/on_install(obj/item/modular_computer/M, mob/living/user = null)
- M.add_verb(device_type)
-
-/obj/item/computer_hardware/hard_drive/portable/on_remove(obj/item/modular_computer/M, mob/living/user = null)
- ..()
- M.remove_verb(device_type)
+/obj/item/computer_hardware/hard_drive/portable/on_remove(obj/item/modular_computer/MC, mob/user)
+ return //this is a floppy disk, let's not shut the computer down when it gets pulled out.
/obj/item/computer_hardware/hard_drive/portable/install_default_programs()
return // Empty by default
diff --git a/code/modules/modular_computers/hardware/printer.dm b/code/modules/modular_computers/hardware/printer.dm
index ebe40c1922..3bd5946435 100644
--- a/code/modules/modular_computers/hardware/printer.dm
+++ b/code/modules/modular_computers/hardware/printer.dm
@@ -5,6 +5,7 @@
icon_state = "printer"
w_class = WEIGHT_CLASS_NORMAL
device_type = MC_PRINT
+ expansion_hw = TRUE
var/stored_paper = 20
var/max_paper = 30
diff --git a/code/modules/modular_computers/hardware/sensor_package.dm b/code/modules/modular_computers/hardware/sensor_package.dm
new file mode 100644
index 0000000000..c0363bc809
--- /dev/null
+++ b/code/modules/modular_computers/hardware/sensor_package.dm
@@ -0,0 +1,8 @@
+//This item doesn't do much on its own, but is required by apps such as AtmoZphere.
+/obj/item/computer_hardware/sensorpackage
+ name = "sensor package"
+ desc = "An integrated sensor package allowing a computer to take readings from the environment. Required by certain programs."
+ icon_state = "servo"
+ w_class = WEIGHT_CLASS_TINY
+ device_type = MC_SENSORS
+ expansion_hw = TRUE
diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm
index a8d30bad21..a3b34c4b9b 100644
--- a/code/modules/modular_computers/laptop_vendor.dm
+++ b/code/modules/modular_computers/laptop_vendor.dm
@@ -52,6 +52,7 @@
var/obj/item/computer_hardware/battery/battery_module = null
if(fabricate)
fabricated_laptop = new /obj/item/modular_computer/laptop/buildable(src)
+ fabricated_laptop.install_component(new /obj/item/computer_hardware/card_slot)
fabricated_laptop.install_component(new /obj/item/computer_hardware/battery)
battery_module = fabricated_laptop.all_components[MC_CELL]
total_price = 99
@@ -107,7 +108,7 @@
if(dev_card)
total_price += 199
if(fabricate)
- fabricated_laptop.install_component(new /obj/item/computer_hardware/card_slot)
+ fabricated_laptop.install_component(new /obj/item/computer_hardware/card_slot/secondary)
return total_price
else if(devtype == 2) // Tablet, more expensive, not everyone could probably afford this.
@@ -116,6 +117,7 @@
fabricated_tablet = new(src)
fabricated_tablet.install_component(new /obj/item/computer_hardware/battery)
fabricated_tablet.install_component(new /obj/item/computer_hardware/processor_unit/small)
+ fabricated_tablet.install_component(new/obj/item/computer_hardware/card_slot)
battery_module = fabricated_tablet.all_components[MC_CELL]
total_price = 199
switch(dev_battery)
@@ -154,11 +156,11 @@
if(dev_printer)
total_price += 99
if(fabricate)
- fabricated_tablet.install_component(new/obj/item/computer_hardware/printer)
+ fabricated_tablet.install_component(new/obj/item/computer_hardware/printer/mini)
if(dev_card)
total_price += 199
if(fabricate)
- fabricated_tablet.install_component(new/obj/item/computer_hardware/card_slot)
+ fabricated_tablet.install_component(new/obj/item/computer_hardware/card_slot/secondary)
return total_price
return FALSE
@@ -222,7 +224,7 @@
return FALSE
/obj/machinery/lapvend/ui_interact(mob/user, datum/tgui/ui)
- if(stat & (BROKEN | NOPOWER | MAINT))
+ if(machine_stat & (BROKEN | NOPOWER | MAINT))
if(ui)
ui.close()
return FALSE
@@ -257,7 +259,7 @@
say("Insufficient credits on card to purchase!")
return
credits += target_credits
- say("[target_credits] cr has been deposited from your account.")
+ say("[target_credits] cr have been withdrawn from your account.")
return
return ..()
diff --git a/code/modules/paperwork/carbonpaper.dm b/code/modules/paperwork/carbonpaper.dm
new file mode 100644
index 0000000000..dc8f172069
--- /dev/null
+++ b/code/modules/paperwork/carbonpaper.dm
@@ -0,0 +1,45 @@
+/obj/item/paper/carbon
+ name = "sheet of carbon"
+ icon_state = "paper_stack"
+ item_state = "paper"
+ // inhand_icon_state = "paper"
+ show_written_words = FALSE
+ var/copied = FALSE
+ var/iscopy = FALSE
+
+/obj/item/paper/carbon/update_icon_state()
+ if(iscopy)
+ icon_state = "cpaper"
+ else if(copied)
+ icon_state = "paper"
+ else
+ icon_state = "paper_stack"
+ if(info)
+ icon_state = "[icon_state]_words"
+
+/obj/item/paper/carbon/proc/removecopy(mob/living/user)
+ if(!copied)
+ var/obj/item/paper/carbon/C = src
+ var/copycontents = C.info
+ var/obj/item/paper/carbon/Copy = new /obj/item/paper/carbon(user.loc)
+
+ if(info)
+ copycontents = replacetext(copycontents, ""
+ Copy.name = "Copy - [C.name]"
+ to_chat(user, "You tear off the carbon-copy!")
+ C.copied = TRUE
+ Copy.iscopy = TRUE
+ Copy.update_icon_state()
+ C.update_icon_state()
+ user.put_in_hands(Copy)
+ else
+ to_chat(user, "There are no more carbon copies attached to this paper!")
+
+/obj/item/paper/carbon/on_attack_hand(mob/living/user)
+ if(loc == user && user.is_holding(src))
+ removecopy(user)
+ return
+ return ..()
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index 1a93661c76..5b576a2438 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -3,6 +3,8 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "clipboard"
item_state = "clipboard"
+ // inhand_icon_state = "clipboard"
+ // worn_icon_state = "clipboard"
throwforce = 0
w_class = WEIGHT_CLASS_SMALL
throw_speed = 3
@@ -34,7 +36,6 @@
. += "clipboard_pen"
. += "clipboard_over"
-
/obj/item/clipboard/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/paper))
if(!user.transferItemToLoc(W, src))
@@ -92,14 +93,14 @@
to_chat(usr, "You slot [W] into [src].")
if(href_list["write"])
- var/obj/item/P = locate(href_list["write"])
- if(istype(P) && P.loc == src)
+ var/obj/item/P = locate(href_list["write"]) in src
+ if(istype(P))
if(usr.get_active_held_item())
P.attackby(usr.get_active_held_item(), usr)
if(href_list["remove"])
- var/obj/item/P = locate(href_list["remove"])
- if(istype(P) && P.loc == src)
+ var/obj/item/P = locate(href_list["remove"]) in src
+ if(istype(P))
P.forceMove(usr.loc)
usr.put_in_hands(P)
if(P == toppaper)
@@ -111,13 +112,13 @@
toppaper = null
if(href_list["read"])
- var/obj/item/paper/P = locate(href_list["read"])
- if(istype(P) && P.loc == src)
+ var/obj/item/paper/P = locate(href_list["read"]) in src
+ if(istype(P))
usr.examinate(P)
if(href_list["top"])
- var/obj/item/P = locate(href_list["top"])
- if(istype(P) && P.loc == src)
+ var/obj/item/P = locate(href_list["top"]) in src
+ if(istype(P))
toppaper = P
to_chat(usr, "You move [P.name] to the top.")
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index b8f2c95762..390cd0cf83 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -35,7 +35,7 @@
. = ..()
if(mapload)
for(var/obj/item/I in loc)
- if(istype(I, /obj/item/paper) || istype(I, /obj/item/folder) || istype(I, /obj/item/photo))
+ if(I.w_class < WEIGHT_CLASS_NORMAL) //there probably shouldn't be anything placed ontop of filing cabinets in a map that isn't meant to go in them
I.forceMove(src)
/obj/structure/filingcabinet/deconstruct(disassembled = TRUE)
@@ -46,7 +46,12 @@
qdel(src)
/obj/structure/filingcabinet/attackby(obj/item/P, mob/user, params)
- if(istype(P, /obj/item/paper) || istype(P, /obj/item/folder) || istype(P, /obj/item/photo) || istype(P, /obj/item/documents))
+ if(P.tool_behaviour == TOOL_WRENCH && user.a_intent != INTENT_HELP)
+ to_chat(user, "You begin to [anchored ? "unwrench" : "wrench"] [src].")
+ if(P.use_tool(src, user, 20, volume=50))
+ to_chat(user, "You successfully [anchored ? "unwrench" : "wrench"] [src].")
+ anchored = !anchored
+ else if(P.w_class < WEIGHT_CLASS_NORMAL)
if(!user.transferItemToLoc(P, src))
return
to_chat(user, "You put [P] in [src].")
@@ -54,11 +59,6 @@
sleep(5)
icon_state = initial(icon_state)
updateUsrDialog()
- else if(istype(P, /obj/item/wrench))
- to_chat(user, "You begin to [anchored ? "unwrench" : "wrench"] [src].")
- if(P.use_tool(src, user, 20, volume=50))
- to_chat(user, "You successfully [anchored ? "unwrench" : "wrench"] [src].")
- anchored = !anchored
else if(user.a_intent != INTENT_HARM)
to_chat(user, "You can't put [P] in [src]!")
else
@@ -67,9 +67,6 @@
/obj/structure/filingcabinet/ui_interact(mob/user)
. = ..()
- if(isobserver(user))
- return
-
if(contents.len <= 0)
to_chat(user, "[src] is empty.")
return
@@ -100,16 +97,17 @@
to_chat(user, "You find nothing in [src].")
/obj/structure/filingcabinet/Topic(href, href_list)
+ if(!usr.canUseTopic(src, BE_CLOSE, ismonkey(usr)))
+ return
if(href_list["retrieve"])
usr << browse("", "window=filingcabinet") // Close the menu
- var/obj/item/P = locate(href_list["retrieve"])//contents[retrieveindex]
- if(istype(P) && P.loc == src && in_range(src, usr))
+ var/obj/item/P = locate(href_list["retrieve"]) in src //contents[retrieveindex]
+ if(istype(P) && in_range(src, usr))
usr.put_in_hands(P)
updateUsrDialog()
icon_state = "[initial(icon_state)]-open"
- sleep(5)
- icon_state = initial(icon_state)
+ addtimer(VARSET_CALLBACK(src, icon_state, initial(icon_state)), 5)
/*
@@ -170,6 +168,7 @@
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
+//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/structure/filingcabinet/medical/on_attack_hand()
populate()
. = ..()
diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm
index c32afab342..305099d115 100644
--- a/code/modules/paperwork/folders.dm
+++ b/code/modules/paperwork/folders.dm
@@ -33,7 +33,10 @@
if(contents.len)
. += "folder_paper"
+
/obj/item/folder/attackby(obj/item/W, mob/user, params)
+ if(burn_paper_product_attackby_check(W, user))
+ return
if(istype(W, /obj/item/paper) || istype(W, /obj/item/photo) || istype(W, /obj/item/documents))
if(!user.transferItemToLoc(W, src))
return
@@ -43,11 +46,14 @@
if(!user.is_literate())
to_chat(user, "You scribble illegibly on the cover of [src]!")
return
+
var/inputvalue = stripped_input(user, "What would you like to label the folder?", "Folder Labelling", "", MAX_NAME_LEN)
+
if(!inputvalue)
return
+
if(user.canUseTopic(src, BE_CLOSE))
- name = "folder - '[inputvalue]'"
+ name = "folder[(inputvalue ? " - '[inputvalue]'" : null)]"
/obj/item/folder/Destroy()
@@ -76,14 +82,14 @@
if(usr.contents.Find(src))
if(href_list["remove"])
- var/obj/item/I = locate(href_list["remove"])
- if(istype(I) && I.loc == src)
+ var/obj/item/I = locate(href_list["remove"]) in src
+ if(istype(I))
I.forceMove(usr.loc)
usr.put_in_hands(I)
if(href_list["read"])
- var/obj/item/I = locate(href_list["read"])
- if(istype(I) && I.loc == src)
+ var/obj/item/I = locate(href_list["read"]) in src
+ if(istype(I))
usr.examinate(I)
//Update everything
diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm
index d054e5ff12..da9fdc4ca4 100644
--- a/code/modules/paperwork/handlabeler.dm
+++ b/code/modules/paperwork/handlabeler.dm
@@ -1,9 +1,10 @@
/obj/item/hand_labeler
name = "hand labeler"
- desc = "A combined label printer and applicator in a portable device, designed to be easy to operate and use."
+ desc = "A combined label printer, applicator, and remover, all in a single portable device. Designed to be easy to operate and use."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "labeler0"
item_state = "flight"
+ // inhand_icon_state = "flight"
var/label = null
var/labels_left = 30
var/mode = 0
@@ -55,9 +56,10 @@
to_chat(user, "You can't label creatures!") // use a collar
return
- user.visible_message("[user] labels [A] as [label].", \
- "You label [A] as [label].")
- A.name = "[A.name] ([label])"
+ user.visible_message("[user] labels [A] with \"[label]\".", \
+ "You label [A] with \"[label]\".")
+ A.AddComponent(/datum/component/label, label)
+ // playsound(A, 'sound/items/handling/component_pickup.ogg', 20, TRUE)
labels_left--
@@ -90,7 +92,9 @@
name = "cyborg-hand labeler"
/obj/item/hand_labeler/borg/afterattack(atom/A, mob/user, proximity)
- . = ..(A, user, proximity)
+ . = ..()
+ if(!proximity)
+ return
if(!iscyborg(user))
return
@@ -114,6 +118,7 @@
desc = "A roll of paper. Use it on a hand labeler to refill it."
icon_state = "labeler_refill"
item_state = "electropack"
+ // inhand_icon_state = "electropack"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
w_class = WEIGHT_CLASS_TINY
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 5d842ef11a..20ec678e45 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -11,41 +11,6 @@
#define MODE_WRITING 1
#define MODE_STAMPING 2
-/**
- * This is a custom ui state. All it really does is keep track of pen
- * being used and if they are editing it or not. This way we can keep
- * the data with the ui rather than on the paper
- */
-/datum/ui_state/default/paper_state
- /// What edit mode we are in and who is
- /// writing on it right now
- var/edit_mode = MODE_READING
- /// Setup for writing to a sheet
- var/pen_color = "black"
- var/pen_font = ""
- var/is_crayon = FALSE
- /// Setup for stamping a sheet
- // Why not the stamp obj? I have no idea
- // what happens to states out of scope so
- // don't want to put instances in this
- var/stamp_icon_state = ""
- var/stamp_name = ""
- var/stamp_class = ""
-
-/datum/ui_state/default/paper_state/proc/copy_from(datum/ui_state/default/paper_state/from)
- switch(from.edit_mode)
- if(MODE_READING)
- edit_mode = MODE_READING
- if(MODE_WRITING)
- edit_mode = MODE_WRITING
- pen_color = from.pen_color
- pen_font = from.pen_font
- is_crayon = from.is_crayon
- if(MODE_STAMPING)
- edit_mode = MODE_STAMPING
- stamp_icon_state = from.stamp_icon_state
- stamp_class = from.stamp_class
- stamp_name = from.stamp_name
/**
* Paper is now using markdown (like in github pull notes) for ALL rendering
@@ -58,6 +23,9 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "paper"
item_state = "paper"
+ // inhand_icon_state = "paper"
+ // worn_icon_state = "paper"
+ // custom_fire_overlay = "paper_onfire_overlay"
throwforce = 0
w_class = WEIGHT_CLASS_TINY
throw_range = 1
@@ -80,34 +48,19 @@
var/list/stamps /// Positioning for the stamp in tgui
var/list/stamped /// Overlay info
- /// This REALLY should be a componenet. Basicly used during, april fools
- /// to honk at you
- var/rigged = 0
- var/spam_flag = 0
-
var/contact_poison // Reagent ID to transfer on contact
var/contact_poison_volume = 0
- // Ok, so WHY are we caching the ui's?
- // Since we are not using autoupdate we
- // need some way to update the ui's of
- // other people looking at it and if
- // its been updated. Yes yes, lame
- // but canot be helped. However by
- // doing it this way, we can see
- // live updates and have multipule
- // people look at it
- var/list/viewing_ui = list()
-
/// When the sheet can be "filled out"
/// This is an associated list
var/list/form_fields = list()
var/field_counter = 1
/obj/item/paper/Destroy()
- close_all_ui()
stamps = null
stamped = null
+ form_fields = null
+ stamped = null
. = ..()
/**
@@ -162,7 +115,7 @@
set category = "Object"
set src in usr
- if(usr.incapacitated() || !usr.is_literate())
+ if(!usr.can_read(src) || usr.incapacitated(TRUE, TRUE) || (isobserver(usr) && !IsAdminGhost(usr)))
return
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
@@ -180,18 +133,6 @@
user.visible_message("[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku...")
return (BRUTELOSS)
-/// ONLY USED FOR APRIL FOOLS
-/obj/item/paper/proc/reset_spamflag()
- spam_flag = FALSE
-
-/obj/item/paper/attack_self(mob/user)
- if(rigged && (SSevents.holidays && SSevents.holidays[APRIL_FOOLS]))
- if(!spam_flag)
- spam_flag = TRUE
- playsound(loc, 'sound/items/bikehorn.ogg', 50, TRUE)
- addtimer(CALLBACK(src, .proc/reset_spamflag), 20)
- . = ..()
-
/obj/item/paper/proc/clearpaper()
info = ""
stamps = null
@@ -199,28 +140,39 @@
cut_overlays()
update_icon_state()
-/obj/item/paper/examine_more(mob/user)
- ui_interact(user)
- return list("You try to read [src]...")
+/obj/item/paper/examine(mob/user)
+ . = ..()
+ if(!in_range(user, src) && !isobserver(user))
+ . += "You're too far away to read it!"
+ return
+ if(user.can_read(src))
+ ui_interact(user)
+ return
+ . += "You cannot read it!"
+
+/obj/item/paper/ui_status(mob/user,/datum/ui_state/state)
+ // Are we on fire? Hard ot read if so
+ if(resistance_flags & ON_FIRE)
+ return UI_CLOSE
+ if(!in_range(user,src))
+ return UI_CLOSE
+ if(user.incapacitated(TRUE, TRUE) || (isobserver(user) && !IsAdminGhost(user)))
+ return UI_UPDATE
+ // Even harder to read if your blind...braile? humm
+ // .. or if you cannot read
+ if(!user.can_read(src))
+ return UI_CLOSE
+ if(in_contents_of(/obj/machinery/door/airlock))
+ return UI_INTERACTIVE
+ return ..()
+
+
/obj/item/paper/can_interact(mob/user)
- if(!..())
- return FALSE
- // Are we on fire? Hard ot read if so
- if(resistance_flags & ON_FIRE)
- return FALSE
- // Even harder to read if your blind...braile? humm
- if(user.is_blind())
- return FALSE
- // checks if the user can read.
- return user.can_read(src)
+ if(in_contents_of(/obj/machinery/door/airlock))
+ return TRUE
+ return ..()
-/**
- * This creates the ui, since we are using a custom state but not much else
- * just makes it easyer to make it.
- */
-/obj/item/paper/proc/create_ui(mob/user, datum/ui_state/default/paper_state/state)
- ui_interact(user, state = state)
/obj/item/proc/burn_paper_product_attackby_check(obj/item/I, mob/living/user, bypass_clumsy)
var/ignition_message = I.ignition_effect(src, user)
@@ -244,49 +196,22 @@
/obj/item/paper/attackby(obj/item/P, mob/living/user, params)
if(burn_paper_product_attackby_check(P, user))
- close_all_ui()
+ SStgui.close_uis(src)
return
if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
if(length(info) >= MAX_PAPER_LENGTH) // Sheet must have less than 1000 charaters
to_chat(user, "This sheet of paper is full!")
return
-
- var/datum/ui_state/default/paper_state/state = new
- state.edit_mode = MODE_WRITING
- // should a crayon be in the same subtype as a pen? How about a brush or charcoal?
- // TODO: Convert all writing stuff to one type, /obj/item/art_tool maybe?
- state.is_crayon = istype(P, /obj/item/toy/crayon);
- if(state.is_crayon)
- var/obj/item/toy/crayon/PEN = P
- state.pen_font = CRAYON_FONT
- state.pen_color = PEN.paint_color
- else
- var/obj/item/pen/PEN = P
- state.pen_font = PEN.font
- state.pen_color = PEN.colour
-
- create_ui(user, state)
+ ui_interact(user)
return
else if(istype(P, /obj/item/stamp))
-
- var/datum/ui_state/default/paper_state/state = new
- state.edit_mode = MODE_STAMPING // we are read only becausse the sheet is full
- state.stamp_icon_state = P.icon_state
- state.stamp_name = P.name
-
- var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper)
- state.stamp_class = sheet.icon_class_name(P.icon_state)
-
to_chat(user, "You ready your stamp over the paper! ")
-
- create_ui(user, state)
+ ui_interact(user)
return /// Normaly you just stamp, you don't need to read the thing
else
// cut paper? the sky is the limit!
- var/datum/ui_state/default/paper_state/state = new
- state.edit_mode = MODE_READING
- create_ui(user, state) // The other ui will be created with just read mode outside of this
+ ui_interact(user) // The other ui will be created with just read mode outside of this
return ..()
@@ -301,68 +226,64 @@
get_asset_datum(/datum/asset/spritesheet/simple/paper),
)
-/obj/item/paper/ui_interact(mob/user, datum/tgui/ui,
- datum/ui_state/default/paper_state/state)
- // Update the state
- ui = ui || SStgui.get_open_ui(user, src)
- if(ui && state)
- var/datum/ui_state/default/paper_state/current_state = ui.state
- current_state.copy_from(state)
+/obj/item/paper/ui_interact(mob/user, datum/tgui/ui)
// Update the UI
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PaperSheet", name)
- state = new
- ui.set_state(state)
- ui.set_autoupdate(FALSE)
- viewing_ui[user] = ui
ui.open()
-/obj/item/paper/ui_close(mob/user)
- /// close the editing window and change the mode
- viewing_ui[user] = null
- . = ..()
-// Again, we have to do this as autoupdate is off
-/obj/item/paper/proc/update_all_ui()
- for(var/datum/tgui/ui in viewing_ui)
- ui.process(force = TRUE)
+/obj/item/paper/ui_static_data(mob/user)
+ . = list()
+ .["text"] = info
+ .["max_length"] = MAX_PAPER_LENGTH
+ .["paper_color"] = !color || color == "white" ? "#FFFFFF" : color // color might not be set
+ .["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling?
+ .["stamps"] = stamps
+
-// Again, we have to do this as autoupdate is off
-/obj/item/paper/proc/close_all_ui()
- for(var/datum/tgui/ui in viewing_ui)
- ui.close()
- viewing_ui = list()
/obj/item/paper/ui_data(mob/user)
var/list/data = list()
-
- var/datum/tgui/ui = viewing_ui[user]
- var/datum/ui_state/default/paper_state/state = ui.state
-
- // Should all this go in static data and just do a forced update?
- data["text"] = info
- data["max_length"] = MAX_PAPER_LENGTH
- data["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling?
- data["paper_color"] = !color || color == "white" ? "#FFFFFF" : color // color might not be set
- data["stamps"] = stamps
-
- data["edit_mode"] = state.edit_mode
- data["edit_usr"] = "[ui.user]";
-
- // pen info for editing
- data["is_crayon"] = state.is_crayon
- data["pen_font"] = state.pen_font
- data["pen_color"] = state.pen_color
- // stamping info for..stamping
- data["stamp_class"] = state.stamp_class
-
+ var/obj/O = user.get_active_held_item()
+ if(istype(O, /obj/item/toy/crayon))
+ var/obj/item/toy/crayon/PEN = O
+ data["pen_font"] = CRAYON_FONT
+ data["pen_color"] = PEN.paint_color
+ data["edit_mode"] = MODE_WRITING
+ data["is_crayon"] = TRUE
+ data["stamp_class"] = "FAKE"
+ data["stamp_icon_state"] = "FAKE"
+ else if(istype(O, /obj/item/pen))
+ var/obj/item/pen/PEN = O
+ data["pen_font"] = PEN.font
+ data["pen_color"] = PEN.colour
+ data["edit_mode"] = MODE_WRITING
+ data["is_crayon"] = FALSE
+ data["stamp_class"] = "FAKE"
+ data["stamp_icon_state"] = "FAKE"
+ else if(istype(O, /obj/item/stamp))
+ var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper)
+ data["stamp_icon_state"] = O.icon_state
+ data["stamp_class"] = sheet.icon_class_name(O.icon_state)
+ data["edit_mode"] = MODE_STAMPING
+ data["pen_font"] = "FAKE"
+ data["pen_color"] = "FAKE"
+ data["is_crayon"] = FALSE
+ else
+ data["edit_mode"] = MODE_READING
+ data["pen_font"] = "FAKE"
+ data["pen_color"] = "FAKE"
+ data["is_crayon"] = FALSE
+ data["stamp_icon_state"] = "FAKE"
+ data["stamp_class"] = "FAKE"
data["field_counter"] = field_counter
data["form_fields"] = form_fields
return data
-/obj/item/paper/ui_act(action, params, datum/tgui/ui, datum/ui_state/default/paper_state/state)
+/obj/item/paper/ui_act(action, params,datum/tgui/ui)
if(..())
return
switch(action)
@@ -370,34 +291,33 @@
var/stamp_x = text2num(params["x"])
var/stamp_y = text2num(params["y"])
var/stamp_r = text2num(params["r"]) // rotation in degrees
-
+ var/stamp_icon_state = params["stamp_icon_state"]
+ var/stamp_class = params["stamp_class"]
if (isnull(stamps))
- stamps = new/list()
+ stamps = list()
if(stamps.len < MAX_PAPER_STAMPS)
// I hate byond when dealing with freaking lists
- stamps += list(list(state.stamp_class, stamp_x, stamp_y,stamp_r)) /// WHHHHY
+ stamps[++stamps.len] = list(stamp_class, stamp_x, stamp_y, stamp_r) /// WHHHHY
/// This does the overlay stuff
if (isnull(stamped))
- stamped = new/list()
+ stamped = list()
if(stamped.len < MAX_PAPER_STAMPS_OVERLAYS)
- var/mutable_appearance/stampoverlay = mutable_appearance('icons/obj/bureaucracy.dmi', "paper_[state.stamp_icon_state]")
+ var/mutable_appearance/stampoverlay = mutable_appearance('icons/obj/bureaucracy.dmi', "paper_[stamp_icon_state]")
stampoverlay.pixel_x = rand(-2, 2)
stampoverlay.pixel_y = rand(-3, 2)
add_overlay(stampoverlay)
- LAZYADD(stamped, state.stamp_icon_state)
+ LAZYADD(stamped, stamp_icon_state)
- ui.user.visible_message("[ui.user] stamps [src] with [state.stamp_name]!", "You stamp [src] with [state.stamp_name]!")
+ update_static_data(usr,ui)
+ ui.user.visible_message("[ui.user] stamps [src] with [stamp_class]!", "You stamp [src] with [stamp_class]!")
else
to_chat(usr, pick("You try to stamp but you miss!", "There is no where else you can stamp!"))
-
- update_all_ui()
. = TRUE
if("save")
var/in_paper = params["text"]
var/paper_len = length(in_paper)
- var/list/fields = params["form_fields"]
field_counter = params["field_counter"] ? text2num(params["field_counter"]) : field_counter
if(paper_len > MAX_PAPER_LENGTH)
@@ -413,14 +333,10 @@
if(info != in_paper)
to_chat(ui.user, "You have added to your paper masterpiece!");
info = in_paper
-
- for(var/key in fields)
- form_fields[key] = fields[key];
+ update_static_data(usr,ui)
- update_all_ui()
update_icon()
-
. = TRUE
/**
diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm
index 3937720f74..a3b9b23141 100644
--- a/code/modules/paperwork/paper_cutter.dm
+++ b/code/modules/paperwork/paper_cutter.dm
@@ -26,11 +26,11 @@
var/obj/item/bodypart/BP = C.get_bodypart(BODY_ZONE_HEAD)
if(BP)
BP.drop_limb()
- playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1)
+ playsound(loc, pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg'),50, TRUE, -1)
return (BRUTELOSS)
else
user.visible_message("[user] repeatedly bashes [src.name] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!")
- playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
+ playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1)
return (BRUTELOSS)
@@ -42,11 +42,12 @@
if(storedpaper)
. += "paper"
+
/obj/item/papercutter/attackby(obj/item/P, mob/user, params)
if(istype(P, /obj/item/paper) && !storedpaper)
if(!user.transferItemToLoc(P, src))
return
- playsound(loc, "pageturn", 60, 1)
+ playsound(loc, "pageturn", 60, TRUE)
to_chat(user, "You place [P] in [src].")
storedpaper = P
update_icon()
@@ -59,17 +60,17 @@
storedcutter = P
update_icon()
return
- if(istype(P, /obj/item/screwdriver) && storedcutter)
+ if(P.tool_behaviour == TOOL_SCREWDRIVER && storedcutter)
P.play_tool_sound(src)
to_chat(user, "[storedcutter] has been [cuttersecured ? "unsecured" : "secured"].")
cuttersecured = !cuttersecured
return
..()
-/obj/item/papercutter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/papercutter/on_attack_hand(mob/user)
add_fingerprint(user)
if(!storedcutter)
- to_chat(user, "The cutting blade is gone! You can't use [src] now.")
+ to_chat(user, "The cutting blade is gone! You can't use [src] now.")
return
if(!cuttersecured)
@@ -79,7 +80,7 @@
update_icon()
if(storedpaper)
- playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1)
+ playsound(src.loc, 'sound/weapons/slash.ogg', 50, TRUE)
to_chat(user, "You neatly cut [storedpaper].")
storedpaper = null
qdel(storedpaper)
@@ -88,6 +89,7 @@
update_icon()
/obj/item/papercutter/MouseDrop(atom/over_object)
+ . = ..()
var/mob/M = usr
if(M.incapacitated() || !Adjacent(M))
return
@@ -98,10 +100,6 @@
else if(istype(over_object, /obj/screen/inventory/hand))
var/obj/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(src, H.held_index)
-
- else
- . = ..()
-
add_fingerprint(M)
/obj/item/paperslip
@@ -112,6 +110,12 @@
resistance_flags = FLAMMABLE
max_integrity = 50
+/obj/item/paperslip/attackby(obj/item/I, mob/living/user, params)
+ if(burn_paper_product_attackby_check(I, user))
+ return
+ return ..()
+
+
/obj/item/paperslip/Initialize()
. = ..()
pixel_x = rand(-5, 5)
@@ -124,5 +128,6 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "cutterblade"
item_state = "knife"
+ // inhand_icon_state = "knife"
lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi'
diff --git a/code/modules/paperwork/paper_premade.dm b/code/modules/paperwork/paper_premade.dm
index 414026924a..97b15628a8 100644
--- a/code/modules/paperwork/paper_premade.dm
+++ b/code/modules/paperwork/paper_premade.dm
@@ -4,53 +4,22 @@
/obj/item/paper/fluff/sop
name = "paper- 'Standard Operating Procedure'"
- info = {"
-Alert Levels:
-* Blue - Emergency
- * Caused by fire
- * Caused by manual interaction
- * Action: Close all fire doors. These can only be opened by resetting the alarm
-* Red- Ejection/Self Destruct
- * Caused by module operating computer.
- * Action: After the specified time the module will eject completely.
-Engine Maintenance Instructions:
-1. Shut off ignition systems:
-2. Activate internal power
-3. Activate orbital balance matrix
-4. Remove volatile liquids from area
-5. Wear a fire suit
-6. After Decontaminate Visit medical examiner
-Toxin Laboratory Procedure:
-1. Wear a gas mask regardless
-2. Get an oxygen tank.
-3. Activate internal atmosphere
-4. After Decontaminate Visit medical examiner
-Disaster Procedure:
-Fire:
-1. Activate sector fire alarm.
-2. Move to a safe area.
-3. Get a fire suit
-* After:
- 1. Assess Damage
- 2. Repair damages
- 3. If needed, Evacuate
-Meteor Shower:
-1. Activate fire alarm
-2. Move to the back of ship
-* After
- 1. Repair damage
- 2. If needed, Evacuate
-Accidental Reentry:
-1. Activate fire alarms in front of ship.
-2. Move volatile matter to a fire proof area!
-3. Get a fire suit.
-4. Stay secure until an emergency ship arrives.
-5. If ship does not arrive-Evacuate to a nearby safe area!
-"};
+ info = "Alert Levels:
\nBlue- Emergency
\n\t1. Caused by fire
\n\t2. Caused by manual interaction
\n\tAction:
\n\t\tClose all fire doors. These can only be opened by resetting the alarm
\nRed- Ejection/Self-Destruct
\n\t1. Caused by module operating computer.
\n\tAction:
\n\t\tAfter the specified time the module will eject completely.
\n
\nEngine Maintenance Instructions:
\n\tShut off ignition systems:
\n\tActivate internal power
\n\tActivate orbital balance matrix
\n\tRemove volatile liquids from area
\n\tWear a fire suit
\n
\n\tAfter
\n\t\tDecontaminate
\n\t\tVisit medical examiner
\n
\nToxin Laboratory Procedure:
\n\tWear a gas mask regardless
\n\tGet an oxygen tank.
\n\tActivate internal atmosphere
\n
\n\tAfter
\n\t\tDecontaminate
\n\t\tVisit medical examiner
\n
\nDisaster Procedure:
\n\tFire:
\n\t\tActivate sector fire alarm.
\n\t\tMove to a safe area.
\n\t\tGet a fire suit
\n\t\tAfter:
\n\t\t\tAssess Damage
\n\t\t\tRepair damages
\n\t\t\tIf needed, Evacuate
\n\tMeteor Shower:
\n\t\tActivate fire alarm
\n\t\tMove to the back of ship
\n\t\tAfter
\n\t\t\tRepair damage
\n\t\t\tIf needed, Evacuate
\n\tAccidental Reentry:
\n\t\tActivate fire alarms in front of ship.
\n\t\tMove volatile matter to a fire proof area!
\n\t\tGet a fire suit.
\n\t\tStay secure until an emergency ship arrives.
\n
\n\t\tIf ship does not arrive-
\n\t\t\tEvacuate to a nearby safe area!"
/obj/item/paper/fluff/shuttles/daniel
info = "i love daniel
daniel is my best friend
you are tearing me apart elise"
+/obj/item/paper/fluff/jobs/prisoner/letter
+ name = "letter from home"
+ info = {"Dearest sweetheart,
+
It is truly saddening you must spend your time locked up in an awful prison on that dangerous station. I have spoken to your lawyer who will attempt to appeal to the judge so your sentence may hopefully be reduced.
+
Regardless, I just want you to understand that all of us out here still love you, and want to see you released safely some day! I know that prison can be a very vicious place, so please promise us you'll avoid getting into any fights or trouble, okay?
+
We all care for your safety deeply, and could not live with ourselves if you ended up getting hurt. We've scheduled a visit to see you, and with any luck, hopefully our request will be granted soon.
+
Anyways, please do your best to make it by in that place, and never forget we'll be always here for you, no matter if we're separated.
+
+
Please stay safe,
+
-Love, Your Dearest"}
+
//////////// Job guides n' fluff
@@ -90,9 +59,42 @@ Accidental Reentry:
name = "paper- 'Chemical Information'"
info = "Known Onboard Toxins:
\n\tGrade A Semi-Liquid Plasma:
\n\t\tHighly poisonous. You cannot sustain concentrations above 15 units.
\n\t\tA gas mask fails to filter plasma after 50 units.
\n\t\tWill attempt to diffuse like a gas.
\n\t\tFiltered by scrubbers.
\n\t\tThere is a bottled version which is very different
\n\t\t\tfrom the version found in canisters!
\n
\n\t\tWARNING: Highly Flammable. Keep away from heat sources
\n\t\texcept in an enclosed fire area!
\n\t\tWARNING: It is a crime to use this without authorization.
\nKnown Onboard Anti-Toxin:
\n\tAnti-Toxin Type 01P: Works against Grade A Plasma.
\n\t\tBest if injected directly into bloodstream.
\n\t\tA full injection is in every regular Med-Kit.
\n\t\tSpecial toxin Kits hold around 7.
\n
\nKnown Onboard Chemicals (other):
\n\tRejuvenation T#001:
\n\t\tEven 1 unit injected directly into the bloodstream
\n\t\t\twill cure unconscious and sleep toxins.
\n\t\tIf administered to a dying patient it will prevent
\n\t\t\tfurther damage for about units*3 seconds.
\n\t\t\tit will not cure them or allow them to be cured.
\n\t\tIt can be administered to a non-dying patient
\n\t\t\tbut the chemicals disappear just as fast.
\n\tMorphine T#054:
\n\t\t5 units will induce precisely 1 minute of sleep.
\n\t\t\tThe effect are cumulative.
\n\t\tWARNING: It is a crime to use this without authorization"
+/obj/item/paper/fluff/jobs/medical/hippocratic
+ name = "paper- 'Hippocratic Oath'"
+ info = {"I swear to fulfill, to the best of my ability and judgment, this covenant:
+
+ I will respect the hard-won scientific gains of those physicians in whose steps I walk,
+ and gladly share such knowledge as is mine with those who are to follow.
+
+ I will apply, for the benefit of the sick, all measures that are required,
+ avoiding those twin traps of overtreatment and therapeutic nihilism.
+
+ I will remember that there is art to medicine as well as science,
+ and that warmth, sympathy, and understanding may outweigh the surgeon's knife or the chemist's drug.
+
+ I will not be ashamed to say "I know not,"
+ nor will I fail to call in my colleagues when the skills of another are needed for a patient's recovery.
+
+ I will respect the privacy of my patients, for their problems are not disclosed to me that the world may know. Most especially must I tread with care in matters of life and death.
+ If it is given me to save a life, all thanks. But it may also be within my power to take a life;
+ this awesome responsibility must be faced with great humbleness and awareness of my own frailty. Above all, I must not play at God.
+
+ I will remember that I do not treat a fever chart, a cancerous growth, but a sick human being, whose illness may affect the person's family and economic stability.
+ My responsibility includes these related problems, if I am to care adequately for the sick.
+
+ I will prevent disease whenever I can, for prevention is preferable to cure.
+
+ I will remember that I remain a member of society, with special obligations to all my fellow human beings,
+ those sound of mind and body as well as the infirm.
+
+ If I do not violate this oath, may I enjoy life and art, respected while I live and remembered with affection thereafter.
+ May I always act so as to preserve the finest traditions of my calling and may I long experience the joy of healing those who seek my help.
+ "}
+
/*
* Stations
*/
+////////// cogstation.
/obj/item/paper/guides/cogstation/job_changes
name = "MEMO: Job Changes"
diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm
index 28cb5ffae9..b8bbd0a30e 100644
--- a/code/modules/paperwork/paperbin.dm
+++ b/code/modules/paperwork/paperbin.dm
@@ -4,6 +4,7 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "paper_bin1"
item_state = "sheet-metal"
+ // inhand_icon_state = "sheet-metal"
lefthand_file = 'icons/mob/inhands/misc/sheets_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/sheets_righthand.dmi'
throwforce = 0
@@ -43,6 +44,7 @@
..()
/obj/item/paper_bin/MouseDrop(atom/over_object)
+ . = ..()
var/mob/living/M = usr
if(!istype(M) || M.incapacitated() || !Adjacent(M))
return
@@ -54,17 +56,18 @@
var/obj/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(src, H.held_index)
- else
- . = ..()
-
add_fingerprint(M)
/obj/item/paper_bin/attack_paw(mob/user)
return attack_hand(user)
-/obj/item/paper_bin/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- if(user.lying)
- return
+//ATTACK HAND IGNORING PARENT RETURN VALUE
+/obj/item/paper_bin/on_attack_hand(mob/user)
+ if(isliving(user))
+ var/mob/living/L = user
+ if(!(L.mobility_flags & MOBILITY_PICKUP))
+ return
+ // user.changeNext_move(CLICK_CD_MELEE)
if(bin_pen)
var/obj/item/pen/P = bin_pen
P.add_fingerprint(user)
@@ -85,8 +88,8 @@
P = new papertype(src)
if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
if(prob(30))
- P.info = "*HONK HONK HONK HONK HONK HONK HONK
HOOOOOOOOOOOOOOOOOOOOOONK*\n*APRIL FOOLS*\n"
- P.rigged = 1
+ P.info = "HONK HONK HONK HONK HONK HONK HONK
HOOOOOOOOOOOOOOOOOOOOOONK
APRIL FOOLS"
+ P.AddComponent(/datum/component/honkspam)
P.add_fingerprint(user)
P.forceMove(user.loc)
@@ -148,8 +151,7 @@
papertype = /obj/item/paper/natural
resistance_flags = FLAMMABLE
-/obj/item/paper_bin/bundlenatural/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- ..()
+/obj/item/paper_bin/bundlenatural/on_attack_hand(mob/user)
if(total_paper < 1)
qdel(src)
@@ -173,3 +175,9 @@
qdel(src)
else
..()
+
+/obj/item/paper_bin/carbon
+ name = "carbon paper bin"
+ desc = "Contains all the paper you'll ever need, in duplicate!"
+ icon_state = "paper_bin_carbon"
+ papertype = /obj/item/paper/carbon
diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm
index c6a1ee1389..d496ae8068 100644
--- a/code/modules/paperwork/paperplane.dm
+++ b/code/modules/paperwork/paperplane.dm
@@ -1,9 +1,9 @@
-
/obj/item/paperplane
name = "paper plane"
desc = "Paper, folded in the shape of a plane."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "paperplane"
+ // custom_fire_overlay = "paperplane_onfire"
throw_range = 7
throw_speed = 1
throwforce = 0
@@ -11,7 +11,7 @@
resistance_flags = FLAMMABLE
max_integrity = 50
- var/hit_probability = 2//%
+ var/hit_probability = 2 //%
var/obj/item/paper/internalPaper
/obj/item/paperplane/origami
@@ -41,6 +41,13 @@
qdel(src)
return ..()
+/obj/item/paperplane/Exited(atom/movable/AM, atom/newLoc)
+ . = ..()
+ if (AM == internalPaper)
+ internalPaper = null
+ if(!QDELETED(src))
+ qdel(src)
+
/obj/item/paperplane/Destroy()
QDEL_NULL(internalPaper)
return ..()
@@ -71,35 +78,23 @@
user.put_in_hands(internal_paper_tmp)
/obj/item/paperplane/attackby(obj/item/P, mob/living/carbon/human/user, params)
- ..()
+ if(burn_paper_product_attackby_check(P, user))
+ return
if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
- to_chat(user, "You should unfold [src] before changing it.")
+ to_chat(user, "You should unfold [src] before changing it!")
return
else if(istype(P, /obj/item/stamp)) //we don't randomize stamps on a paperplane
internalPaper.attackby(P, user) //spoofed attack to update internal paper.
update_icon()
+ add_fingerprint(user)
+ return
- else if(P.get_temperature())
- if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10))
- user.visible_message("[user] accidentally ignites [user.p_them()]self!", \
- "You miss [src] and accidentally light yourself on fire!")
- user.dropItemToGround(P)
- user.adjust_fire_stacks(1)
- user.IgniteMob()
- return
-
- if(!(in_range(user, src))) //to prevent issues as a result of telepathically lighting a paper
- return
- user.dropItemToGround(src)
- user.visible_message("[user] lights [src] ablaze with [P]!", "You light [src] on fire!")
- fire_act()
-
- add_fingerprint(user)
+ return ..()
-/obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback)
- . = ..(target, range, speed, thrower, FALSE, diagonals_first, callback)
+/obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback, quickstart = TRUE)
+ . = ..(target, range, speed, thrower, FALSE, diagonals_first, callback, quickstart = quickstart)
/obj/item/paperplane/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(iscarbon(hit_atom))
@@ -112,26 +107,28 @@
if(..() || !ishuman(hit_atom))//if the plane is caught or it hits a nonhuman
return
var/mob/living/carbon/human/H = hit_atom
+ var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
if(prob(hit_probability))
if(H.is_eyes_covered())
return
- var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
- visible_message("\The [src] hits [H] in the eye!")
+ visible_message("\The [src] hits [H] in the eye[eyes ? "" : " socket"]!")
H.adjust_blurriness(6)
- if(eyes)
- eyes.applyOrganDamage(rand(6,8))
+ eyes?.applyOrganDamage(rand(6,8))
H.DefaultCombatKnockdown(40)
H.emote("scream")
-
/obj/item/paper/examine(mob/user)
. = ..()
. += "Alt-click [src] to fold it into a paper plane."
/obj/item/paper/AltClick(mob/living/carbon/user, obj/item/I)
- . = ..()
- if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user), NO_TK))
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
+ if(istype(src, /obj/item/paper/carbon))
+ var/obj/item/paper/carbon/Carbon = src
+ if(!Carbon.iscopy && !Carbon.copied)
+ to_chat(user, "Take off the carbon copy first.")
+ return
to_chat(user, "You fold [src] into the shape of a plane!")
user.temporarilyRemoveItemFromInventory(src)
var/obj/item/paperplane/plane_type = /obj/item/paperplane
@@ -142,4 +139,3 @@
I = new plane_type(user, src)
user.put_in_hands(I)
- return TRUE
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 91b8a6719b..13890ae69e 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -16,6 +16,8 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "pen"
item_state = "pen"
+ // inhand_icon_state = "pen"
+ // worn_icon_state = "pen"
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_EARS
throwforce = 0
w_class = WEIGHT_CLASS_TINY
@@ -76,6 +78,22 @@
icon_state = "pen-fountain"
font = FOUNTAIN_PEN_FONT
+/obj/item/pen/charcoal
+ name = "charcoal stylus"
+ desc = "It's just a wooden stick with some compressed ash on the end. At least it can write."
+ icon_state = "pen-charcoal"
+ colour = "dimgray"
+ font = CHARCOAL_FONT
+ custom_materials = null
+ grind_results = list(/datum/reagent/ash = 5, /datum/reagent/cellulose = 10)
+
+/datum/crafting_recipe/charcoal_stylus
+ name = "Charcoal Stylus"
+ result = /obj/item/pen/charcoal
+ reqs = list(/obj/item/stack/sheet/mineral/wood = 1, /datum/reagent/ash = 30)
+ time = 30
+ category = CAT_PRIMAL
+
/obj/item/pen/fountain/captain
name = "captain's fountain pen"
desc = "It's an expensive Oak fountain pen. The nib is quite sharp."
@@ -93,6 +111,7 @@
"Black and Silver" = "pen-fountain-b",
"Command Blue" = "pen-fountain-cb"
)
+ embedding = list("embed_chance" = 75)
/obj/item/pen/fountain/captain/Initialize()
. = ..()
@@ -139,20 +158,18 @@
if(QDELETED(O) || !user.canUseTopic(O, BE_CLOSE))
return
if(oldname == input)
- to_chat(user, "You changed \the [O.name] to... well... \the [O.name].")
+ to_chat(user, "You changed \the [O.name] to... well... \the [O.name].")
else
O.name = input
- to_chat(user, "\The [oldname] has been successfully been renamed to \the [input].")
+ to_chat(user, "\The [oldname] has been successfully been renamed to \the [input].")
O.renamedByPlayer = TRUE
- log_game("[user] [key_name(user)] has renamed [O] to [input]")
if(penchoice == "Change description")
- var/input = stripped_input(user,"Describe \the [O.name] here", ,"", 2048)
+ var/input = stripped_input(user,"Describe \the [O.name] here", ,"", 100)
if(QDELETED(O) || !user.canUseTopic(O, BE_CLOSE))
return
O.desc = input
- to_chat(user, "You have successfully changed \the [O.name]'s description.")
- log_game("[user] [key_name(user)] has changed [O]'s description to to [input]")
+ to_chat(user, "You have successfully changed \the [O.name]'s description.")
/*
* Sleepypens
@@ -181,9 +198,10 @@
*/
/obj/item/pen/edagger
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") //these wont show up if the pen is off
+ // attack_verb_continuous = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") //these won't show up if the pen is off
+ // attack_verb_simple = list("slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")
sharpness = SHARP_EDGED
var/on = FALSE
- embedding = list(embed_chance = EMBED_CHANCE)
/obj/item/pen/edagger/ComponentInitialize()
. = ..()
@@ -193,29 +211,38 @@
/obj/item/pen/edagger/get_sharpness()
return on * sharpness
+/obj/item/pen/edagger/suicide_act(mob/user)
+ . = BRUTELOSS
+ if(on)
+ user.visible_message("[user] forcefully rams the pen into their mouth!")
+ else
+ user.visible_message("[user] is holding a pen up to their mouth! It looks like [user.p_theyre()] trying to commit suicide!")
+ attack_self(user)
+
/obj/item/pen/edagger/attack_self(mob/living/user)
if(on)
on = FALSE
force = initial(force)
+ throw_speed = initial(throw_speed)
w_class = initial(w_class)
name = initial(name)
hitsound = initial(hitsound)
- embedding = null
+ embedding = list(embed_chance = EMBED_CHANCE)
throwforce = initial(throwforce)
- playsound(user, 'sound/weapons/saberoff.ogg', 5, 1)
+ playsound(user, 'sound/weapons/saberoff.ogg', 5, TRUE)
to_chat(user, "[src] can now be concealed.")
- updateEmbedding()
else
on = TRUE
force = 18
+ throw_speed = 4
w_class = WEIGHT_CLASS_NORMAL
name = "energy dagger"
hitsound = 'sound/weapons/blade1.ogg'
- embedding = list(embed_chance = 100, fall_chance = 0) //rule of cool
+ embedding = list(embed_chance = 100) //rule of cool
throwforce = 35
- playsound(user, 'sound/weapons/saberon.ogg', 5, 1)
+ playsound(user, 'sound/weapons/saberon.ogg', 5, TRUE)
to_chat(user, "[src] is now active.")
- updateEmbedding()
+ updateEmbedding()
update_icon()
/obj/item/pen/edagger/update_icon_state()
@@ -235,6 +262,8 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "digging_pen"
item_state = "pen"
+ // inhand_icon_state = "pen"
+ // worn_icon_state = "pen"
force = 3
w_class = WEIGHT_CLASS_TINY
custom_materials = list(/datum/material/iron=10, /datum/material/diamond=100, /datum/material/titanium = 10)
diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm
index 241dde13a8..104f70bfdf 100644
--- a/code/modules/paperwork/stamps.dm
+++ b/code/modules/paperwork/stamps.dm
@@ -4,6 +4,7 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "stamp-ok"
item_state = "stamp"
+ // inhand_icon_state = "stamp"
throwforce = 0
w_class = WEIGHT_CLASS_TINY
throw_speed = 3
@@ -11,6 +12,8 @@
custom_materials = list(/datum/material/iron=60)
pressure_resistance = 2
attack_verb = list("stamped")
+ // attack_verb_continuous = list("stamps")
+ // attack_verb_simple = list("stamp")
/obj/item/stamp/suicide_act(mob/user)
user.visible_message("[user] stamps 'VOID' on [user.p_their()] forehead, then promptly falls over, dead.")
@@ -66,5 +69,25 @@
icon_state = "stamp-clown"
dye_color = DYE_CLOWN
+/obj/item/stamp/mime
+ name = "mime's rubber stamp"
+ icon_state = "stamp-mime"
+ dye_color = DYE_MIME
+
+/obj/item/stamp/chap
+ name = "chaplain's rubber stamp"
+ icon_state = "stamp-chap"
+ dye_color = DYE_CHAP
+
+/obj/item/stamp/centcom
+ name = "CentCom rubber stamp"
+ icon_state = "stamp-centcom"
+ dye_color = DYE_CENTCOM
+
+/obj/item/stamp/syndicate
+ name = "Syndicate rubber stamp"
+ icon_state = "stamp-syndicate"
+ dye_color = DYE_SYNDICATE
+
/obj/item/stamp/attack_paw(mob/user)
return attack_hand(user)
diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm
new file mode 100644
index 0000000000..e46ed64971
--- /dev/null
+++ b/code/modules/paperwork/ticketmachine.dm
@@ -0,0 +1,231 @@
+//Bureaucracy machine!
+//Simply set this up in the hopline and you can serve people based on ticket numbers
+
+/obj/machinery/ticket_machine
+ name = "ticket machine"
+ icon = 'icons/obj/bureaucracy.dmi'
+ icon_state = "ticketmachine"
+ desc = "A marvel of bureaucratic engineering encased in an efficient plastic shell. It can be refilled with a hand labeler refill roll and linked to buttons with a multitool."
+ density = FALSE
+ maptext_height = 26
+ maptext_width = 32
+ maptext_x = 7
+ maptext_y = 10
+ layer = HIGH_OBJ_LAYER
+ var/ticket_number = 0 //Increment the ticket number whenever the HOP presses his button
+ var/current_number = 0 //What ticket number are we currently serving?
+ var/max_number = 100 //At this point, you need to refill it.
+ var/cooldown = 50
+ var/ready = TRUE
+ var/id = "ticket_machine_default" //For buttons
+ var/list/ticket_holders = list()
+ var/list/obj/item/ticket_machine_ticket/tickets = list()
+
+/obj/machinery/ticket_machine/multitool_act(mob/living/user, obj/item/I)
+ if(!multitool_check_buffer(user, I)) //make sure it has a data buffer
+ return
+ var/obj/item/multitool/M = I
+ M.buffer = src
+ to_chat(user, "You store linkage information in [I]'s buffer.")
+ return TRUE
+
+/obj/machinery/ticket_machine/emag_act(mob/user) //Emag the ticket machine to dispense burning tickets, as well as randomize its number to destroy the HoP's mind.
+ if(obj_flags & EMAGGED)
+ return
+ to_chat(user, "You overload [src]'s bureaucratic logic circuitry to its MAXIMUM setting.")
+ ticket_number = rand(0,max_number)
+ current_number = ticket_number
+ obj_flags |= EMAGGED
+ if(tickets.len)
+ for(var/obj/item/ticket_machine_ticket/ticket in tickets)
+ ticket.audible_message("\the [ticket] disperses!")
+ qdel(ticket)
+ tickets.Cut()
+ update_icon()
+
+/obj/machinery/ticket_machine/Initialize()
+ . = ..()
+ update_icon()
+
+/obj/machinery/ticket_machine/proc/increment()
+ if(current_number > ticket_number)
+ return
+ if(current_number && !(obj_flags & EMAGGED) && tickets[current_number])
+ tickets[current_number].audible_message("\the [tickets[current_number]] disperses!")
+ qdel(tickets[current_number])
+ if(current_number < ticket_number)
+ current_number ++ //Increment the one we're serving.
+ playsound(src, 'sound/misc/announce_dig.ogg', 50, FALSE)
+ say("Now serving ticket #[current_number]!")
+ if(!(obj_flags & EMAGGED) && tickets[current_number])
+ tickets[current_number].audible_message("\the [tickets[current_number]] vibrates!")
+ update_icon() //Update our icon here rather than when they take a ticket to show the current ticket number being served
+
+/obj/machinery/button/ticket_machine
+ name = "increment ticket counter"
+ desc = "Use this button after you've served someone to tell the next person to come forward."
+ device_type = /obj/item/assembly/control/ticket_machine
+ req_access = list()
+ id = "ticket_machine_default"
+
+/obj/machinery/button/ticket_machine/Initialize()
+ . = ..()
+ if(device)
+ var/obj/item/assembly/control/ticket_machine/ours = device
+ ours.id = id
+
+/obj/machinery/button/ticket_machine/multitool_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(I.tool_behaviour == TOOL_MULTITOOL)
+ var/obj/item/multitool/M = I
+ if(M.buffer && !istype(M.buffer, /obj/machinery/ticket_machine))
+ return
+ var/obj/item/assembly/control/ticket_machine/controller = device
+ controller.linked = M.buffer
+ id = null
+ controller.id = null
+ to_chat(user, "You've linked [src] to [controller.linked].")
+
+/obj/item/assembly/control/ticket_machine
+ name = "ticket machine controller"
+ desc = "A remote controller for the HoP's ticket machine."
+ var/obj/machinery/ticket_machine/linked //To whom are we linked?
+
+/obj/item/assembly/control/ticket_machine/Initialize()
+ ..()
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/item/assembly/control/ticket_machine/LateInitialize()
+ find_machine()
+
+/obj/item/assembly/control/ticket_machine/proc/find_machine() //Locate the one to which we're linked
+ for(var/obj/machinery/ticket_machine/ticketsplease in GLOB.machines)
+ if(ticketsplease.id == id)
+ linked = ticketsplease
+ if(linked)
+ return TRUE
+ else
+ return FALSE
+
+/obj/item/assembly/control/ticket_machine/activate()
+ if(cooldown)
+ return
+ if(!linked)
+ return
+ cooldown = TRUE
+ linked.increment()
+ addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
+
+/obj/machinery/ticket_machine/update_icon()
+ switch(ticket_number) //Gives you an idea of how many tickets are left
+ if(0 to 49)
+ icon_state = "ticketmachine_100"
+ if(50 to 99)
+ icon_state = "ticketmachine_50"
+ if(100)
+ icon_state = "ticketmachine_0"
+ handle_maptext()
+
+/obj/machinery/ticket_machine/proc/handle_maptext()
+ switch(ticket_number) //This is here to handle maptext offsets so that the numbers align.
+ if(0 to 9)
+ maptext_x = 13
+ if(10 to 99)
+ maptext_x = 10
+ if(100)
+ maptext_x = 8
+ maptext = "[current_number]" //Finally, apply the maptext
+
+/obj/machinery/ticket_machine/attackby(obj/item/I, mob/user, params)
+ ..()
+ if(istype(I, /obj/item/hand_labeler_refill))
+ if(!(ticket_number >= max_number))
+ to_chat(user, "[src] refuses [I]! There [max_number-ticket_number==1 ? "is" : "are"] still [max_number-ticket_number] ticket\s left!")
+ return
+ to_chat(user, "You start to refill [src]'s ticket holder (doing this will reset its ticket count!).")
+ if(do_after(user, 30, target = src))
+ to_chat(user, "You insert [I] into [src] as it whirs nondescriptly.")
+ qdel(I)
+ ticket_number = 0
+ current_number = 0
+ if(tickets.len)
+ for(var/obj/item/ticket_machine_ticket/ticket in tickets)
+ ticket.audible_message("\the [ticket] disperses!")
+ qdel(ticket)
+ tickets.Cut()
+ max_number = initial(max_number)
+ update_icon()
+ return
+
+/obj/machinery/ticket_machine/proc/reset_cooldown()
+ ready = TRUE
+
+/obj/machinery/ticket_machine/attack_hand(mob/living/carbon/user)
+ . = ..()
+ if(!ready)
+ to_chat(user,"You press the button, but nothing happens...")
+ return
+ if(ticket_number >= max_number)
+ to_chat(user,"Ticket supply depleted, please refill this unit with a hand labeller refill cartridge!")
+ return
+ if((user in ticket_holders) && !(obj_flags & EMAGGED))
+ to_chat(user, "You already have a ticket!")
+ return
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 100, FALSE)
+ ticket_number ++
+ to_chat(user, "You take a ticket from [src], looks like you're ticket number #[ticket_number]...")
+ var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src))
+ theirticket.name = "Ticket #[ticket_number]"
+ theirticket.maptext = "[ticket_number]"
+ theirticket.saved_maptext = "[ticket_number]"
+ theirticket.ticket_number = ticket_number
+ theirticket.source = src
+ theirticket.owner = user
+ user.put_in_hands(theirticket)
+ ticket_holders += user
+ tickets += theirticket
+ if(obj_flags & EMAGGED) //Emag the machine to destroy the HOP's life.
+ ready = FALSE
+ addtimer(CALLBACK(src, .proc/reset_cooldown), cooldown)//Small cooldown to prevent piles of flaming tickets
+ theirticket.fire_act()
+ user.dropItemToGround(theirticket)
+ user.adjust_fire_stacks(1)
+ user.IgniteMob()
+ return
+
+/obj/item/ticket_machine_ticket
+ name = "Ticket"
+ desc = "A ticket which shows your place in the Head of Personnel's line. Made from Nanotrasen patented NanoPaper®. Though solid, its form seems to shimmer slightly. Feels (and burns) just like the real thing."
+ icon = 'icons/obj/bureaucracy.dmi'
+ icon_state = "ticket"
+ maptext_x = 7
+ maptext_y = 10
+ w_class = WEIGHT_CLASS_TINY
+ resistance_flags = FLAMMABLE
+ max_integrity = 50
+ var/saved_maptext = null
+ var/mob/living/carbon/owner
+ var/obj/machinery/ticket_machine/source
+ var/ticket_number
+
+/obj/item/ticket_machine_ticket/attack_hand(mob/user)
+ . = ..()
+ maptext = saved_maptext //For some reason, storage code removes all maptext off objs, this stops its number from being wiped off when taken out of storage.
+
+/obj/item/ticket_machine_ticket/attackby(obj/item/P, mob/living/carbon/human/user, params) //Stolen from papercode
+ if(burn_paper_product_attackby_check(P, user))
+ return
+
+ return ..()
+
+/obj/item/paper/extinguish()
+ ..()
+ update_icon()
+
+/obj/item/ticket_machine_ticket/Destroy()
+ if(owner && source)
+ source.ticket_holders -= owner
+ source.tickets[ticket_number] = null
+ owner = null
+ source = null
+ return ..()
diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi
index 95ae326f1e..b778a9d1a2 100644
Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ
diff --git a/icons/stamp_icons/font.png b/icons/stamp_icons/font.png
new file mode 100644
index 0000000000..4297937696
Binary files /dev/null and b/icons/stamp_icons/font.png differ
diff --git a/icons/stamp_icons/large_stamp-cap.png b/icons/stamp_icons/large_stamp-cap.png
index 7f7ce460a4..19883563b2 100644
Binary files a/icons/stamp_icons/large_stamp-cap.png and b/icons/stamp_icons/large_stamp-cap.png differ
diff --git a/icons/stamp_icons/large_stamp-ce.png b/icons/stamp_icons/large_stamp-ce.png
index 189db310cf..d07f70c4d5 100644
Binary files a/icons/stamp_icons/large_stamp-ce.png and b/icons/stamp_icons/large_stamp-ce.png differ
diff --git a/icons/stamp_icons/large_stamp-centcom.png b/icons/stamp_icons/large_stamp-centcom.png
new file mode 100644
index 0000000000..6250cbff88
Binary files /dev/null and b/icons/stamp_icons/large_stamp-centcom.png differ
diff --git a/icons/stamp_icons/large_stamp-chap.png b/icons/stamp_icons/large_stamp-chap.png
new file mode 100644
index 0000000000..2586c13bad
Binary files /dev/null and b/icons/stamp_icons/large_stamp-chap.png differ
diff --git a/icons/stamp_icons/large_stamp-clown.png b/icons/stamp_icons/large_stamp-clown.png
index 5abbff7113..d606870507 100644
Binary files a/icons/stamp_icons/large_stamp-clown.png and b/icons/stamp_icons/large_stamp-clown.png differ
diff --git a/icons/stamp_icons/large_stamp-cmo.png b/icons/stamp_icons/large_stamp-cmo.png
index eb004be621..bac4c7b2f9 100644
Binary files a/icons/stamp_icons/large_stamp-cmo.png and b/icons/stamp_icons/large_stamp-cmo.png differ
diff --git a/icons/stamp_icons/large_stamp-deny.png b/icons/stamp_icons/large_stamp-deny.png
index 7c216fce48..1c7f416597 100644
Binary files a/icons/stamp_icons/large_stamp-deny.png and b/icons/stamp_icons/large_stamp-deny.png differ
diff --git a/icons/stamp_icons/large_stamp-hop.png b/icons/stamp_icons/large_stamp-hop.png
index 3f9aa4a76f..1447d58a87 100644
Binary files a/icons/stamp_icons/large_stamp-hop.png and b/icons/stamp_icons/large_stamp-hop.png differ
diff --git a/icons/stamp_icons/large_stamp-hos.png b/icons/stamp_icons/large_stamp-hos.png
index 67b69d7503..bd59590975 100644
Binary files a/icons/stamp_icons/large_stamp-hos.png and b/icons/stamp_icons/large_stamp-hos.png differ
diff --git a/icons/stamp_icons/large_stamp-law.png b/icons/stamp_icons/large_stamp-law.png
index d6d77eee9b..aee5aa3fbc 100644
Binary files a/icons/stamp_icons/large_stamp-law.png and b/icons/stamp_icons/large_stamp-law.png differ
diff --git a/icons/stamp_icons/large_stamp-mime.png b/icons/stamp_icons/large_stamp-mime.png
new file mode 100644
index 0000000000..c9a0143439
Binary files /dev/null and b/icons/stamp_icons/large_stamp-mime.png differ
diff --git a/icons/stamp_icons/large_stamp-ok.png b/icons/stamp_icons/large_stamp-ok.png
index e568ae0921..b40d3e3f1b 100644
Binary files a/icons/stamp_icons/large_stamp-ok.png and b/icons/stamp_icons/large_stamp-ok.png differ
diff --git a/icons/stamp_icons/large_stamp-qm.png b/icons/stamp_icons/large_stamp-qm.png
index ea863078b4..4ba31b3741 100644
Binary files a/icons/stamp_icons/large_stamp-qm.png and b/icons/stamp_icons/large_stamp-qm.png differ
diff --git a/icons/stamp_icons/large_stamp-rd.png b/icons/stamp_icons/large_stamp-rd.png
index 35479e805f..a9e7ad040b 100644
Binary files a/icons/stamp_icons/large_stamp-rd.png and b/icons/stamp_icons/large_stamp-rd.png differ
diff --git a/icons/stamp_icons/large_stamp-syndicate.png b/icons/stamp_icons/large_stamp-syndicate.png
new file mode 100644
index 0000000000..68f17d8f5e
Binary files /dev/null and b/icons/stamp_icons/large_stamp-syndicate.png differ
diff --git a/tgstation.dme b/tgstation.dme
index e5a59d5dde..e7eec0af7d 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -432,6 +432,7 @@
#include "code\datums\components\footstep.dm"
#include "code\datums\components\fried.dm"
#include "code\datums\components\gps.dm"
+#include "code\datums\components\honkspam.dm"
#include "code\datums\components\identification.dm"
#include "code\datums\components\igniter.dm"
#include "code\datums\components\infective.dm"
@@ -439,6 +440,7 @@
#include "code\datums\components\killerqueen.dm"
#include "code\datums\components\knockback.dm"
#include "code\datums\components\knockoff.dm"
+#include "code\datums\components\label.dm"
#include "code\datums\components\lifesteal.dm"
#include "code\datums\components\lockon_aiming.dm"
#include "code\datums\components\magnetic_catch.dm"
@@ -2836,6 +2838,7 @@
#include "code\modules\NTNet\network.dm"
#include "code\modules\NTNet\relays.dm"
#include "code\modules\NTNet\services\_service.dm"
+#include "code\modules\paperwork\carbonpaper.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\contract.dm"
#include "code\modules\paperwork\filingcabinet.dm"
@@ -2849,6 +2852,7 @@
#include "code\modules\paperwork\pen.dm"
#include "code\modules\paperwork\photocopier.dm"
#include "code\modules\paperwork\stamps.dm"
+#include "code\modules\paperwork\ticketmachine.dm"
#include "code\modules\photography\_pictures.dm"
#include "code\modules\photography\camera\camera.dm"
#include "code\modules\photography\camera\camera_image_capturing.dm"