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 @@ -->
+

02 June 2023

+

Absolucy updated:

+ +

benbot16 updated:

+ +

covertcorvid updated:

+ +

itsmeow updated:

+ +

25 May 2023

Bobbanz1 updated:

- -

31 March 2023

-

covertcorvid updated:

- - -

30 March 2023

-

BetaCentari updated:

- -

Bobbanz1 updated:

- -

HowToLoLu updated:

- -

WhereAmO updated:

- -

benbot16 updated:

- - -

27 March 2023

-

Bobbanz1, ghost, Qustinnus, Kryson, uglykoala, KittyNoodle, itseasytosee, FlamingLily, SmArtKar, Fikou, ShizCalev, wesoda25 updated:

- -

benbot16 updated:

- - -

26 March 2023

-

covertcorvid, Karmic-Skink updated:

-
GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 24c1cc6906c..d7f6b5096c0 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -1384,3 +1384,34 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - tweak: Atlas now allows for a second pilot - tweak: Helmet camera number tags are more consistent - rscadd: Genpop timer for sentenced prisoners can now be adjusted +2023-06-02: + Absolucy: + - refactor: Refactored tail wagging code a bit. + - tweak: All species can now *wag their tail if they have one. + benbot16: + - bugfix: Ship mouse aim now works while you're dragging the mouse. + covertcorvid: + - bugfix: Map verb now works on Snake + itsmeow: + - bugfix: Martial arts granting books (karate scroll, CQC manual, Ju Jitsu books, + etc) no longer break permanently if you interrupt it last second. + - rscadd: Re-added the Clown's ability to upload a honk virus to airlocks with their + PDA. + - rscadd: Added preference for default PDA theme + - rscdel: Removed old PDA Style preference + - tweak: ModPCs/Tablets/PDAs will now use the same window for all apps, reducing + the lag between switching apps and preventing the window from jumping around + the screen. + - rscadd: Added the IC date to the NtOS header. + - balance: Nukie PDAs can now connect to NTNet while off-station. + - bugfix: You can no longer imprint IDs onto ModPCs that don't support it. + - bugfix: Fixed a potential exploit where any airlock could be remotely controlled + with the airlock control app. + - admin: Added more detail to some href exploit logs. + - tweak: Illiterate people can no longer use ModPCs. + - rscadd: Gives the AGCNR/SD Monitoring Programs individual program icons, same + with the hail log program and the squad management program. + - bugfix: NT Bounty Hunter and SecurEye apps work again + - tweak: Added a cooldown to the bounty list printer in NT Bounty Hunter. + - tweak: Blind people can now use ModPCs/PDAs again, this was caused by an oversight + in not allowing illiterate people to use PDAs. diff --git a/nsv13.dme b/nsv13.dme index 7de866b86ea..27b94d0ec1f 100644 --- a/nsv13.dme +++ b/nsv13.dme @@ -568,7 +568,7 @@ #include "code\datums\components\sizzle.dm" #include "code\datums\components\slippery.dm" #include "code\datums\components\snail_crawl.dm" -#include "code\datums\components\soundplayer.dm" +#include "code\datums\components\sound_player.dm" #include "code\datums\components\spawner.dm" #include "code\datums\components\spikes.dm" #include "code\datums\components\spill.dm" diff --git a/nsv13/code/modules/mob/living/simple_animal/bot/hugbot.dm b/nsv13/code/modules/mob/living/simple_animal/bot/hugbot.dm index 6af7a7e4471..0830a2c1f03 100644 --- a/nsv13/code/modules/mob/living/simple_animal/bot/hugbot.dm +++ b/nsv13/code/modules/mob/living/simple_animal/bot/hugbot.dm @@ -363,21 +363,14 @@ playsound(H, 'sound/weapons/tap.ogg', 50, 0) SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat) else if(check_zone(zone_selected) == BODY_ZONE_HEAD) - var/datum/species/S if(ishuman(H)) - S = H.dna.species - visible_message("[src] gives [H] a pat on the head to make [H.p_them()] feel better!", \ "You give [src] a pat on the head to make [H.p_them()] feel better!") SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat) - if(S?.can_wag_tail(src) && !(S?.is_wagging_tail())) - var/static/list/many_tails - if(!many_tails) - many_tails = list("tail_human", "tail_lizard", "mam_tail") - for(var/T in many_tails) - if(S.mutant_bodyparts[T] && H.dna.features[T] != "None") - H.emote("wag") - break + var/obj/item/organ/tail/tail = H.get_bodypart(ORGAN_SLOT_TAIL) + if(!tail) + return + tail.toggle_wag(H) else visible_message("[src] hugs [H] to make [H.p_them()] feel better!", \ "You hug [H] to make [H.p_them()] feel better!") diff --git a/nsv13/code/modules/modular_computer/wiki_uplink.dm b/nsv13/code/modules/modular_computer/wiki_uplink.dm index c0a9ca4f778..62e9703836b 100644 --- a/nsv13/code/modules/modular_computer/wiki_uplink.dm +++ b/nsv13/code/modules/modular_computer/wiki_uplink.dm @@ -9,7 +9,7 @@ program_icon = "book" /datum/computer_file/program/databank_uplink/ui_data(mob/user) - var/list/data = get_header_data() + var/list/data = list() var/wikiurl = CONFIG_GET(string/wikiurl) data["src"] = wikiurl diff --git a/nsv13/code/modules/overmap/aim_helper.dm b/nsv13/code/modules/overmap/aim_helper.dm index eca12d274ed..cdfcbe5b087 100644 --- a/nsv13/code/modules/overmap/aim_helper.dm +++ b/nsv13/code/modules/overmap/aim_helper.dm @@ -1,11 +1,21 @@ /obj/structure/overmap/onMouseDrag(src_object, over_object, src_location, over_location, params, mob/M) - aiming_target = over_object - aiming_params = params - var/datum/component/overmap_gunning/user_gun = M.GetComponent(/datum/component/overmap_gunning) - if(user_gun) + // Handle pilots dragging their mouse + if(M == pilot) + if(move_by_mouse && can_move() && !pilot.incapacitated()) + desired_angle = getMouseAngle(params, M) + + // If we're the pilot but not the gunner, don't update gunner-specific information + if(!LAZYFIND(gauss_gunners, M) && M != gunner) + return + + // Handle gunners dragging their mouse + if(LAZYFIND(gauss_gunners, M)) // Anyone with overmap_gunning should also be in gauss_gunners + var/datum/component/overmap_gunning/user_gun = M.GetComponent(/datum/component/overmap_gunning) user_gun.onMouseDrag(src_object, over_object, src_location, over_location, params, M) return TRUE if(aiming) + aiming_target = over_object + aiming_params = params if(target_lock) lastangle = get_angle(src, get_turf(over_object)) else @@ -23,6 +33,8 @@ if(user_gun) user_gun?.onMouseDown(object) return TRUE + if(M != gunner) + return if((fire_mode == FIRE_MODE_MAC || fire_mode == FIRE_MODE_BLUE_LASER || fire_mode == FIRE_MODE_HYBRID_RAIL)) aiming_target = object aiming_params = params @@ -41,6 +53,8 @@ if(user_gun) user_gun?.onMouseUp(object) return TRUE + if(M != gunner) + return autofire_target = null lastangle = get_angle(src, get_turf(object)) stop_aiming() diff --git a/nsv13/code/modules/power/reactor/rbmk.dm b/nsv13/code/modules/power/reactor/rbmk.dm index 35eddff15c0..4b1f3cfb499 100644 --- a/nsv13/code/modules/power/reactor/rbmk.dm +++ b/nsv13/code/modules/power/reactor/rbmk.dm @@ -806,6 +806,7 @@ The reactor CHEWS through moderator. It does not do this slowly. Be very careful network_destination = "rbmk monitoring system" size = 2 tgui_id = "NtosRbmkStats" + program_icon = "radiation" var/active = TRUE //Easy process throttle var/next_stat_interval = 0 var/list/psiData = list() @@ -866,7 +867,7 @@ The reactor CHEWS through moderator. It does not do this slowly. Be very careful ..() /datum/computer_file/program/nuclear_monitor/ui_data() - var/list/data = get_header_data() + var/list/data = list() data["powerData"] = powerData data["psiData"] = psiData data["tempInputData"] = tempInputData diff --git a/nsv13/code/modules/power/stormdrive.dm b/nsv13/code/modules/power/stormdrive.dm index 87e6c0cf15c..dcf3ee6933c 100644 --- a/nsv13/code/modules/power/stormdrive.dm +++ b/nsv13/code/modules/power/stormdrive.dm @@ -1865,6 +1865,7 @@ Control Rods network_destination = "storm drive monitoring system" size = 2 tgui_id = "NtosStormdriveMonitor" + program_icon = "atom" var/active = TRUE //Easy process throttle var/obj/machinery/atmospherics/components/binary/stormdrive_reactor/reactor //Our reactor. @@ -1909,7 +1910,7 @@ Control Rods ..() /datum/computer_file/program/stormdrive_monitor/ui_data() - var/list/data = get_header_data() + var/list/data = list() data["heat"] = reactor.heat data["rod_integrity"] = reactor.control_rod_integrity data["control_rod_percent"] = reactor.control_rod_percent diff --git a/nsv13/code/modules/ship_missions/hail_computer.dm b/nsv13/code/modules/ship_missions/hail_computer.dm index 7f51d7f6080..560cbd4b0ce 100644 --- a/nsv13/code/modules/ship_missions/hail_computer.dm +++ b/nsv13/code/modules/ship_missions/hail_computer.dm @@ -12,6 +12,7 @@ category = PROGRAM_CATEGORY_SUPL size = 4 tgui_id = "NtosHailLogs" + program_icon = "envelope-open" var/obj/var/obj/structure/overmap/ship //Our ship /datum/computer_file/program/ship_hail_logger/on_start(mob/living/user) @@ -29,7 +30,7 @@ /datum/computer_file/program/ship_hail_logger/ui_data() - var/list/data = get_header_data() + var/list/data = list() data["ship_name"] = ship ? ship.name : "No ship detected!" data["missions"] = prep_missions() return data diff --git a/nsv13/code/modules/squads/squad_computers.dm b/nsv13/code/modules/squads/squad_computers.dm index 8b1e314d877..b31bc84dce9 100644 --- a/nsv13/code/modules/squads/squad_computers.dm +++ b/nsv13/code/modules/squads/squad_computers.dm @@ -140,10 +140,11 @@ network_destination = "squad management" size = 2 tgui_id = "NtosSquadManager" + program_icon = "users-cog" var/next_major_action = 0 /datum/computer_file/program/squad_manager/ui_data() - var/list/data = get_header_data() + var/list/data = list() var/list/squads_info = list() for(var/datum/squad/S in GLOB.squad_manager.squads) var/list/squad_info = list() diff --git a/tgui/packages/tgui/layouts/NtosWindow.js b/tgui/packages/tgui/layouts/NtosWindow.js index 7ce5906361f..e004b268890 100644 --- a/tgui/packages/tgui/layouts/NtosWindow.js +++ b/tgui/packages/tgui/layouts/NtosWindow.js @@ -26,6 +26,7 @@ export const NtosWindow = (props, context) => { PC_ntneticon, PC_apclinkicon, PC_stationtime, + PC_stationdate, PC_programheaders = [], PC_showexitprogram, PC_classic_color, @@ -41,6 +42,15 @@ export const NtosWindow = (props, context) => {
+