diff --git a/_maps/snake.json b/_maps/snake.json
index e68d1cf09fe..8385d2be10d 100644
--- a/_maps/snake.json
+++ b/_maps/snake.json
@@ -1,5 +1,6 @@
{
"map_name": "NSV Snake",
+ "map_link": "Snake",
"map_path": "map_files/Snake",
"map_file": [
"snake_lower.dmm",
diff --git a/code/__DEFINES/devices.dm b/code/__DEFINES/devices.dm
index 179b9e93d78..6fba8aa4f7e 100644
--- a/code/__DEFINES/devices.dm
+++ b/code/__DEFINES/devices.dm
@@ -43,6 +43,7 @@
#define THEME_SYNDICATE "syndicate"
+/// Map of theme name -> theme ID
GLOBAL_LIST_INIT(ntos_device_themes_default, list(
"NtOS Default" = THEME_NTOS,
"Thinktronic Classic" = THEME_THINKTRONIC,
@@ -67,6 +68,39 @@ GLOBAL_LIST_INIT(ntos_device_themes_default, list(
"Retro" = THEME_RETRO
))
+// I hate BYOND lists. just let me reverse the map please
+/// Sanitization list for the database, allowed roundstart theme IDs
+GLOBAL_LIST_INIT(ntos_device_themes_default_content, list(
+ THEME_NTOS,
+ THEME_THINKTRONIC,
+ THEME_NTOS_LIGHT,
+ THEME_NTOS_DARK,
+ THEME_NTOS_RED,
+ THEME_NTOS_ORANGE,
+ THEME_NTOS_YELLOW,
+ THEME_NTOS_OLIVE,
+ THEME_NTOS_GREEN,
+ THEME_NTOS_TEAL,
+ THEME_NTOS_BLUE,
+ THEME_NTOS_VIOLET,
+ THEME_NTOS_PURPLE,
+ THEME_NTOS_PINK,
+ THEME_NTOS_BROWN,
+ THEME_NTOS_GREY,
+ THEME_NTOS_CLOWN_PINK,
+ THEME_NTOS_CLOWN_YELLOW,
+ THEME_NTOS_HACKERMAN,
+ THEME_HACKERMAN,
+ THEME_RETRO
+))
+
GLOBAL_LIST_INIT(ntos_device_themes_emagged, list(
"Syndix" = THEME_SYNDICATE
) + GLOB.ntos_device_themes_default)
+
+/// Reverse map of GLOB.ntos_device_themes_emagged
+/proc/theme_name_for_id(id)
+ for(var/key in GLOB.ntos_device_themes_emagged)
+ if(GLOB.ntos_device_themes_emagged[key] == id)
+ return key
+ return null
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index cb7c4fcf79d..6e093378fbe 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -207,15 +207,6 @@ GLOBAL_LIST_INIT(ghost_accs_options, list(GHOST_ACCS_NONE, GHOST_ACCS_DIR, GHOST
GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DEFAULT_SPRITE, GHOST_OTHERS_THEIR_SETTING)) //Same as ghost_accs_options.
-//pda fonts
-#define MONO "Monospaced"
-#define VT "VT323"
-#define ORBITRON "Orbitron"
-#define SHARE "Share Tech Mono"
-
-GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE)))
-
-
// Consider these images/atoms as part of the UI/HUD
#define APPEARANCE_UI_IGNORE_ALPHA (RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA|PIXEL_SCALE)
#define APPEARANCE_UI (RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|PIXEL_SCALE)
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index 30c8a7613f7..003ccf3e3db 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -179,7 +179,7 @@
#define PREFERENCE_TAG_PIXELSIZE "19"
#define PREFERENCE_TAG_SCALING_METHOD "20"
#define PREFERENCE_TAG_TIP_DELAY "21"
-#define PREFERENCE_TAG_PDA_STYLE "22"
+#define PREFERENCE_TAG_PDA_THEME "22"
#define PREFERENCE_TAG_PDA_COLOUR "23"
#define PREFERENCE_TAG_KEYBINDS "24"
#define PREFERENCE_TAG_PURCHASED_GEAR "25"
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index ea3dd54e959..5df30226e24 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -202,9 +202,9 @@
if (CONFIG_GET(flag/log_job_debug))
WRITE_LOG(GLOB.world_job_debug_log, "JOB: [text]")
-/proc/log_href_exploit(atom/user)
- WRITE_LOG(GLOB.href_exploit_attempt_log, "HREF: [key_name(user)] has potentially attempted an href exploit.")
- message_admins("[key_name_admin(user)] has potentially attempted an href exploit.")
+/proc/log_href_exploit(atom/user, data = "")
+ WRITE_LOG(GLOB.href_exploit_attempt_log, "HREF: [key_name(user)] has potentially attempted an href exploit.[data]")
+ message_admins("[key_name_admin(user)] has potentially attempted an href exploit.[data]")
/* Log to both DD and the logfile. */
/proc/log_world(text)
diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm
index c8158b21e2f..05625b8a166 100644
--- a/code/_onclick/drag_drop.dm
+++ b/code/_onclick/drag_drop.dm
@@ -74,7 +74,7 @@
var/obj/item/H = get_active_held_item()
if(H)
. = H.canItemMouseDown(object, location, params)
- else if(src.overmap_ship && (src.overmap_ship.gunner == src) || (GetComponent(/datum/component/overmap_gunning))) //NSV13 - let us mouse-down if we're a gunner
+ else if(src.overmap_ship && (src.overmap_ship.gunner == src || (GetComponent(/datum/component/overmap_gunning)))) //NSV13 - let us mouse-down if we're a ship operator
. = src.overmap_ship
/obj/item/proc/CanItemAutoclick(object, location, params)
diff --git a/code/datums/components/sound_player.dm b/code/datums/components/sound_player.dm
new file mode 100644
index 00000000000..ecbe804a9ea
--- /dev/null
+++ b/code/datums/components/sound_player.dm
@@ -0,0 +1,39 @@
+/**
+ * Sound Player component
+ *
+ * Component that will play a sound upon recieving some signal
+ */
+/datum/component/sound_player
+ ///Volume of the sound when played
+ var/volume
+ ///The list of sounds played, picked randomly.
+ var/list/sounds
+ ///Uses left before the sound player deletes itself. If set to a negative number that will mean infinite uses.
+ var/uses
+
+/datum/component/sound_player/Initialize(
+ volume = 30,
+ sounds = list('sound/items/bikehorn.ogg'),
+ uses = -1,
+ signal_list = list(COMSIG_ATOM_ATTACK_HAND),
+)
+ src.volume = volume
+ src.sounds = sounds
+ src.uses = uses
+
+ RegisterSignal(parent, signal_list, PROC_REF(play_sound))
+
+/**
+ * Attempt to play the sound on parent
+ *
+ * If out of uses, will qdel itself.
+ */
+/datum/component/sound_player/proc/play_sound()
+ SIGNAL_HANDLER
+
+ playsound(parent, pick(sounds), volume, TRUE)
+ if(uses <= -1)
+ return
+ uses--
+ if(!uses)
+ qdel(src)
diff --git a/code/datums/components/soundplayer.dm b/code/datums/components/soundplayer.dm
deleted file mode 100644
index ad52d1df3fe..00000000000
--- a/code/datums/components/soundplayer.dm
+++ /dev/null
@@ -1,41 +0,0 @@
-/*This is the sound_player component. It can be attached to any datum and register any signal to play the sound(s) you want, when you want. Used for the honk virus as an example
- Usage :
- target.AddComponent(/datum/component/sound_player, args)
- Arguments :
- custom_volume : Used to define a custom volume. Default : 30
- custom_sounds : Used to define a list of custom sounds that will be picked at random when play_sound() is triggered. Default : list('sound/items/bikehorn.ogg')
- amount : Used to define an amount of time the component will work before deleting itself. Default : -1
- signal_or_sig_list : Used to register the signal(s) you want to play the sound when they are sent. Default : None
-*/
-/datum/component/sound_player
- var/volume = 30
- var/list/sounds = list('sound/items/bikehorn.ogg')
- var/amount_left = -1
-
-/datum/component/sound_player/Initialize(custom_volume, custom_sounds, amount, signal_or_sig_list)
- if(!isnull(custom_volume))
- volume = custom_volume
-
- if(!isnull(custom_sounds))
- sounds = custom_sounds
-
- if(!isnull(amount))
- amount_left = amount
-
- RegisterSignal(parent, signal_or_sig_list, PROC_REF(play_sound)) //Registers all the signals in signal_or_sig_list.
-
-
-
-/*play_sound() os the proc that actually plays the sound.
- If amount_left is equal to -1, the component is infinite and will never delete itself.
-*/
-/datum/component/sound_player/proc/play_sound()
- playsound(parent, pickweight(sounds), volume, TRUE)
- switch(amount_left)
- if(-1)
- return
- if(1) //Last use.
- qdel(src)
- return
- else
- amount_left--
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index 62e6522ddc3..a87f9b30918 100644
--- a/code/datums/mood_events/generic_negative_events.dm
+++ b/code/datums/mood_events/generic_negative_events.dm
@@ -96,9 +96,11 @@
var/mob/living/T = L.parent
if(ishuman(T))
var/mob/living/carbon/human/H = T
- if(iscatperson(H))
- H.dna.species.start_wagging_tail(H)
- addtimer(CALLBACK(H.dna.species, TYPE_PROC_REF(/datum/species, stop_wagging_tail), H), 30)
+ if(iscatperson(H) || (istype(H.getorganslot(ORGAN_SLOT_EARS), /obj/item/organ/ears/cat) && istype(H.getorganslot(ORGAN_SLOT_TAIL), /obj/item/organ/tail/cat)))
+ var/obj/item/organ/tail/tail = H.getorganslot(ORGAN_SLOT_TAIL)
+ if(tail)
+ tail.set_wagging(H, TRUE)
+ addtimer(CALLBACK(tail, TYPE_PROC_REF(/obj/item/organ/tail, set_wagging), H, FALSE), 3 SECONDS)
description = "They want to play on the table!\n"
mood_change = 2
diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm
index f53736c34a6..927972aa065 100644
--- a/code/game/objects/items/granters.dm
+++ b/code/game/objects/items/granters.dm
@@ -59,7 +59,7 @@
return
if(do_after(user,50, user))
on_reading_finished(user)
- reading = FALSE
+ reading = FALSE
return TRUE
///ACTION BUTTONS///
diff --git a/code/modules/NTNet/network.dm b/code/modules/NTNet/network.dm
index a978f9730ab..90bbc61d2d0 100644
--- a/code/modules/NTNet/network.dm
+++ b/code/modules/NTNet/network.dm
@@ -316,12 +316,12 @@
#endif
// Checks whether NTNet operates. If parameter is passed checks whether specific function is enabled.
-/datum/ntnet/station_root/proc/check_function(specific_action = 0, zlevel)
+/datum/ntnet/station_root/proc/check_function(specific_action = 0, zlevel, ignore_relay = FALSE)
if(!SSnetworks.relays || !SSnetworks.relays.len) // No relays found. NTNet is down
return FALSE
// Check all relays. If we have at least one working relay, network is up.
- if(!SSnetworks.check_relay_operation(zlevel))
+ if(!ignore_relay && !SSnetworks.check_relay_operation(zlevel))
return FALSE
if(setting_disabled)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 05edbbc8cd1..11319ebfd6a 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -44,7 +44,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/ghost_accs = GHOST_ACCS_DEFAULT_OPTION
var/ghost_others = GHOST_OTHERS_DEFAULT_OPTION
var/preferred_map = null
- var/pda_style = MONO
+ var/pda_theme = THEME_NTOS
var/pda_color = "#808000"
// Custom Keybindings
@@ -623,8 +623,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Action Buttons: [(toggles2 & PREFTOGGLE_2_LOCKED_BUTTONS) ? "Locked In Place" : "Unlocked"]
"
dat += "Hotkey Mode: [(toggles2 & PREFTOGGLE_2_HOTKEYS) ? "Hotkeys" : "Default"]
"
dat += "
"
- dat += "PDA Color: Change
"
- dat += "PDA Style: [pda_style]
"
+ dat += "PDA Theme: [theme_name_for_id(pda_theme)]
"
+ dat += "PDA Classic Color: Change
"
dat += "
"
dat += "Crew Objectives: [(toggles2 & PREFTOGGLE_2_CREW_OBJECTIVES) ? "Yes" : "No"]
"
dat += "
"
@@ -1825,12 +1825,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
UI_style = pickedui
if (parent && parent.mob && parent.mob.hud_used)
parent.mob.hud_used.update_ui_style(ui_style2icon(UI_style))
- if("pda_style")
- var/pickedPDAStyle = input(user, "Choose your PDA style.", "Character Preference", pda_style) as null|anything in GLOB.pda_styles
+ if("pda_theme")
+ var/pickedPDAStyle = input(user, "Choose your default PDA theme.", "Character Preference", pda_theme) as null|anything in GLOB.ntos_device_themes_default
if(pickedPDAStyle)
- pda_style = pickedPDAStyle
+ pda_theme = GLOB.ntos_device_themes_default[pickedPDAStyle]
if("pda_color")
- var/pickedPDAColor = input(user, "Choose your PDA Interface color.", "Character Preference", pda_color) as color|null
+ var/pickedPDAColor = input(user, "Choose your default Thinktronic Classic theme background color.", "Character Preference", pda_color) as color|null
if(pickedPDAColor)
pda_color = pickedPDAColor
if ("see_balloon_alerts")
diff --git a/code/modules/client/preferences2/preferences2.dm b/code/modules/client/preferences2/preferences2.dm
index 1d80a5bdc56..3a4c4f1d983 100644
--- a/code/modules/client/preferences2/preferences2.dm
+++ b/code/modules/client/preferences2/preferences2.dm
@@ -77,7 +77,7 @@
READPREF_RAW(ghost_orbit, PREFERENCE_TAG_GHOST_ORBIT)
READPREF_RAW(ghost_accs, PREFERENCE_TAG_GHOST_ACCS)
READPREF_RAW(ghost_others, PREFERENCE_TAG_GHOST_OTHERS)
- READPREF_RAW(pda_style, PREFERENCE_TAG_PDA_STYLE)
+ READPREF_RAW(pda_theme, PREFERENCE_TAG_PDA_THEME)
READPREF_RAW(pda_color, PREFERENCE_TAG_PDA_COLOUR)
READPREF_RAW(preferred_syndie_role, PREFERENCE_TAG_PREFERRED_SYNDIE_ROLE) //NSV13
@@ -106,7 +106,7 @@
ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION)
be_special = SANITIZE_LIST(be_special)
- pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style))
+ pda_theme = sanitize_inlist(pda_theme, GLOB.ntos_device_themes_default_content, initial(pda_theme))
pda_color = sanitize_hexcolor(pda_color, 6, TRUE, initial(pda_color))
preferred_syndie_role = sanitize_text(preferred_syndie_role, CONQUEST_ROLE_GRUNT) //NSV13
@@ -147,7 +147,7 @@
PREP_WRITEPREF_RAW(parallax, PREFERENCE_TAG_PARALLAX)
PREP_WRITEPREF_RAW(pixel_size, PREFERENCE_TAG_PIXELSIZE)
PREP_WRITEPREF_RAW(tip_delay, PREFERENCE_TAG_TIP_DELAY)
- PREP_WRITEPREF_RAW(pda_style, PREFERENCE_TAG_PDA_STYLE)
+ PREP_WRITEPREF_RAW(pda_theme, PREFERENCE_TAG_PDA_THEME)
PREP_WRITEPREF_RAW(pda_color, PREFERENCE_TAG_PDA_COLOUR)
PREP_WRITEPREF_RAW(preferred_syndie_role, PREFERENCE_TAG_PREFERRED_SYNDIE_ROLE) //NSV13
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 2f766dda011..a3f22576b09 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -101,25 +101,22 @@
if(!.)
return
var/mob/living/carbon/human/H = user
- if(!istype(H) || !H.dna || !H.dna.species || !H.dna.species.can_wag_tail(H))
+ var/obj/item/organ/tail/tail = H?.getorganslot(ORGAN_SLOT_TAIL)
+ if(!tail)
return
- if(!H.dna.species.is_wagging_tail())
- H.dna.species.start_wagging_tail(H)
- else
- H.dna.species.stop_wagging_tail(H)
+ tail.toggle_wag(H)
/datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE , intentional)
if(!..())
return FALSE
var/mob/living/carbon/human/H = user
- return H.dna && H.dna.species && H.dna.species.can_wag_tail(user)
+ return istype(H?.getorganslot(ORGAN_SLOT_TAIL), /obj/item/organ/tail)
/datum/emote/living/carbon/human/wag/select_message_type(mob/user, intentional)
. = ..()
var/mob/living/carbon/human/H = user
- if(!H.dna || !H.dna.species)
- return
- if(H.dna.species.is_wagging_tail())
+ var/obj/item/organ/tail/tail = H.getorganslot(ORGAN_SLOT_TAIL)
+ if(tail?.is_wagging(H))
. = null
/datum/emote/living/carbon/human/wing
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 69aacdc66c0..3f46cddf200 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -2086,15 +2086,9 @@ GLOBAL_LIST_EMPTY(roundstart_races)
//Tail Wagging//
////////////////
-/datum/species/proc/can_wag_tail(mob/living/carbon/human/H)
- return FALSE
-
-/datum/species/proc/is_wagging_tail(mob/living/carbon/human/H)
- return FALSE
-
-/datum/species/proc/start_wagging_tail(mob/living/carbon/human/H)
-
/datum/species/proc/stop_wagging_tail(mob/living/carbon/human/H)
+ var/obj/item/organ/tail/tail = H?.getorganslot(ORGAN_SLOT_TAIL)
+ tail?.set_wagging(H, FALSE)
///////////////
//FLIGHT SHIT//
diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm
index ad7101ace17..d851dc73637 100644
--- a/code/modules/mob/living/carbon/human/species_types/felinid.dm
+++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm
@@ -31,24 +31,6 @@
stop_wagging_tail(H)
. = ..()
-/datum/species/human/felinid/can_wag_tail(mob/living/carbon/human/H)
- return ("tail_human" in mutant_bodyparts) || ("waggingtail_human" in mutant_bodyparts)
-
-/datum/species/human/felinid/is_wagging_tail(mob/living/carbon/human/H)
- return ("waggingtail_human" in mutant_bodyparts)
-
-/datum/species/human/felinid/start_wagging_tail(mob/living/carbon/human/H)
- if("tail_human" in mutant_bodyparts)
- mutant_bodyparts -= "tail_human"
- mutant_bodyparts |= "waggingtail_human"
- H.update_body()
-
-/datum/species/human/felinid/stop_wagging_tail(mob/living/carbon/human/H)
- if("waggingtail_human" in mutant_bodyparts)
- mutant_bodyparts -= "waggingtail_human"
- mutant_bodyparts |= "tail_human"
- H.update_body()
-
/datum/species/human/felinid/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
if(ishuman(C))
var/mob/living/carbon/human/H = C
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index d927395ede2..0919b024e28 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -53,28 +53,6 @@
stop_wagging_tail(H)
. = ..()
-/datum/species/lizard/can_wag_tail(mob/living/carbon/human/H)
- return ("tail_lizard" in mutant_bodyparts) || ("waggingtail_lizard" in mutant_bodyparts)
-
-/datum/species/lizard/is_wagging_tail(mob/living/carbon/human/H)
- return ("waggingtail_lizard" in mutant_bodyparts)
-
-/datum/species/lizard/start_wagging_tail(mob/living/carbon/human/H)
- if("tail_lizard" in mutant_bodyparts)
- mutant_bodyparts -= "tail_lizard"
- mutant_bodyparts -= "spines"
- mutant_bodyparts |= "waggingtail_lizard"
- mutant_bodyparts |= "waggingspines"
- H.update_body()
-
-/datum/species/lizard/stop_wagging_tail(mob/living/carbon/human/H)
- if("waggingtail_lizard" in mutant_bodyparts)
- mutant_bodyparts -= "waggingtail_lizard"
- mutant_bodyparts -= "waggingspines"
- mutant_bodyparts |= "tail_lizard"
- mutant_bodyparts |= "spines"
- H.update_body()
-
/*
Lizard subspecies: ASHWALKERS
*/
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index 3796b34677d..5beb7149961 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -24,6 +24,8 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
var/device_theme = THEME_NTOS
/// Whether this device is allowed to change themes or not.
var/theme_locked = FALSE
+ /// If the theme should not be initialized from theme prefs (for custom job themes)
+ var/ignore_theme_pref = FALSE
/// List of themes for this device to allow.
var/list/allowed_themes
/// Color used for the Thinktronic Classic theme.
@@ -61,12 +63,14 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
/// Number of total expansion bays this computer has available.
var/max_bays = 0
+ /// If we can imprint IDs on this device
+ var/can_save_id = FALSE
/// The currently imprinted ID.
var/saved_identification = null
/// The currently imprinted job.
var/saved_job = null
/// If the saved info should auto-update
- var/saved_auto_imprint = TRUE
+ var/saved_auto_imprint = FALSE
/// The amount of honks. honk honk honk honk honk honkh onk honkhnoohnk
var/honk_amount = 0
/// Idle programs on background. They still receive process calls but can't be interacted with.
@@ -95,8 +99,8 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
var/can_store_pai = FALSE
/obj/item/modular_computer/Initialize(mapload)
- . = ..()
allowed_themes = GLOB.ntos_device_themes_default
+ . = ..()
START_PROCESSING(SSobj, src)
if(!physical)
physical = src
@@ -115,9 +119,10 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
id.UpdateDisplay()
/obj/item/modular_computer/proc/on_id_insert()
+ ui_update()
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
// We shouldn't auto-imprint if ID modification is open.
- if(!saved_auto_imprint || !cardholder || istype(active_program, /datum/computer_file/program/card_mod))
+ if(!can_save_id || !saved_auto_imprint || !cardholder || istype(active_program, /datum/computer_file/program/card_mod))
return
if(cardholder.current_identification == saved_identification && cardholder.current_job == saved_job)
return
@@ -256,10 +261,14 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
newemag = TRUE
if(newemag)
to_chat(user, "You swipe \the [src]. A console window momentarily fills the screen, with white text rapidly scrolling past.")
+ kill_program(forced = TRUE, update = FALSE)
+
var/datum/computer_file/program/emag_console/emag_console = new(src)
emag_console.computer = src
emag_console.program_state = PROGRAM_STATE_ACTIVE
- emag_console.ui_interact(user)
+ active_program = emag_console
+ ui_interact(user)
+ update_icon()
return TRUE
to_chat(user, "You swipe \the [src]. A console window fills the screen, but it quickly closes itself after only a few lines are written to it.")
return FALSE
@@ -292,14 +301,6 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
add_overlay(mutable_appearance(init_icon, "bsod"))
add_overlay(mutable_appearance(init_icon, "broken"))
-
-// On-click handling. Turns on the computer if it's off and opens the GUI.
-/obj/item/modular_computer/interact(mob/user)
- if(enabled)
- ui_interact(user)
- else
- turn_on(user)
-
/obj/item/modular_computer/proc/turn_on(mob/user, open_ui = TRUE)
if(enabled)
if(open_ui)
@@ -451,32 +452,33 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
if(3)
data["PC_ntneticon"] = "sig_lan.gif"
- if(length(idle_threads))
- var/list/program_headers = list()
- for(var/I in idle_threads)
- var/datum/computer_file/program/P = I
- if(!P.ui_header)
- continue
- program_headers.Add(list(list(
- "icon" = P.ui_header
- )))
+ var/list/program_headers = list()
+ for(var/datum/computer_file/program/P as anything in idle_threads)
+ if(!P?.ui_header)
+ continue
+ program_headers.Add(list(list(
+ "icon" = P.ui_header
+ )))
- data["PC_programheaders"] = program_headers
+ data["PC_programheaders"] = program_headers
- data["PC_stationtime"] = station_time_timestamp()
+ data["PC_stationdate"] = "[time2text(world.realtime, "DDD, Month DD")], [GLOB.year_integer+YEAR_OFFSET]"
data["PC_hasheader"] = 1
data["PC_showexitprogram"] = active_program ? 1 : 0 // Hides "Exit Program" button on mainscreen
return data
// Relays kill program request to currently active program. Use this to quit current program.
-/obj/item/modular_computer/proc/kill_program(forced = FALSE)
+/obj/item/modular_computer/proc/kill_program(forced = FALSE, update = TRUE)
if(active_program)
+ if(active_program in idle_threads)
+ idle_threads.Remove(active_program)
active_program.kill_program(forced)
active_program = null
- var/mob/user = usr
- if(user && istype(user))
- ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
- update_icon()
+ if(update)
+ var/mob/user = usr
+ if(user && istype(user))
+ ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
+ update_icon()
/obj/item/modular_computer/proc/open_program(mob/user, datum/computer_file/program/program, in_background = FALSE)
if(program.computer != src)
@@ -497,7 +499,6 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
program.alert_pending = FALSE
idle_threads.Remove(program)
update_icon()
- updateUsrDialog()
return TRUE
else if(program in idle_threads)
return TRUE
@@ -516,7 +517,7 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
if(!in_background)
active_program = program
program.alert_pending = FALSE
- updateUsrDialog()
+ ui_interact(user)
else
program.program_state = PROGRAM_STATE_BACKGROUND
idle_threads.Add(program)
@@ -604,6 +605,7 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
tool.play_tool_sound(user, volume=20)
uninstall_component(H, user, TRUE)
+ ui_update()
return
/obj/item/modular_computer/attackby(obj/item/attacking_item, mob/user, params)
@@ -620,12 +622,14 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
saved_image = pic.picture
messenger.ProcessPhoto()
to_chat(user, "You scan \the [pic] into \the [src]'s messenger.")
+ ui_update()
return
// Insert items into the components
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
if(H.try_insert(attacking_item, user))
+ ui_update()
return
// Insert a pAI card
@@ -645,6 +649,7 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
if(istype(inserted_hardware) && upgradable)
if(install_component(inserted_hardware, user))
inserted_hardware.on_inserted(user)
+ ui_update()
return
if(attacking_item.tool_behaviour == TOOL_WRENCH)
diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm
index 686f14ebca3..c5ee063727e 100644
--- a/code/modules/modular_computers/computers/item/computer_ui.dm
+++ b/code/modules/modular_computers/computers/item/computer_ui.dm
@@ -1,3 +1,9 @@
+/obj/item/modular_computer/interact(mob/user)
+ if(enabled)
+ ui_interact(user)
+ else
+ turn_on(user)
+
// Operates TGUI
/obj/item/modular_computer/ui_state(mob/user)
@@ -10,14 +16,10 @@
)
/obj/item/modular_computer/ui_interact(mob/user, datum/tgui/ui)
- if(!enabled)
+ if(!enabled || !user.is_literate() || !use_power())
if(ui)
ui.close()
- return FALSE
- if(!use_power())
- if(ui)
- ui.close()
- return FALSE
+ return
// Robots don't really need to see the screen, their wireless connection works as long as computer is on.
if(!screen_on && !issilicon(user))
@@ -25,13 +27,6 @@
ui.close()
return FALSE
- // If we have an active program switch to it now.
- if(active_program)
- if(ui) // This is the main laptop screen. Since we are switching to program's UI close it for now.
- ui.close()
- active_program.ui_interact(user)
- return
-
// We are still here, that means there is no program loaded. Load the BIOS/ROM/OS/whatever you want to call it.
// This screen simply lists available programs and user may select them.
var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
@@ -44,15 +39,53 @@
playsound(src, 'sound/items/bikehorn.ogg', 30, TRUE)
ui = SStgui.try_update_ui(user, src, ui)
- if (!ui)
- ui = new(user, src, "NtosMain")
- ui.set_autoupdate(TRUE)
- if(ui.open())
- ui.send_asset(get_asset_datum(/datum/asset/simple/headers))
+ if(!ui)
+ if(active_program)
+ ui = new(user, src, active_program.tgui_id, active_program.filedesc)
+ ui.set_autoupdate(TRUE)
+ else
+ ui = new(user, src, "NtosMain")
+ ui.set_autoupdate(TRUE)
+ ui.open()
+ return
+
+ var/old_open_ui = ui.interface
+ if(active_program)
+ ui.interface = active_program.tgui_id
+ ui.title = active_program.filedesc
+ else
+ ui.interface = "NtosMain"
+ //opened a new UI
+ if(old_open_ui != ui.interface)
+ update_static_data(user, ui) // forces a static UI update for the new UI
+ ui.send_assets() // sends any new asset datums from the new UI
+ if(active_program)
+ active_program.on_ui_create(user, ui)
+
+/obj/item/modular_computer/ui_close(mob/user, datum/tgui/tgui)
+ if(active_program)
+ active_program.on_ui_close(user, tgui)
+
+/obj/item/modular_computer/ui_assets(mob/user)
+ var/list/data = list()
+ data += get_asset_datum(/datum/asset/simple/headers)
+ if(active_program)
+ data += active_program.ui_assets(user)
+ return data
+
+/obj/item/modular_computer/ui_static_data(mob/user)
+ . = ..()
+ var/list/data = list()
+ if(active_program)
+ data += active_program.ui_static_data(user)
+ return data
+ return data
/obj/item/modular_computer/ui_data(mob/user)
var/list/data = get_header_data()
- data["device_theme"] = device_theme
+ if(active_program)
+ data += active_program.ui_data(user)
+ return data
data["login"] = list()
data["disk"] = null
@@ -88,11 +121,11 @@
data["disk_name"] = ssd.name
for(var/datum/computer_file/program/prog in ssd.stored_files)
- var/running = FALSE
+ var/background_running = FALSE
if(prog in idle_threads)
- running = TRUE
+ background_running = TRUE
- data["disk_programs"] += list(list("name" = prog.filename, "desc" = prog.filedesc, "running" = running, "icon" = prog.program_icon, "alert" = prog.alert_pending))
+ data["disk_programs"] += list(list("name" = prog.filename, "desc" = prog.filedesc, "running" = background_running, "icon" = prog.program_icon, "alert" = prog.alert_pending))
data["removable_media"] = list()
if(all_components[MC_SDD])
@@ -107,11 +140,11 @@
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)
- var/running = 0
+ var/background_running = FALSE
if(P in idle_threads)
- running = 1
+ background_running = TRUE
- data["programs"] += list(list("name" = P.filename, "desc" = P.filedesc, "running" = running, "icon" = P.program_icon, "alert" = P.alert_pending))
+ data["programs"] += list(list("name" = P.filename, "desc" = P.filedesc, "running" = background_running, "icon" = P.program_icon, "alert" = P.alert_pending))
data["has_light"] = has_light
data["light_on"] = light_on
@@ -120,7 +153,7 @@
// Handles user's GUI input
-/obj/item/modular_computer/ui_act(action, params)
+/obj/item/modular_computer/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
if(device_theme == THEME_THINKTRONIC)
@@ -134,32 +167,29 @@
shutdown_computer()
return TRUE
if("PC_minimize")
- var/mob/user = usr
if(!active_program || !all_components[MC_CPU])
return
idle_threads.Add(active_program)
active_program.program_state = PROGRAM_STATE_BACKGROUND // Should close any existing UIs
-
active_program = null
+ if(ismob(usr))
+ ui_interact(usr) // Re-open the UI on this computer. It should show the main screen now.
update_icon()
- if(user && istype(user))
- ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
-
+ return TRUE
if("PC_killprogram")
var/prog = params["name"]
- var/datum/computer_file/program/P = null
- var/mob/user = usr
+ var/datum/computer_file/program/killed_program = null
if(hard_drive)
- P = hard_drive.find_file_by_name(prog)
+ killed_program = hard_drive.find_file_by_name(prog)
- if(!istype(P) || P.program_state == PROGRAM_STATE_KILLED)
+ if(!istype(killed_program) || killed_program.program_state == PROGRAM_STATE_KILLED)
return
-
- P.kill_program(forced = TRUE)
- to_chat(user, "Program [P.filename].[P.filetype] with PID [rand(100,999)] has been killed.")
+ if(killed_program in idle_threads)
+ idle_threads.Remove(killed_program)
+ killed_program.kill_program(forced = TRUE)
+ to_chat(usr, "Program [killed_program.filename].[killed_program.filetype] with PID [rand(100,999)] has been killed.")
return TRUE
-
if("PC_runprogram")
var/is_disk = params["is_disk"]
var/datum/computer_file/program/program
@@ -201,34 +231,39 @@
return
if(uninstall_component(portable_drive, usr, TRUE))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50)
+ return TRUE
if("job disk")
var/obj/item/computer_hardware/hard_drive/role/ssd = all_components[MC_HDD_JOB]
if(!ssd)
return
if(uninstall_component(ssd, usr, TRUE))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50)
+ return TRUE
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/terminal_insert_disc.ogg', 50)
+ return TRUE
if("ID")
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
if(!cardholder)
return
if(cardholder.try_eject(user))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50)
+ return TRUE
if("secondary RFID card")
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD2]
if(!cardholder)
return
if(cardholder.try_eject(user))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50)
+ return TRUE
if("PC_Imprint_ID")
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
- if(!cardholder)
- return
+ if(!cardholder || !can_save_id)
+ return TRUE
saved_identification = cardholder.current_identification
saved_job = cardholder.current_job
@@ -237,10 +272,12 @@
playsound(src, 'sound/machines/terminal_processing.ogg', 15, TRUE)
addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(playsound), src, 'sound/machines/terminal_success.ogg', 15, TRUE), 1.3 SECONDS)
+ return TRUE
if("PC_Toggle_Auto_Imprint")
saved_auto_imprint = !saved_auto_imprint
if(saved_auto_imprint)
on_id_insert()
+ return TRUE
if("PC_Pai_Interact")
if(!can_store_pai || !istype(stored_pai_card))
return
@@ -251,8 +288,9 @@
remove_pai()
to_chat(usr, "You remove the pAI from [src].")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50)
- else
- return
+ return TRUE
+ if(active_program)
+ return active_program.ui_act(action, params, ui, state)
/obj/item/modular_computer/ui_host()
if(physical)
diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm
index d5b2646895f..e303437b804 100644
--- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm
+++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm
@@ -9,6 +9,7 @@
var/list/slip_victims = list()
init_ringtone = "honk"
device_theme = THEME_NTOS_CLOWN_PINK // Give the clown the best theme
+ ignore_theme_pref = TRUE
/obj/item/modular_computer/tablet/pda/clown/ComponentInitialize()
. = ..()
@@ -199,6 +200,13 @@
device_theme = THEME_SYNDICATE
theme_locked = TRUE
+/obj/item/modular_computer/tablet/pda/syndicate/Initialize(mapload)
+ . = ..()
+ var/obj/item/computer_hardware/network_card/network_card = all_components[MC_NET]
+ if(istype(network_card))
+ forget_component(network_card)
+ install_component(new /obj/item/computer_hardware/network_card/advanced/norelay)
+
/obj/item/modular_computer/tablet/pda/chaplain
name = "chaplain PDA"
icon_state = "pda-chaplain"
diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm
index 67c72fd1a48..b37c2a1b3e9 100644
--- a/code/modules/modular_computers/computers/item/tablet.dm
+++ b/code/modules/modular_computers/computers/item/tablet.dm
@@ -14,6 +14,8 @@
has_light = TRUE //LED flashlight!
comp_light_luminosity = 2.3 //Same as the PDA
interaction_flags_atom = INTERACT_ATOM_ALLOW_USER_LOCATION
+ can_save_id = TRUE
+ saved_auto_imprint = TRUE
var/has_variants = TRUE
var/finish_color = null
@@ -60,6 +62,7 @@
qdel(stored_paper)
stored_paper = paper.copy(src)
to_chat(user, "Paper scanned. Saved to PDA's notekeeper.")
+ ui_update()
return TRUE
/obj/item/modular_computer/tablet/attackby(obj/item/attacking_item, mob/user)
@@ -83,9 +86,11 @@
/obj/item/modular_computer/tablet/pre_attack(atom/target, mob/living/user, params)
if(try_scan_paper(target, user))
return FALSE
+ var/obj/item/computer_hardware/hard_drive/role/job_disk = all_components[MC_HDD_JOB]
+ if(istype(job_disk) && !job_disk.process_pre_attack(target, user, params))
+ return FALSE
return ..()
-
/obj/item/modular_computer/tablet/attack(atom/target, mob/living/user, params)
// Send to programs for processing - this should go LAST
// Used to implement the physical scanner.
@@ -354,8 +359,16 @@
. = ..()
if(equipped || !user.client)
return
- classic_color = user.client.prefs.pda_color
equipped = TRUE
+ if(!user.client.prefs)
+ return
+ var/pref_theme = user.client.prefs.pda_theme
+ if(!theme_locked && !ignore_theme_pref)
+ for(var/key in allowed_themes) // i am going to scream. DM lists stop sucking please
+ if(allowed_themes[key] == pref_theme)
+ device_theme = pref_theme
+ break
+ classic_color = user.client.prefs.pda_color
/obj/item/modular_computer/tablet/pda/update_icon()
..()
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index ad4f9feb13b..27964c4c583 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -134,17 +134,6 @@
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.
- **/
-/datum/computer_file/program/proc/get_header_data()
- if(computer)
- return computer.get_header_data()
- return list()
-
/**
* Called on program startup.
*
@@ -190,71 +179,6 @@
generate_network_log("Connection to [network_destination] closed.")
return 1
-/datum/computer_file/program/ui_assets(mob/user)
- return list(
- get_asset_datum(/datum/asset/simple/headers),
- )
-
-/datum/computer_file/program/ui_state(mob/user)
- return GLOB.default_state
-
-/datum/computer_file/program/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui && tgui_id)
- ui = new(user, src, tgui_id, filedesc)
- ui.set_autoupdate(TRUE)
- if(ui.open())
- ui.send_asset(get_asset_datum(/datum/asset/simple/headers))
-
-// CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC:
-// Topic calls are automagically forwarded from NanoModule this program contains.
-// Calls beginning with "PRG_" are reserved for programs handling.
-// Calls beginning with "PC_" are reserved for computer handling (by whatever runs the program)
-// ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE.
-/datum/computer_file/program/ui_act(action,params,datum/tgui/ui)
- if(..())
- return TRUE
- if(computer)
- if(computer.device_theme == THEME_THINKTRONIC)
- computer.send_select_sound()
- switch(action)
- if("PC_exit")
- computer.kill_program()
- ui.close()
- return TRUE
- if("PC_shutdown")
- computer.shutdown_computer()
- ui.close()
- return TRUE
- if("PC_minimize")
- var/mob/user = usr
- if(!computer.active_program || !computer.all_components[MC_CPU])
- return
-
- computer.idle_threads.Add(computer.active_program)
- program_state = PROGRAM_STATE_BACKGROUND // Should close any existing UIs
-
- computer.active_program = null
- computer.update_icon()
- ui.close()
-
- if(user && istype(user))
- computer.ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
- return TRUE
-
-
-/datum/computer_file/program/ui_host()
- if(computer)
- if(computer.physical)
- return computer.physical
- return computer
- return ..()
-
-/datum/computer_file/program/ui_status(mob/user)
- if(program_state != PROGRAM_STATE_ACTIVE) // Our program was closed. Close the ui if it exists.
- return UI_CLOSE
- return ..()
-
/// Return TRUE if nothing was processed. Return FALSE to prevent further actions running.
/// Set use_attack = TRUE to receive proccalls from the parent computer.
/datum/computer_file/program/proc/attack(atom/target, mob/living/user, params)
@@ -264,3 +188,11 @@
/// Set use_attack_obj = TRUE to receive proccalls from the parent computer.
/datum/computer_file/program/proc/attack_obj(obj/target, mob/living/user)
return TRUE
+
+/// Called when the datum/tgui is initialized by the computer
+/datum/computer_file/program/proc/on_ui_create(mob/user, datum/tgui/ui)
+ return
+
+/// Called when ui_close is called on the computer while this program is active. Any behavior in this should also be in kill_program.
+/datum/computer_file/program/proc/on_ui_close(mob/user, datum/tgui/ui)
+ return
diff --git a/code/modules/modular_computers/file_system/programs/airestorer.dm b/code/modules/modular_computers/file_system/programs/airestorer.dm
index a13a4ff9147..0af159655be 100644
--- a/code/modules/modular_computers/file_system/programs/airestorer.dm
+++ b/code/modules/modular_computers/file_system/programs/airestorer.dm
@@ -90,7 +90,7 @@
/datum/computer_file/program/aidiag/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/mob/living/silicon/ai/AI = get_ai()
var/obj/item/aicard/aicard = get_ai(2)
diff --git a/code/modules/modular_computers/file_system/programs/alarm.dm b/code/modules/modular_computers/file_system/programs/alarm.dm
index 59eefd18565..fc56d97d14b 100644
--- a/code/modules/modular_computers/file_system/programs/alarm.dm
+++ b/code/modules/modular_computers/file_system/programs/alarm.dm
@@ -27,7 +27,7 @@
return 1
/datum/computer_file/program/alarm_monitor/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
data["alarms"] = list()
for(var/class in GLOB.alarms)
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 e7858d8cccc..4ef00c4ce3d 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
@@ -126,7 +126,6 @@
if (hard_drive && hard_drive.traitor_data != null)
var/datum/antagonist/traitor/traitor_data = hard_drive.traitor_data
- data += get_header_data()
if (traitor_data.contractor_hub.current_contract)
data["ongoing_contract"] = TRUE
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
index 6f3be85d00b..9ae761571c7 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
@@ -73,7 +73,7 @@
if(!SSnetworks.station_network)
return
- var/list/data = get_header_data()
+ var/list/data = list()
data["error"] = error
if(target && executed)
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/emag.dm b/code/modules/modular_computers/file_system/programs/antagonist/emag.dm
index 7dbab341d2f..7fa2aecc6e0 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/emag.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/emag.dm
@@ -8,15 +8,14 @@
available_on_ntnet = FALSE
tgui_id = "NtosEmagConsole"
-/datum/computer_file/program/emag_console/ui_data(mob/user)
- return get_header_data()
-
/datum/computer_file/program/emag_console/ui_act(action,params,datum/tgui/ui)
if(!ui || ui.status != UI_INTERACTIVE)
return TRUE
+ kill_program(forced = TRUE)
+ return TRUE
+
+/datum/computer_file/program/emag_console/kill_program(forced)
+ . = ..()
if(computer)
computer.device_theme = THEME_SYNDICATE
computer.allowed_themes = GLOB.ntos_device_themes_emagged
- // bye bye UI
- qdel(src)
- return TRUE
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 5dcf3e19a17..3d5cb20db16 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
@@ -72,7 +72,7 @@
return temp
/datum/computer_file/program/revelation/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
data["armed"] = armed
diff --git a/code/modules/modular_computers/file_system/programs/arcade.dm b/code/modules/modular_computers/file_system/programs/arcade.dm
index 622140a76ee..403d6cb01a5 100644
--- a/code/modules/modular_computers/file_system/programs/arcade.dm
+++ b/code/modules/modular_computers/file_system/programs/arcade.dm
@@ -81,7 +81,7 @@
)
/datum/computer_file/program/arcade/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
data["Hitpoints"] = boss_hp
data["PlayerHitpoints"] = player_hp
data["PlayerMP"] = player_mp
diff --git a/code/modules/modular_computers/file_system/programs/atmosscan.dm b/code/modules/modular_computers/file_system/programs/atmosscan.dm
index c6ad5c039a0..10b2f2e7efc 100644
--- a/code/modules/modular_computers/file_system/programs/atmosscan.dm
+++ b/code/modules/modular_computers/file_system/programs/atmosscan.dm
@@ -18,9 +18,9 @@
/datum/computer_file/program/atmosscan/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/list/airlist = list()
- var/turf/T = get_turf(ui_host())
+ var/turf/T = get_turf(computer.ui_host())
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()
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 c6dc672ab1e..dd809b038c4 100644
--- a/code/modules/modular_computers/file_system/programs/borg_monitor.dm
+++ b/code/modules/modular_computers/file_system/programs/borg_monitor.dm
@@ -22,7 +22,7 @@
/datum/computer_file/program/borg_monitor/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
// Syndicate version doesn't require an ID - so we use this proc instead of computer.GetID()
data["card"] = !!get_id_name()
@@ -61,13 +61,13 @@
if("messagebot")
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
if(!istype(R))
- return
+ return TRUE
var/sender_name = get_id_name()
if(!sender_name)
// This can only happen if the action somehow gets called as UI blocks this action with no ID
computer.visible_message("Insert an ID to send messages.")
playsound(usr, 'sound/machines/terminal_error.ogg', 15, TRUE)
- return
+ return TRUE
if(R.stat == DEAD) //Dead borgs will listen to you no longer
to_chat(usr, "Error -- Could not open a connection to unit:[R]")
var/message = stripped_input(usr, message = "Enter message to be sent to remote cyborg.", title = "Send Message")
@@ -85,6 +85,7 @@
SEND_SOUND(R.connected_ai, 'sound/machines/twobeep_high.ogg')
R.logevent("Message from [sender_name] -- \"[message]\"")
usr.log_talk(message, LOG_PDA, tag="Cyborg Monitor Program: ID name \"[sender_name]\" to [R]")
+ return TRUE
///This proc is used to determin if a borg should be shown in the list (based on the borg's scrambledcodes var). Syndicate version overrides this to show only syndicate borgs.
/datum/computer_file/program/borg_monitor/proc/evaluate_borg(mob/living/silicon/robot/R)
diff --git a/code/modules/modular_computers/file_system/programs/borg_self_monitor.dm b/code/modules/modular_computers/file_system/programs/borg_self_monitor.dm
index 1fd66dd63d4..81390787195 100644
--- a/code/modules/modular_computers/file_system/programs/borg_self_monitor.dm
+++ b/code/modules/modular_computers/file_system/programs/borg_self_monitor.dm
@@ -31,7 +31,7 @@
return FALSE
/datum/computer_file/program/borg_self_monitor/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
if(!iscyborg(user))
return data
var/mob/living/silicon/robot/borgo = tablet.borgo
diff --git a/code/modules/modular_computers/file_system/programs/budgetordering.dm b/code/modules/modular_computers/file_system/programs/budgetordering.dm
index 397c36a0d22..b10f9232bc4 100644
--- a/code/modules/modular_computers/file_system/programs/budgetordering.dm
+++ b/code/modules/modular_computers/file_system/programs/budgetordering.dm
@@ -48,8 +48,7 @@
return TRUE
/datum/computer_file/program/budgetorders/ui_data(mob/user)
- . = ..()
- var/list/data = get_header_data()
+ var/list/data = list()
data["location"] = SSshuttle.supply.getStatusText()
data["department"] = "Cargo" //NSV13
var/datum/bank_account/buyer = SSeconomy.get_dep_account(ACCOUNT_CAR)
diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm
index ab1646a33a5..761cbda614e 100644
--- a/code/modules/modular_computers/file_system/programs/card.dm
+++ b/code/modules/modular_computers/file_system/programs/card.dm
@@ -350,7 +350,7 @@
return data
/datum/computer_file/program/card_mod/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
data["station_name"] = station_name()
diff --git a/code/modules/modular_computers/file_system/programs/cargobounty.dm b/code/modules/modular_computers/file_system/programs/cargobounty.dm
index 4d6fb60dd1c..43195dee272 100644
--- a/code/modules/modular_computers/file_system/programs/cargobounty.dm
+++ b/code/modules/modular_computers/file_system/programs/cargobounty.dm
@@ -11,23 +11,23 @@
tgui_id = "NtosBountyConsole"
program_icon = "tags"
- ///cooldown var for printing paper sheets.
- var/printer_ready = 0
- ///The cargo account for grabbing the cargo account's credits.
+ /// Cooldown var for printing paper sheets.
+ COOLDOWN_DECLARE(printer_ready)
+ /// The cargo account for grabbing the cargo account's credits.
var/static/datum/bank_account/cargocash
/datum/computer_file/program/bounty/proc/print_paper()
new /obj/item/paper/bounty_printout(get_turf(computer))
-/datum/computer_file/program/bounty/ui_interact(mob/user, datum/tgui/ui)
+/datum/computer_file/program/bounty/on_ui_create(mob/user, datum/tgui/ui)
+ COOLDOWN_START(src, printer_ready, PRINTER_TIMEOUT)
+
+/datum/computer_file/program/bounty/ui_data(mob/user)
+ var/list/data = list()
+
if(!GLOB.bounties_list.len)
setup_bounties()
- printer_ready = world.time + PRINTER_TIMEOUT
cargocash = SSeconomy.get_dep_account(ACCOUNT_CAR)
- . = ..()
-
-/datum/computer_file/program/bounty/ui_data(mob/user)
- var/list/data = get_header_data()
var/obj/item/computer_hardware/printer/printer
if(computer)
@@ -48,7 +48,7 @@
data["has_printer"] = printer ? TRUE : FALSE
- data["stored_cash"] = cargocash.account_balance
+ data["stored_cash"] = cargocash ? cargocash.account_balance : 0
data["bountydata"] = bountyinfo
return data
@@ -63,6 +63,9 @@
cashmoney.claim()
return TRUE
if("Print")
+ if(!COOLDOWN_FINISHED(src, printer_ready))
+ to_chat(usr, "The printer is not ready to print yet!")
+ return
var/obj/item/computer_hardware/printer/printer
if(computer)
printer = computer.all_components[MC_PRINT]
@@ -72,4 +75,5 @@
to_chat(usr, "Hardware error: Printer was unable to print the file. It may be out of paper.")
return
else
+ COOLDOWN_START(src, printer_ready, PRINTER_TIMEOUT)
computer.visible_message("\The [computer] prints out a paper.")
diff --git a/code/modules/modular_computers/file_system/programs/configurator.dm b/code/modules/modular_computers/file_system/programs/configurator.dm
index 6e4186df8de..0afba30879a 100644
--- a/code/modules/modular_computers/file_system/programs/configurator.dm
+++ b/code/modules/modular_computers/file_system/programs/configurator.dm
@@ -28,7 +28,7 @@
if(!computer)
return FALSE
- var/list/data = get_header_data()
+ var/list/data = list()
data["disk_size"] = hard_drive.max_capacity
data["disk_used"] = hard_drive.used_capacity
@@ -66,9 +66,9 @@
H.enabled = !H.enabled
. = TRUE
if("PC_select_theme")
- if(computer.theme_locked || !(params["theme"] in computer.allowed_themes))
+ if(computer.theme_locked || !(params["theme"] in computer.allowed_themes)) // filtering based on theme name here
return
- computer.device_theme = computer.allowed_themes[params["theme"]]
+ computer.device_theme = computer.allowed_themes[params["theme"]] // converting theme name to ID
. = TRUE
if("PC_set_classic_color")
if(computer.device_theme != THEME_THINKTRONIC)
diff --git a/code/modules/modular_computers/file_system/programs/crewmanifest.dm b/code/modules/modular_computers/file_system/programs/crewmanifest.dm
index 6fdfbea9782..c96da8bd253 100644
--- a/code/modules/modular_computers/file_system/programs/crewmanifest.dm
+++ b/code/modules/modular_computers/file_system/programs/crewmanifest.dm
@@ -18,7 +18,7 @@
return data
/datum/computer_file/program/crew_manifest/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/obj/item/computer_hardware/printer/printer
if(computer)
diff --git a/code/modules/modular_computers/file_system/programs/file_browser.dm b/code/modules/modular_computers/file_system/programs/file_browser.dm
index 92fbc1d7a3e..edf967980c3 100644
--- a/code/modules/modular_computers/file_system/programs/file_browser.dm
+++ b/code/modules/modular_computers/file_system/programs/file_browser.dm
@@ -88,7 +88,7 @@
binary.alert_silenced = !binary.alert_silenced
/datum/computer_file/program/filemanager/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/obj/item/computer_hardware/hard_drive/HDD = computer.all_components[MC_HDD]
var/obj/item/computer_hardware/hard_drive/portable/RHDD = computer.all_components[MC_SDD]
diff --git a/code/modules/modular_computers/file_system/programs/jobmanagement.dm b/code/modules/modular_computers/file_system/programs/jobmanagement.dm
index 3c533344894..303c4791297 100644
--- a/code/modules/modular_computers/file_system/programs/jobmanagement.dm
+++ b/code/modules/modular_computers/file_system/programs/jobmanagement.dm
@@ -63,14 +63,14 @@
var/obj/item/card/id/user_id = card_slot?.stored_card
if(!user_id || !(ACCESS_CHANGE_IDS in user_id.access))
- return
+ return TRUE
switch(action)
if("PRG_open_job")
var/edit_job_target = params["target"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j || !can_open_job(j))
- return
+ return TRUE
if(opened_positions[edit_job_target] >= 0)
GLOB.time_last_changed_position = world.time / 10
j.total_positions++
@@ -81,7 +81,7 @@
var/edit_job_target = params["target"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j || !can_close_job(j))
- return
+ return TRUE
//Allow instant closing without cooldown if a position has been opened before
if(opened_positions[edit_job_target] <= 0)
GLOB.time_last_changed_position = world.time / 10
@@ -93,9 +93,9 @@
var/priority_target = params["target"]
var/datum/job/j = SSjob.GetJob(priority_target)
if(!j)
- return
+ return TRUE
if(j.total_positions <= j.current_positions)
- return
+ return TRUE
if(j in SSjob.prioritized_jobs)
SSjob.prioritized_jobs -= j
else
@@ -108,7 +108,7 @@
/datum/computer_file/program/job_management/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/authed = FALSE
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
diff --git a/code/modules/modular_computers/file_system/programs/log_viewer.dm b/code/modules/modular_computers/file_system/programs/log_viewer.dm
index 8e533d1394b..64f3bec8453 100644
--- a/code/modules/modular_computers/file_system/programs/log_viewer.dm
+++ b/code/modules/modular_computers/file_system/programs/log_viewer.dm
@@ -45,7 +45,7 @@
return TRUE
/datum/computer_file/program/log_viewer/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
if(!istype(computer))
return data
var/list/datum/computer_file/data/log_file/data_files = list()
diff --git a/code/modules/modular_computers/file_system/programs/notepad.dm b/code/modules/modular_computers/file_system/programs/notepad.dm
index 6268744200a..64cc3e463a0 100644
--- a/code/modules/modular_computers/file_system/programs/notepad.dm
+++ b/code/modules/modular_computers/file_system/programs/notepad.dm
@@ -32,7 +32,7 @@
/datum/computer_file/program/notepad/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/obj/item/modular_computer/tablet/tablet = computer
if(!istype(tablet))
return data
diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm
index a2a7d4e3750..bbc0d8645bd 100644
--- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm
+++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm
@@ -140,7 +140,7 @@
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()
+ var/list/data = list()
data["downloading"] = !!downloaded_file
data["error"] = downloaderror || FALSE
diff --git a/code/modules/modular_computers/file_system/programs/ntmessenger.dm b/code/modules/modular_computers/file_system/programs/ntmessenger.dm
index c5d870f82e4..29671f8f24b 100644
--- a/code/modules/modular_computers/file_system/programs/ntmessenger.dm
+++ b/code/modules/modular_computers/file_system/programs/ntmessenger.dm
@@ -92,11 +92,6 @@
usr << browse_rsc(img, deter_path) // funny random assignment for now, i'll make an actual key later
photo_path = deter_path
-/datum/computer_file/program/messenger/ui_state(mob/user)
- if(istype(user, /mob/living/silicon))
- return GLOB.reverse_contained_state
- return GLOB.default_state
-
/datum/computer_file/program/messenger/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/chat),
@@ -148,7 +143,7 @@
if(!disk?.spam_delay)
if(!disk)
return
- log_href_exploit(usr)
+ log_href_exploit(usr, " Attempted sending PDA message to all without a disk capable of doing so: [disk].")
return
var/list/targets = list()
@@ -213,7 +208,7 @@
return TRUE
/datum/computer_file/program/messenger/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/obj/item/computer_hardware/hard_drive/role/disk = computer.all_components[MC_HDD_JOB]
diff --git a/code/modules/modular_computers/file_system/programs/ntmonitor.dm b/code/modules/modular_computers/file_system/programs/ntmonitor.dm
index 69a9e61ed3a..9bb0f227872 100644
--- a/code/modules/modular_computers/file_system/programs/ntmonitor.dm
+++ b/code/modules/modular_computers/file_system/programs/ntmonitor.dm
@@ -52,7 +52,7 @@
/datum/computer_file/program/ntnetmonitor/ui_data(mob/user)
if(!SSnetworks.station_network)
return
- var/list/data = get_header_data()
+ var/list/data = list()
data["ntnetstatus"] = SSnetworks.station_network.check_function(zlevel=user.get_virtual_z_level())
data["ntnetrelays"] = SSnetworks.relays.len
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 00a1882ed39..5a3ab3bf9a6 100644
--- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
+++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
@@ -218,8 +218,6 @@
var/list/data = list()
- data = get_header_data()
-
var/list/all_channels = list()
for(var/C in SSnetworks.station_network.chat_channels)
var/datum/ntnet_conversation/conv = C
diff --git a/code/modules/modular_computers/file_system/programs/phys_scanner.dm b/code/modules/modular_computers/file_system/programs/phys_scanner.dm
index e51b15137cd..a44c5472db8 100644
--- a/code/modules/modular_computers/file_system/programs/phys_scanner.dm
+++ b/code/modules/modular_computers/file_system/programs/phys_scanner.dm
@@ -107,7 +107,7 @@
/datum/computer_file/program/phys_scanner/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
data["set_mode"] = ReadCurrent()
data["last_record"] = last_record
diff --git a/code/modules/modular_computers/file_system/programs/powermonitor.dm b/code/modules/modular_computers/file_system/programs/powermonitor.dm
index b3cc10ae4d9..048968bdd70 100644
--- a/code/modules/modular_computers/file_system/programs/powermonitor.dm
+++ b/code/modules/modular_computers/file_system/programs/powermonitor.dm
@@ -80,7 +80,7 @@
/datum/computer_file/program/power_monitor/ui_data()
var/datum/powernet/connected_powernet = get_powernet()
- var/list/data = get_header_data()
+ var/list/data = list()
data["stored"] = record_size
data["interval"] = record_interval / 10
data["attached"] = connected_powernet ? TRUE : FALSE
diff --git a/code/modules/modular_computers/file_system/programs/radar.dm b/code/modules/modular_computers/file_system/programs/radar.dm
index 7246c881334..d57bac4d843 100644
--- a/code/modules/modular_computers/file_system/programs/radar.dm
+++ b/code/modules/modular_computers/file_system/programs/radar.dm
@@ -49,7 +49,7 @@
)
/datum/computer_file/program/radar/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
// PDAs should not have full radar capabilities
data["full_capability"] = !istype(computer, /obj/item/modular_computer/tablet/pda)
data["selected"] = selected
@@ -75,8 +75,10 @@
switch(action)
if("selecttarget")
selected = params["ref"]
+ return TRUE
if("scan")
scan()
+ return TRUE
/**
*Updates tracking information of the selected target.
diff --git a/code/modules/modular_computers/file_system/programs/records.dm b/code/modules/modular_computers/file_system/programs/records.dm
index 97e0b95b0d4..37415a880d0 100644
--- a/code/modules/modular_computers/file_system/programs/records.dm
+++ b/code/modules/modular_computers/file_system/programs/records.dm
@@ -81,7 +81,7 @@
/datum/computer_file/program/records/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
data["records"] = GetRecordsReadable()
data["mode"] = mode
return data
diff --git a/code/modules/modular_computers/file_system/programs/remote_airlock.dm b/code/modules/modular_computers/file_system/programs/remote_airlock.dm
index 66e0709b952..b1f70ff043f 100644
--- a/code/modules/modular_computers/file_system/programs/remote_airlock.dm
+++ b/code/modules/modular_computers/file_system/programs/remote_airlock.dm
@@ -11,7 +11,7 @@
unsendable = TRUE
/datum/computer_file/program/remote_airlock/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/list/airlocks = list()
var/list/all_controllable = list()
var/obj/item/computer_hardware/hard_drive/drive = computer.all_components[MC_HDD]
@@ -40,8 +40,18 @@
if("airlock_control")
if(!params["id"])
return
+ var/list/all_controllable = list()
+ var/obj/item/computer_hardware/hard_drive/drive = computer.all_components[MC_HDD]
+ if(istype(drive) && length(drive.controllable_airlocks))
+ all_controllable += drive.controllable_airlocks
+ drive = computer.all_components[MC_HDD_JOB]
+ if(istype(drive) && length(drive.controllable_airlocks))
+ all_controllable += drive.controllable_airlocks
for(var/obj/machinery/door/poddoor/airlock in GLOB.airlocks)
if(airlock.id == params["id"])
+ if(!(airlock.id in all_controllable))
+ log_href_exploit(usr, " Attempted control of airlock: [params["id"]] which they do not have access to (access: [english_list(all_controllable)]).")
+ return TRUE
// Fail, but reload data
if(airlock.get_virtual_z_level() != computer.get_virtual_z_level())
return TRUE
diff --git a/code/modules/modular_computers/file_system/programs/robocontrol.dm b/code/modules/modular_computers/file_system/programs/robocontrol.dm
index bf73121c0be..a5aa7697260 100644
--- a/code/modules/modular_computers/file_system/programs/robocontrol.dm
+++ b/code/modules/modular_computers/file_system/programs/robocontrol.dm
@@ -18,8 +18,8 @@
var/list/current_access = list()
/datum/computer_file/program/robocontrol/ui_data(mob/user)
- var/list/data = get_header_data()
- var/turf/current_turf = get_turf(ui_host())
+ var/list/data = list()
+ var/turf/current_turf = get_turf(computer.ui_host())
var/zlevel = current_turf.get_virtual_z_level()
var/list/botlist = list()
var/list/mulelist = list()
@@ -95,7 +95,7 @@
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment, id_card.hud_state)
card_slot.try_eject(current_user)
else
- playsound(get_turf(ui_host()) , 'sound/machines/buzz-sigh.ogg', 25, FALSE)
+ playsound(get_turf(computer.ui_host()) , 'sound/machines/buzz-sigh.ogg', 25, FALSE)
if(!selected_bot)
return
var access_okay = TRUE
diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm
index f5872c131aa..95bcf0a4d21 100644
--- a/code/modules/modular_computers/file_system/programs/secureye.dm
+++ b/code/modules/modular_computers/file_system/programs/secureye.dm
@@ -58,28 +58,23 @@
QDEL_NULL(cam_background)
return ..()
-/datum/computer_file/program/secureye/ui_interact(mob/user, datum/tgui/ui)
- // Update UI
- ui = SStgui.try_update_ui(user, src, ui)
-
+/datum/computer_file/program/secureye/on_ui_create(mob/user, datum/tgui/ui)
// Update the camera, showing static if necessary and updating data if the location has moved.
update_active_camera_screen()
- if(!ui)
- var/user_ref = REF(user)
- // Ghosts shouldn't count towards concurrent users, which produces
- // an audible terminal_on click.
- if(isliving(user))
- concurrent_users += user_ref
- // Register map objects
- user.client.register_map_obj(cam_screen)
- for(var/plane in cam_plane_masters)
- user.client.register_map_obj(plane)
- user.client.register_map_obj(cam_background)
- return ..()
+ var/user_ref = REF(user)
+ // Ghosts shouldn't count towards concurrent users, which produces
+ // an audible terminal_on click.
+ if(isliving(user))
+ concurrent_users += user_ref
+ // Register map objects
+ user.client.register_map_obj(cam_screen)
+ for(var/plane in cam_plane_masters)
+ user.client.register_map_obj(plane)
+ user.client.register_map_obj(cam_background)
/datum/computer_file/program/secureye/ui_data()
- var/list/data = get_header_data()
+ var/list/data = list()
data["network"] = network
data["activeCamera"] = null
if(active_camera)
@@ -122,8 +117,18 @@
return TRUE
-/datum/computer_file/program/secureye/ui_close(mob/user)
+/datum/computer_file/program/secureye/on_ui_close(mob/user, datum/tgui/tgui)
+ on_exit(user)
+
+/datum/computer_file/program/secureye/kill_program(forced)
. = ..()
+ on_exit()
+
+/datum/computer_file/program/secureye/proc/on_exit(mob/user)
+ if(!ismob(user))
+ user = usr
+ if(!ismob(user))
+ return
var/user_ref = REF(user)
var/is_living = isliving(user)
// Living creature or not, we remove you anyway.
diff --git a/code/modules/modular_computers/file_system/programs/signaller.dm b/code/modules/modular_computers/file_system/programs/signaller.dm
index 0e82a6bd4fc..6f9dfbf9b12 100644
--- a/code/modules/modular_computers/file_system/programs/signaller.dm
+++ b/code/modules/modular_computers/file_system/programs/signaller.dm
@@ -28,7 +28,7 @@
SSradio.remove_object(computer, signal_frequency)
/datum/computer_file/program/signaller/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
var/obj/item/computer_hardware/radio_card/sensor = computer?.get_modular_computer_part(MC_SIGNALLER)
if(sensor?.check_functionality())
data["frequency"] = signal_frequency
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 822b93e775a..87ea248f58b 100644
--- a/code/modules/modular_computers/file_system/programs/sm_monitor.dm
+++ b/code/modules/modular_computers/file_system/programs/sm_monitor.dm
@@ -50,7 +50,7 @@
for(var/supermatter in supermatters)
clear_supermatter(supermatter)
supermatters = list()
- var/turf/T = get_turf(ui_host())
+ var/turf/T = get_turf(computer.ui_host())
if(!T)
return
for(var/obj/machinery/power/supermatter_crystal/S in GLOB.machines)
@@ -118,7 +118,7 @@
computer.alert_call(src, "Crystal delamination in progress!")
/datum/computer_file/program/supermatter_monitor/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
if(istype(active))
var/turf/T = get_turf(active)
diff --git a/code/modules/modular_computers/file_system/programs/statusdisplay.dm b/code/modules/modular_computers/file_system/programs/statusdisplay.dm
index f283ecf66e4..d063716bf8f 100644
--- a/code/modules/modular_computers/file_system/programs/statusdisplay.dm
+++ b/code/modules/modular_computers/file_system/programs/statusdisplay.dm
@@ -61,7 +61,7 @@
SendSignal("alert")
/datum/computer_file/program/status/ui_data(mob/user)
- var/list/data = get_header_data()
+ var/list/data = list()
data["upper"] = upper_text
data["lower"] = lower_text
diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm
index 0904e7b8a3c..2b1451c658a 100644
--- a/code/modules/modular_computers/hardware/card_slot.dm
+++ b/code/modules/modular_computers/hardware/card_slot.dm
@@ -71,6 +71,7 @@
current_job = stored_card.assignment
holder?.on_id_insert()
holder?.update_icon()
+ holder?.ui_update()
return TRUE
diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm
index cb1a777250d..f933807ad75 100644
--- a/code/modules/modular_computers/hardware/hard_drive.dm
+++ b/code/modules/modular_computers/hardware/hard_drive.dm
@@ -38,6 +38,10 @@
. = ..()
. += "It has [max_capacity] GQ of storage capacity."
+/// Return true if nothing happens, return false to cancel attack action
+/obj/item/computer_hardware/hard_drive/proc/process_pre_attack(atom/target, mob/living/user, params)
+ return TRUE
+
/obj/item/computer_hardware/hard_drive/diagnostics(var/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.
diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm
index 92af91f0e26..1429c6bc1ba 100644
--- a/code/modules/modular_computers/hardware/network_card.dm
+++ b/code/modules/modular_computers/hardware/network_card.dm
@@ -6,8 +6,11 @@
network_id = NETWORK_CARDS // Network we are on
var/hardware_id = null // Identification ID. Technically MAC address of this device. Can't be changed by user.
var/identification_string = "" // Identification string, technically nickname seen in the network. Can be set by user.
- var/long_range = 0
- var/ethernet = 0 // Hard-wired, therefore always on, ignores NTNet wireless checks.
+ /// If this works without being on the same zlevel, as long as there is a tcomms relay
+ var/long_range = FALSE
+ /// If this works without a tcomms relay on the zlevel (requires long_range)
+ var/ignore_relay = FALSE
+ var/ethernet = FALSE // Hard-wired, therefore always on, ignores NTNet wireless checks.
malfunction_probability = 1
device_type = MC_NET
@@ -43,7 +46,7 @@
if(ethernet) // Computer is connected via wired connection.
return 3
- if(!SSnetworks.station_network || !SSnetworks.station_network.check_function(specific_action, get_virtual_z_level())) // NTNet is down and we are not connected via wired connection. No signal.
+ if(!SSnetworks.station_network || !SSnetworks.station_network.check_function(specific_action, get_virtual_z_level(), ignore_relay)) // NTNet is down and we are not connected via wired connection. No signal.
return 0
if(holder)
@@ -65,13 +68,18 @@
/obj/item/computer_hardware/network_card/advanced
name = "advanced network card"
desc = "An advanced network card for usage with standard NTNet frequencies. Its transmitter is strong enough to connect even off-station."
- long_range = 1
+ long_range = TRUE
power_usage = 100 // Better range but higher power usage.
icon_state = "radio"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
w_class = WEIGHT_CLASS_TINY
+/obj/item/computer_hardware/network_card/advanced/norelay
+ name = "ultra-advanced network card"
+ desc = "An advanced network card for usage with standard NTNet frequencies. Its transmitter is strong enough to connect even off-station, even without a telecomms relay."
+ ignore_relay = TRUE
+
/obj/item/computer_hardware/network_card/wired
name = "wired network card"
desc = "An advanced network card for usage with standard NTNet frequencies. This one also supports wired connection."
diff --git a/code/modules/modular_computers/hardware/virus_disk.dm b/code/modules/modular_computers/hardware/virus_disk.dm
index e7f19f3c2fb..613bdc2ee64 100644
--- a/code/modules/modular_computers/hardware/virus_disk.dm
+++ b/code/modules/modular_computers/hardware/virus_disk.dm
@@ -23,6 +23,35 @@
else
to_chat(user, "ERROR: Could not find device.")
+/obj/item/computer_hardware/hard_drive/role/virus/clown/process_pre_attack(atom/target, mob/living/user, params)
+ // only run if we're inside a computer
+ if(!istype(loc, /obj/item/modular_computer))
+ return ..()
+ if(!ismachinery(target))
+ return TRUE
+ var/obj/machinery/target_machine = target
+ if(!target_machine.panel_open && !istype(target, /obj/machinery/computer))
+ return TRUE
+ if(!charges)
+ to_chat(user, "[src] beeps: 'Out of charge. Please insert a new cartridge.'")
+ return TRUE
+ if(target.GetComponent(/datum/component/sound_player))
+ to_chat(user, "[src] beeps: 'Virus already present on client, aborting.'")
+ return TRUE
+ to_chat(user, "You upload the virus to [target]!")
+ var/list/sig_list
+ if(istype(target, /obj/machinery/door/airlock))
+ sig_list = list(COMSIG_AIRLOCK_OPEN, COMSIG_AIRLOCK_CLOSE)
+ else
+ sig_list = list(COMSIG_ATOM_ATTACK_HAND)
+ charges--
+ target.AddComponent(
+ /datum/component/sound_player, \
+ uses = rand(30,50), \
+ signal_list = sig_list, \
+ )
+ return FALSE
+
/obj/item/computer_hardware/hard_drive/role/virus/mime
name = "\improper sound of silence disk"
diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm
index 26692d11664..d9440688d80 100644
--- a/code/modules/surgery/organs/tails.dm
+++ b/code/modules/surgery/organs/tails.dm
@@ -8,10 +8,14 @@
slot = ORGAN_SLOT_TAIL
var/tail_type = "None"
-/obj/item/organ/tail/Remove(mob/living/carbon/human/H, special = 0)
- ..()
- if(H?.dna?.species)
- H.dna.species.stop_wagging_tail(H)
+/obj/item/organ/tail/proc/is_wagging(mob/living/carbon/human/H)
+ return FALSE
+
+/obj/item/organ/tail/proc/set_wagging(mob/living/carbon/human/H, wagging = FALSE)
+ return FALSE
+
+/obj/item/organ/tail/proc/toggle_wag(mob/living/carbon/human/H)
+ return set_wagging(H, !is_wagging(H))
/obj/item/organ/tail/cat
name = "cat tail"
@@ -34,6 +38,25 @@
color = H.hair_color
H.update_body()
+/obj/item/organ/tail/cat/is_wagging(mob/living/carbon/human/H)
+ if(!H?.dna?.species)
+ return FALSE
+ return ("waggingtail_human" in H.dna.species.mutant_bodyparts)
+
+/obj/item/organ/tail/cat/set_wagging(mob/living/carbon/human/H, wagging = FALSE)
+ . = FALSE
+ if(!H?.dna?.species)
+ return FALSE
+ var/datum/species/species = H.dna.species
+ if(wagging)
+ species.mutant_bodyparts -= "tail_human"
+ species.mutant_bodyparts |= "waggingtail_human"
+ . = TRUE
+ else
+ species.mutant_bodyparts -= "waggingtail_human"
+ species.mutant_bodyparts |= "tail_human"
+ H.update_body()
+
/obj/item/organ/tail/lizard
name = "lizard tail"
desc = "A severed lizard tail. Somewhere, no doubt, a lizard hater is very pleased with themselves."
@@ -63,3 +86,22 @@
tail_type = H.dna.features["tail_lizard"]
spines = H.dna.features["spines"]
H.update_body()
+
+/obj/item/organ/tail/lizard/is_wagging(mob/living/carbon/human/H)
+ if(!H?.dna?.species)
+ return FALSE
+ return ("waggingtail_lizard" in H.dna.species.mutant_bodyparts)
+
+/obj/item/organ/tail/lizard/set_wagging(mob/living/carbon/human/H, wagging = FALSE)
+ . = FALSE
+ if(!H?.dna?.species)
+ return
+ var/datum/species/species = H.dna.species
+ if(wagging)
+ species.mutant_bodyparts -= list("tail_lizard", "spines")
+ species.mutant_bodyparts |= list("waggingtail_lizard", "waggingspines")
+ . = TRUE
+ else
+ species.mutant_bodyparts -= list("waggingtail_lizard", "waggingspines")
+ species.mutant_bodyparts |= list("tail_lizard", "spines")
+ H.update_body()
diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm
index 72830907bef..a91f5b06624 100644
--- a/code/modules/tgui/tgui.dm
+++ b/code/modules/tgui/tgui.dm
@@ -102,6 +102,15 @@
))
else
window.send_message("ping")
+ send_assets()
+ window.send_message("update", get_payload(
+ with_data = TRUE,
+ with_static_data = TRUE))
+ SStgui.on_open(src)
+
+ return TRUE
+
+/datum/tgui/proc/send_assets()
var/flush_queue = window.send_asset(get_asset_datum(
/datum/asset/simple/namespaced/fontawesome))
flush_queue |= window.send_asset(get_asset_datum(
@@ -110,12 +119,6 @@
flush_queue |= window.send_asset(asset)
if (flush_queue)
user.client.browse_queue_flush()
- window.send_message("update", get_payload(
- with_data = TRUE,
- with_static_data = TRUE))
- SStgui.on_open(src)
-
- return TRUE
/**
* public
diff --git a/html/changelog.html b/html/changelog.html
index 4e82d054327..9afbebb5a27 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -56,6 +56,39 @@
-->