mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-10 07:41:16 +01:00
[MIRROR] Integrated circuits for modular computers (#26196)
Integrated circuits for modular computers (#80530) This PR integrates circuits for modular computers and a good bits of their programs. The peculiarity here is that modular computers have no fixed amount of unremovable components (except the base one with just a couple ports for now), instead, they're added and removed along with programs. With a few exceptions (such as the messenger and signaler), for these program circuits to work, their associated program has to be either open or in the background. For a reason or another, not all programs have a circuit associated to them, still, however the programs with a circuit are still a handful. They are: - Nanotrasen Pay System - Notepad - SiliConnect - WireCarp - MODsuit Control - Spectre Meter - Direct Messenger* - LifeConnect - Custodial Locator - Fission360 - Camera - Status Display - SignalCommander *By the by, sending messages has a cooldown, so it shouldn't be as spammy. If it turns out to not be enough, I can make it so messages from circuit will be ignored by other messenger circuits. The PR is no longer WIP. I believe modular computers could make for some interesting setups with circuits, since they're fairly flexible and stocked with features unlike many other appliances, therefore also a speck more abusable, though limits, cooldowns, logging and sanitization have been implemented to keep it in check. 🆑 add: Modular Computers now support integrated circuits. What can be done with them depends on the programs installed and whether they're running (open or background). add: Modular Consoles (the machinery) now have a small backup cell they draw power from if the power goes out. /🆑 Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
@@ -97,6 +97,7 @@
|
||||
|
||||
|
||||
/datum/computer_file/program/ai_restorer/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_beginReconstruction")
|
||||
if(!stored_card || !stored_card.AI)
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
traitor_data = null
|
||||
return ..()
|
||||
|
||||
/datum/computer_file/program/contract_uplink/ui_act(action, params)
|
||||
/datum/computer_file/program/contract_uplink/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/computer_file/program/ntnet_dos/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_target_relay")
|
||||
for(var/obj/machinery/ntnet_relay/relays as anything in SSmachines.get_machines_by_type(/obj/machinery/ntnet_relay))
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
spark_system.start()
|
||||
|
||||
/datum/computer_file/program/revelation/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_arm")
|
||||
armed = !armed
|
||||
|
||||
@@ -107,7 +107,8 @@
|
||||
data["BossID"] = "boss[boss_id].gif"
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/arcade/ui_act(action, list/params)
|
||||
/datum/computer_file/program/arcade/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
usr.played_game()
|
||||
var/gamerSkillLevel = 0
|
||||
var/gamerSkill = 0
|
||||
|
||||
@@ -67,7 +67,8 @@
|
||||
data["gasmixes"] = last_gasmix_data
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/atmosscan/ui_act(action, list/params)
|
||||
/datum/computer_file/program/atmosscan/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("scantoggle")
|
||||
if(atmozphere_mode == ATMOZPHERE_SCAN_CLICK)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
size = 5
|
||||
tgui_id = "NtosCyborgRemoteMonitor"
|
||||
program_icon = "project-diagram"
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/borg_monitor
|
||||
var/list/loglist = list() ///A list to copy a borg's IC log list into
|
||||
var/mob/living/silicon/robot/DL_source ///reference of a borg if we're downloading a log, or null if not.
|
||||
var/DL_progress = -1 ///Progress of current download, 0 to 100, -1 for no current download
|
||||
@@ -105,29 +106,46 @@
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/borg_monitor/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("messagebot")
|
||||
var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
|
||||
if(!istype(R))
|
||||
return TRUE
|
||||
var/ID = checkID()
|
||||
if(!ID)
|
||||
return TRUE
|
||||
if(R.stat == DEAD) //Dead borgs will listen to you no longer
|
||||
to_chat(usr, span_warning("Error -- Could not open a connection to unit:[R]"))
|
||||
var/message = tgui_input_text(usr, "Message to be sent to remote cyborg", "Send Message")
|
||||
if(!message)
|
||||
return TRUE
|
||||
to_chat(R, "<br><br>[span_notice("Message from [ID] -- \"[message]\"")]<br>")
|
||||
to_chat(usr, "Message sent to [R]: [message]")
|
||||
R.logevent("Message from [ID] -- \"[message]\"")
|
||||
SEND_SOUND(R, 'sound/machines/twobeep_high.ogg')
|
||||
if(R.connected_ai)
|
||||
to_chat(R.connected_ai, "<br><br>[span_notice("Message from [ID] to [R] -- \"[message]\"")]<br>")
|
||||
SEND_SOUND(R.connected_ai, 'sound/machines/twobeep_high.ogg')
|
||||
usr.log_talk(message, LOG_PDA, tag="Cyborg Monitor Program: ID name \"[ID]\" to [R]")
|
||||
var/mob/living/silicon/robot/robot = locate(params["ref"]) in GLOB.silicon_mobs
|
||||
message_robot(robot, usr)
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/borg_monitor/proc/message_robot(mob/living/silicon/robot/robot, mob/user)
|
||||
if(!istype(robot))
|
||||
return TRUE
|
||||
var/ID = checkID()
|
||||
if(!ID)
|
||||
return FALSE
|
||||
if(robot.stat == DEAD) //Dead borgs will listen to you no longer
|
||||
to_chat(user, span_warning("Error -- Could not open a connection to unit:[robot]"))
|
||||
return FALSE
|
||||
var/message = tgui_input_text(user, "Message to be sent to remote cyborg", "Send Message")
|
||||
if(!message)
|
||||
return FALSE
|
||||
send_message(message, robot, user)
|
||||
|
||||
/datum/computer_file/program/borg_monitor/proc/send_message(message, mob/living/silicon/robot/robot, mob/user)
|
||||
var/ID = checkID()
|
||||
if(!ID)
|
||||
return FALSE
|
||||
if(robot.stat == DEAD) //Dead borgs will listen to you no longer
|
||||
if(user)
|
||||
to_chat(user, span_warning("Error -- Could not open a connection to unit:[robot]"))
|
||||
return FALSE
|
||||
to_chat(robot, "<br><br>[span_notice("Message from [ID] -- \"[message]\"")]<br>")
|
||||
if(user)
|
||||
to_chat(user, "Message sent to [robot]: [message]")
|
||||
robot.logevent("Message from [ID] -- \"[message]\"")
|
||||
SEND_SOUND(robot, 'sound/machines/twobeep_high.ogg')
|
||||
if(robot.connected_ai)
|
||||
to_chat(robot.connected_ai, "<br><br>[span_notice("Message from [ID] to [robot] -- \"[message]\"")]<br>")
|
||||
SEND_SOUND(robot.connected_ai, 'sound/machines/twobeep_high.ogg')
|
||||
user?.log_talk(message, LOG_PDA, tag = "Cyborg Monitor Program: ID name \"[ID]\" to [robot]")
|
||||
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)
|
||||
if(!is_valid_z_level(get_turf(computer), get_turf(R)))
|
||||
@@ -154,6 +172,7 @@
|
||||
extended_desc = "This program allows for remote monitoring of mission-assigned cyborgs."
|
||||
program_flags = PROGRAM_ON_SYNDINET_STORE
|
||||
download_access = list()
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/borg_monitor/syndie
|
||||
|
||||
/datum/computer_file/program/borg_monitor/syndicate/evaluate_borg(mob/living/silicon/robot/R)
|
||||
if(!is_valid_z_level(get_turf(computer), get_turf(R)))
|
||||
@@ -164,3 +183,31 @@
|
||||
|
||||
/datum/computer_file/program/borg_monitor/syndicate/checkID()
|
||||
return "\[CLASSIFIED\]" //no ID is needed for the syndicate version's message function, and the borg will see "[CLASSIFIED]" as the message sender.
|
||||
|
||||
/obj/item/circuit_component/mod_program/borg_monitor
|
||||
associated_program = /datum/computer_file/program/borg_monitor
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
|
||||
|
||||
///Circuit input for the robot we want to message
|
||||
var/datum/port/input/target_robot
|
||||
///The message we want to send
|
||||
var/datum/port/input/set_message
|
||||
|
||||
/obj/item/circuit_component/mod_program/borg_monitor/populate_ports()
|
||||
. = ..()
|
||||
target_robot = add_input_port("Receiver", PORT_TYPE_ATOM)
|
||||
set_message = add_input_port("Set Message", PORT_TYPE_STRING, trigger = PROC_REF(sanitize_borg_message))
|
||||
|
||||
/obj/item/circuit_component/mod_program/borg_monitor/proc/sanitize_borg_message(datum/port/port)
|
||||
set_message.set_value(trim(html_encode(set_message.value), MAX_MESSAGE_LEN))
|
||||
|
||||
/obj/item/circuit_component/mod_program/borg_monitor/input_received(datum/port/port)
|
||||
if(!length(set_message.value) || !iscyborg(target_robot.value))
|
||||
return
|
||||
var/mob/living/silicon/robot/robot = target_robot.value
|
||||
var/datum/computer_file/program/borg_monitor/monitor = associated_program
|
||||
if(monitor.send_message(set_message.value, robot))
|
||||
monitor.computer.log_talk("Cyborg Monitor message (ID name \"[monitor.checkID()]\") sent to [key_name(robot)] by [parent.get_creator()]: [set_message.value]")
|
||||
|
||||
/obj/item/circuit_component/mod_program/borg_monitor/syndie
|
||||
associated_program = /datum/computer_file/program/borg_monitor/syndicate
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
data["bountyText"] = bounty_text
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/bounty_board/ui_act(action, list/params)
|
||||
/datum/computer_file/program/bounty_board/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/current_ref_num = params["request"]
|
||||
var/current_app_num = params["applicant"]
|
||||
var/datum/bank_account/request_target
|
||||
|
||||
@@ -166,7 +166,8 @@
|
||||
data["max_order"] = CARGO_MAX_ORDER
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/budgetorders/ui_act(action, params, datum/tgui/ui)
|
||||
/datum/computer_file/program/budgetorders/ui_act(action, params, datum/tgui/ui, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("send")
|
||||
if(!SSshuttle.supply.canMove())
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/computer_file/program/card_mod/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/mob/user = usr
|
||||
var/obj/item/card/id/inserted_auth_card = computer.computer_id_slot
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
data["barcode_split"] = cut_multiplier * 100
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/shipping/ui_act(action, list/params)
|
||||
/datum/computer_file/program/shipping/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(!computer.computer_id_slot) //We need an ID to successfully run
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
return new_converstaion
|
||||
|
||||
/datum/computer_file/program/chatclient/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/datum/ntnet_conversation/channel = SSmodular_computers.get_chat_channel_by_id(active_channel)
|
||||
var/authed = FALSE
|
||||
if(channel && ((channel.channel_operator == src) || netadmin_mode))
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
data["valid_id"] = TRUE
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/coupon/ui_act(action, params, datum/tgui/ui)
|
||||
/datum/computer_file/program/coupon/ui_act(action, params, datum/tgui/ui, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/obj/item/card/id/user_id = computer.computer_id_slot
|
||||
if(!(user_id?.registered_account.add_to_accounts))
|
||||
return TRUE
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
data["manifest"] = GLOB.manifest.get_manifest()
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/crew_manifest/ui_act(action, params, datum/tgui/ui)
|
||||
/datum/computer_file/program/crew_manifest/ui_act(action, params, datum/tgui/ui, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_print")
|
||||
if(computer) //This option should never be called if there is no printer
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
var/error
|
||||
|
||||
/datum/computer_file/program/filemanager/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_deletefile")
|
||||
var/datum/computer_file/file = computer.find_file_by_name(params["name"])
|
||||
|
||||
@@ -162,6 +162,7 @@
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/scipaper_program/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("et_alia")
|
||||
paper_to_be.et_alia = !paper_to_be.et_alia
|
||||
|
||||
@@ -53,7 +53,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/computer_file/program/job_management/ui_act(action, params, datum/tgui/ui)
|
||||
/datum/computer_file/program/job_management/ui_act(action, params, datum/tgui/ui, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/obj/item/card/id/user_id = computer.computer_id_slot
|
||||
if(!user_id || !(ACCESS_CHANGE_IDS in user_id.access))
|
||||
return TRUE
|
||||
|
||||
@@ -49,7 +49,8 @@
|
||||
data += game.ui_assets(user)
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/mafia/ui_act(mob/user, params, datum/tgui/ui, datum/ui_state/state)
|
||||
/datum/computer_file/program/mafia/ui_act(mob/user, params, datum/tgui/ui, datum/ui_state/state, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/datum/mafia_controller/game = GLOB.mafia_game
|
||||
if(!game)
|
||||
game = create_mafia_game()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
can_run_on_flags = PROGRAM_PDA
|
||||
tgui_id = "NtosCamera"
|
||||
program_icon = "camera"
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/camera
|
||||
|
||||
/// Camera built-into the tablet.
|
||||
var/obj/item/camera/internal_camera
|
||||
@@ -16,6 +17,48 @@
|
||||
/// How many pictures were taken already, used for the camera's TGUI photo display
|
||||
var/picture_number = 1
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera
|
||||
associated_program = /datum/computer_file/program/maintenance/camera
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
|
||||
|
||||
///A target to take a picture of.
|
||||
var/datum/port/input/picture_target
|
||||
///The photographed target
|
||||
var/datum/port/output/photographed
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/populate_ports()
|
||||
. = ..()
|
||||
picture_target = add_input_port("Picture Target", PORT_TYPE_ATOM)
|
||||
photographed = add_output_port("Photographed Entity", PORT_TYPE_ATOM)
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/register_shell(atom/movable/shell)
|
||||
. = ..()
|
||||
var/datum/computer_file/program/maintenance/camera/cam = associated_program
|
||||
RegisterSignal(cam.internal_camera, COMSIG_CAMERA_IMAGE_CAPTURED, PROC_REF(on_image_captured))
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/unregister_shell()
|
||||
var/datum/computer_file/program/maintenance/camera/cam = associated_program
|
||||
UnregisterSignal(cam.internal_camera, COMSIG_CAMERA_IMAGE_CAPTURED)
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/input_received(datum/port/input/port)
|
||||
var/atom/target = picture_target.value
|
||||
if(!target)
|
||||
var/turf/our_turf = get_location()
|
||||
target = locate(our_turf.x, our_turf.y, our_turf.z)
|
||||
if(!target)
|
||||
return
|
||||
var/datum/computer_file/program/maintenance/camera/cam = associated_program
|
||||
if(!cam.internal_camera.can_target(target))
|
||||
return
|
||||
var/pic_size_x = cam.internal_camera.picture_size_x - 1
|
||||
var/pic_size_y = cam.internal_camera.picture_size_y - 1
|
||||
INVOKE_ASYNC(cam.internal_camera, TYPE_PROC_REF(/obj/item/camera, captureimage), target, null, pic_size_x, pic_size_y)
|
||||
|
||||
/obj/item/circuit_component/mod_program/camera/proc/on_image_captured(obj/item/camera/source, atom/target, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
photographed.set_output(target)
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/on_install()
|
||||
. = ..()
|
||||
internal_camera = new(computer)
|
||||
@@ -50,13 +93,13 @@
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/maintenance/camera/ui_act(action, params, datum/tgui/ui)
|
||||
var/mob/living/user = usr
|
||||
/datum/computer_file/program/maintenance/camera/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("print_photo")
|
||||
if(computer.stored_paper <= 0)
|
||||
to_chat(usr, span_notice("Hardware error: Printer out of paper."))
|
||||
return
|
||||
internal_camera.printpicture(user, internal_picture)
|
||||
internal_camera.printpicture(usr, internal_picture)
|
||||
computer.stored_paper--
|
||||
computer.visible_message(span_notice("\The [computer] prints out a paper."))
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
size = 2
|
||||
tgui_id = "NtosMODsuit"
|
||||
program_icon = "user-astronaut"
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/modsuit_control
|
||||
|
||||
///The suit we have control over.
|
||||
var/obj/item/mod/control/controlled_suit
|
||||
@@ -20,12 +21,15 @@
|
||||
. = ..()
|
||||
if(!istype(attacking_item, /obj/item/mod/control))
|
||||
return FALSE
|
||||
sync_modsuit(attacking_item, user)
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/maintenance/modsuit_control/proc/sync_modsuit(obj/item/mod/control/new_modsuit, mob/living/user)
|
||||
if(controlled_suit)
|
||||
unsync_modsuit()
|
||||
controlled_suit = attacking_item
|
||||
controlled_suit = new_modsuit
|
||||
RegisterSignal(controlled_suit, COMSIG_QDELETING, PROC_REF(unsync_modsuit))
|
||||
user.balloon_alert(user, "suit updated")
|
||||
return TRUE
|
||||
user?.balloon_alert(user, "suit updated")
|
||||
|
||||
/datum/computer_file/program/maintenance/modsuit_control/proc/unsync_modsuit(atom/source)
|
||||
SIGNAL_HANDLER
|
||||
@@ -43,4 +47,26 @@
|
||||
return controlled_suit?.ui_static_data()
|
||||
|
||||
/datum/computer_file/program/maintenance/modsuit_control/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
return controlled_suit?.ui_act(action, params, ui, state)
|
||||
|
||||
|
||||
/obj/item/circuit_component/mod_program/modsuit_control
|
||||
associated_program = /datum/computer_file/program/maintenance/modsuit_control
|
||||
|
||||
///Circuit port for loading a new suit to control
|
||||
var/datum/port/input/suit_port
|
||||
|
||||
/obj/item/circuit_component/mod_program/modsuit_control/populate_ports()
|
||||
. = ..()
|
||||
suit_port = add_input_port("MODsuit Controlled", PORT_TYPE_ATOM)
|
||||
|
||||
/obj/item/circuit_component/mod_program/modsuit_control/input_received(datum/port/port)
|
||||
var/datum/computer_file/program/maintenance/modsuit_control/control = associated_program
|
||||
var/obj/item/mod/control/mod = suit_port.value
|
||||
if(isnull(mod) && control.controlled_suit)
|
||||
control.unsync_modsuit()
|
||||
return
|
||||
if(!istype(mod))
|
||||
return
|
||||
control.sync_modsuit(mod)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
#define SPOOK_VALUE_SAME_TURF_MULT 1.5
|
||||
#define SPOOK_VALUE_LIVING_MULT 6
|
||||
#define SPOOK_VALUE_DEF_MOB 10
|
||||
#define SPOOK_VALUE_ICON_STATE_MAX 120
|
||||
#define SPOOK_VALUE_SEGMENT 15
|
||||
#define SPOOK_COOLDOWN 2 SECONDS
|
||||
|
||||
/datum/computer_file/program/maintenance/spectre_meter
|
||||
filename = "spectre_meter"
|
||||
@@ -16,6 +16,7 @@
|
||||
tgui_id = "NtosSpectreMeter"
|
||||
program_icon = "ghost"
|
||||
program_open_overlay = "spectre_meter_0"
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/spectre_meter
|
||||
/// The cooldown for manual scans
|
||||
COOLDOWN_DECLARE(manual_scan_cd)
|
||||
/// Whether the automatic scan mode is active or not
|
||||
@@ -46,13 +47,11 @@
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/maintenance/spectre_meter/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("manual_scan")
|
||||
if(COOLDOWN_FINISHED(src, manual_scan_cd))
|
||||
INVOKE_ASYNC(src, PROC_REF(scan_surroundings))
|
||||
COOLDOWN_START(src, manual_scan_cd, 2 SECONDS)
|
||||
playsound(computer, 'sound/effects/ping_hit.ogg', vol = 40, vary = TRUE)
|
||||
return TRUE
|
||||
INVOKE_ASYNC(src, PROC_REF(scan_surroundings))
|
||||
return TRUE
|
||||
if("toggle_mode")
|
||||
auto_mode = !auto_mode
|
||||
if(auto_mode)
|
||||
@@ -67,10 +66,13 @@
|
||||
|
||||
/datum/computer_file/program/maintenance/spectre_meter/process(seconds_per_tick)
|
||||
if(auto_mode)
|
||||
INVOKE_ASYNC(src, PROC_REF(scan_surroundings))
|
||||
INVOKE_ASYNC(src, PROC_REF(scan_surroundings), FALSE)
|
||||
|
||||
///Return the "spook level" of the area the computer is in.
|
||||
/datum/computer_file/program/maintenance/spectre_meter/proc/scan_surroundings()
|
||||
/datum/computer_file/program/maintenance/spectre_meter/proc/scan_surroundings(manual = TRUE)
|
||||
if(manual && !COOLDOWN_FINISHED(src, manual_scan_cd))
|
||||
return
|
||||
|
||||
var/spook_value = 0
|
||||
var/turf/turf = get_turf(computer)
|
||||
|
||||
@@ -103,6 +105,12 @@
|
||||
if(program_open_overlay != old_open_overlay)
|
||||
computer.update_appearance(UPDATE_OVERLAYS)
|
||||
|
||||
if(manual)
|
||||
COOLDOWN_START(src, manual_scan_cd, SPOOK_COOLDOWN)
|
||||
playsound(computer, 'sound/effects/ping_hit.ogg', vol = 40, vary = TRUE)
|
||||
|
||||
SEND_SIGNAL(computer, COMSIG_MODULAR_COMPUTER_SPECTRE_SCAN, last_spook_value)
|
||||
|
||||
/datum/looping_sound/spectre_meter
|
||||
mid_sounds = /datum/looping_sound/geiger::mid_sounds
|
||||
mid_length = 2
|
||||
@@ -128,8 +136,41 @@
|
||||
last_spook_value = 0
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/circuit_component/mod_program/spectre_meter
|
||||
associated_program = /datum/computer_file/program/maintenance/spectre_meter
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
|
||||
|
||||
/// Returns the spookiness of each scan.
|
||||
var/datum/port/output/scan_results
|
||||
|
||||
/obj/item/circuit_component/mod_program/spectre_meter/populate_ports()
|
||||
. = ..()
|
||||
scan_results = add_output_port("Scan Results", PORT_TYPE_NUMBER)
|
||||
|
||||
/obj/item/circuit_component/mod_program/spectre_meter/register_shell(atom/movable/shell)
|
||||
. = ..()
|
||||
RegisterSignal(associated_program.computer, COMSIG_MODULAR_COMPUTER_SPECTRE_SCAN, PROC_REF(on_scan))
|
||||
|
||||
/obj/item/circuit_component/mod_program/spectre_meter/unregister_shell()
|
||||
UnregisterSignal(associated_program.computer, COMSIG_MODULAR_COMPUTER_SPECTRE_SCAN)
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/mod_program/spectre_meter/get_ui_notices()
|
||||
. = ..()
|
||||
. += create_ui_notice("Scan Coooldown: [SPOOK_COOLDOWN]", "orange", "stopwatch")
|
||||
|
||||
/obj/item/circuit_component/mod_program/spectre_meter/input_received(datum/port/port)
|
||||
var/datum/computer_file/program/maintenance/spectre_meter/meter = associated_program
|
||||
INVOKE_ASYNC(meter, TYPE_PROC_REF(/datum/computer_file/program/maintenance/spectre_meter, scan_surroundings))
|
||||
|
||||
/obj/item/circuit_component/mod_program/spectre_meter/proc/on_scan(datum/source, spook_value)
|
||||
SIGNAL_HANDLER
|
||||
scan_results.set_value(spook_value)
|
||||
|
||||
#undef SPOOK_VALUE_SAME_TURF_MULT
|
||||
#undef SPOOK_VALUE_LIVING_MULT
|
||||
#undef SPOOK_VALUE_DEF_MOB
|
||||
#undef SPOOK_VALUE_ICON_STATE_MAX
|
||||
#undef SPOOK_VALUE_SEGMENT
|
||||
#undef SPOOK_COOLDOWN
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
///Called post-installation of an application in a computer, after 'computer' var is set.
|
||||
/datum/computer_file/program/maintenance/theme/on_install()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
//add the theme to the computer and increase its size to match
|
||||
var/datum/computer_file/program/themeify/theme_app = locate() in computer.stored_files
|
||||
if(theme_app)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#define MESSENGER_CIRCUIT_MIN_COOLDOWN 5 SECONDS
|
||||
#define MESSENGER_CIRCUIT_MAX_COOLDOWN 45 SECONDS
|
||||
#define MESSENGER_CIRCUIT_CD_PER_RECIPIENT 1.5 SECONDS
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger
|
||||
associated_program = /datum/computer_file/program/messenger
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
|
||||
|
||||
///Contents of the last received message
|
||||
var/datum/port/output/received_message
|
||||
///Name of the sender of the above
|
||||
var/datum/port/output/sender_name
|
||||
///Job title of the sender of the above
|
||||
var/datum/port/output/sender_job
|
||||
///Reference to the device that sent the message. Usually a PDA.
|
||||
var/datum/port/output/sender_device
|
||||
|
||||
///A message to be sent when triggered
|
||||
var/datum/port/input/message
|
||||
///A list of PDA targets for the message to be sent
|
||||
var/datum/port/input/targets
|
||||
|
||||
///Plays the ringtone when the input is received
|
||||
var/datum/port/input/ring
|
||||
///Set the ringtone to the input
|
||||
var/datum/port/input/set_ring
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger/populate_ports()
|
||||
. = ..()
|
||||
received_message = add_output_port("Received Message", PORT_TYPE_STRING)
|
||||
sender_name = add_output_port("Sender Name", PORT_TYPE_STRING)
|
||||
sender_job = add_output_port("Sender Job", PORT_TYPE_STRING)
|
||||
sender_device = add_output_port("Sender Device", PORT_TYPE_ATOM)
|
||||
|
||||
message = add_input_port("Message", PORT_TYPE_STRING)
|
||||
targets = add_input_port("Targets", PORT_TYPE_LIST(PORT_TYPE_ATOM))
|
||||
|
||||
ring = add_input_port("Play Ringtone", PORT_TYPE_SIGNAL, trigger = PROC_REF(play_ringtone))
|
||||
set_ring = add_input_port("Set Ringtone", PORT_TYPE_STRING, trigger = PROC_REF(set_ringtone))
|
||||
|
||||
///Sanitize the targets list so it doesn't contain duplicate targets and our own computer.
|
||||
/obj/item/circuit_component/mod_program/messenger/pre_input_received(datum/port/port)
|
||||
if(COMPONENT_TRIGGERED_BY(targets, port))
|
||||
targets.value = unique_list(targets.value) - associated_program.computer
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger/input_received(datum/port/port)
|
||||
var/list/messenger_targets = list()
|
||||
for(var/obj/item/modular_computer/modpc in targets.value)
|
||||
var/datum/computer_file/program/messenger/messenger = locate() in modpc.stored_files
|
||||
if(messenger)
|
||||
messenger_targets |= messenger
|
||||
var/messenger_length = length(messenger_targets)
|
||||
if(!messenger_length)
|
||||
return
|
||||
var/datum/computer_file/program/messenger/messenger = associated_program
|
||||
if(is_ic_filtered_for_pdas(message.value) || is_soft_ic_filtered_for_pdas(message.value))
|
||||
return
|
||||
///We need to async send_message() because some tcomms devices might sleep. Also because of (non-existent) user tgui alerts.
|
||||
INVOKE_ASYNC(messenger, TYPE_PROC_REF(/datum/computer_file/program/messenger, send_message), src, message.value, messenger_targets)
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger/register_shell(atom/movable/shell)
|
||||
. = ..()
|
||||
RegisterSignal(associated_program.computer, COMSIG_MODULAR_PDA_MESSAGE_RECEIVED, PROC_REF(message_received))
|
||||
RegisterSignal(associated_program.computer, COMSIG_MODULAR_PDA_MESSAGE_SENT, PROC_REF(message_sent))
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger/unregister_shell()
|
||||
UnregisterSignal(associated_program.computer, list(COMSIG_MODULAR_PDA_MESSAGE_RECEIVED, COMSIG_MODULAR_PDA_MESSAGE_SENT))
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger/get_ui_notices()
|
||||
. = ..()
|
||||
. += create_ui_notice("Cooldown per recipient: [DisplayTimeText(MESSENGER_CIRCUIT_CD_PER_RECIPIENT)]", "orange", "stopwatch")
|
||||
. += create_ui_notice("Minimum cooldown: [DisplayTimeText(MESSENGER_CIRCUIT_MIN_COOLDOWN)]", "orange", "stopwatch")
|
||||
. += create_ui_notice("Maximum cooldown: [DisplayTimeText(MESSENGER_CIRCUIT_MAX_COOLDOWN)]", "orange", "stopwatch")
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger/proc/message_received(datum/source, datum/signal/subspace/messaging/tablet_message/signal, message_job, message_name)
|
||||
SIGNAL_HANDLER
|
||||
received_message.set_value(signal.data["message"])
|
||||
sender_name.set_value(message_name)
|
||||
sender_job.set_value(message_job)
|
||||
|
||||
var/atom/source_device
|
||||
if(istype(signal.source, /datum/computer_file/program/messenger))
|
||||
var/datum/computer_file/program/messenger/sender_messenger = source
|
||||
source_device = sender_messenger.computer
|
||||
else if(isatom(signal.source))
|
||||
source_device = signal.source
|
||||
|
||||
sender_device.set_value(source_device)
|
||||
|
||||
///Set the cooldown after the message was sent (by us)
|
||||
/obj/item/circuit_component/mod_program/messenger/proc/message_sent(datum/source, atom/origin, datum/signal/subspace/messaging/tablet_message/signal)
|
||||
SIGNAL_HANDLER
|
||||
if(origin != src)
|
||||
return
|
||||
var/targets_length = length(signal.data["targets"])
|
||||
var/datum/computer_file/program/messenger/messenger = associated_program
|
||||
var/cool = clamp(targets_length * MESSENGER_CIRCUIT_CD_PER_RECIPIENT, MESSENGER_CIRCUIT_MIN_COOLDOWN, MESSENGER_CIRCUIT_MAX_COOLDOWN)
|
||||
COOLDOWN_START(messenger, last_text, cool)
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger/proc/set_ringtone(datum/port/port)
|
||||
var/datum/computer_file/program/messenger/messenger = associated_program
|
||||
messenger.set_ringtone(set_ring.value)
|
||||
|
||||
/obj/item/circuit_component/mod_program/messenger/proc/play_ringtone(datum/port/port)
|
||||
var/datum/computer_file/program/messenger/messenger = associated_program
|
||||
messenger.computer.ring(messenger.ringtone)
|
||||
|
||||
#undef MESSENGER_CIRCUIT_MIN_COOLDOWN
|
||||
#undef MESSENGER_CIRCUIT_MAX_COOLDOWN
|
||||
#undef MESSENGER_CIRCUIT_CD_PER_RECIPIENT
|
||||
+60
-30
@@ -14,12 +14,13 @@
|
||||
size = 0
|
||||
undeletable = TRUE // It comes by default in tablets, can't be downloaded, takes no space and should obviously not be able to be deleted.
|
||||
power_cell_use = NONE
|
||||
program_flags = PROGRAM_HEADER | PROGRAM_RUNS_WITHOUT_POWER
|
||||
program_flags = PROGRAM_HEADER | PROGRAM_RUNS_WITHOUT_POWER | PROGRAM_CIRCUITS_RUN_WHEN_CLOSED
|
||||
can_run_on_flags = PROGRAM_PDA
|
||||
ui_header = "ntnrc_idle.gif"
|
||||
tgui_id = "NtosMessenger"
|
||||
program_icon = "comment-alt"
|
||||
alert_able = TRUE
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/messenger
|
||||
|
||||
/// Whether the user is invisible to the message list.
|
||||
var/invisible = FALSE
|
||||
@@ -138,6 +139,18 @@
|
||||
for(var/datum/tgui/window as anything in computer.open_uis)
|
||||
SSassets.transport.send_assets(window.user, data)
|
||||
|
||||
/// Set the ringtone if possible. Also handles encoding.
|
||||
/datum/computer_file/program/messenger/proc/set_ringtone(new_ringtone, mob/user)
|
||||
new_ringtone = trim(html_encode(new_ringtone), MESSENGER_RINGTONE_MAX_LENGTH)
|
||||
if(!new_ringtone)
|
||||
return FALSE
|
||||
|
||||
if(SEND_SIGNAL(computer, COMSIG_TABLET_CHANGE_ID, user, new_ringtone) & COMPONENT_STOP_RINGTONE_CHANGE)
|
||||
return FALSE
|
||||
|
||||
ringtone = ringtone
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/messenger/ui_interact(mob/user, datum/tgui/ui)
|
||||
var/list/data = get_picture_assets()
|
||||
SSassets.transport.send_assets(user, data)
|
||||
@@ -147,19 +160,15 @@
|
||||
return GLOB.reverse_contained_state
|
||||
return GLOB.default_state
|
||||
|
||||
/datum/computer_file/program/messenger/ui_act(action, list/params, datum/tgui/ui)
|
||||
/datum/computer_file/program/messenger/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PDA_ringSet")
|
||||
var/new_ringtone = tgui_input_text(usr, "Enter a new ringtone", "Ringtone", ringtone, MESSENGER_RINGTONE_MAX_LENGTH)
|
||||
var/mob/living/usr_mob = usr
|
||||
if(!new_ringtone || !in_range(computer, usr_mob) || computer.loc != usr_mob)
|
||||
var/mob/living/user = usr
|
||||
var/new_ringtone = tgui_input_text(user, "Enter a new ringtone", "Ringtone", ringtone, encode = FALSE)
|
||||
if(!in_range(computer, user) || computer.loc != user)
|
||||
return FALSE
|
||||
|
||||
if(SEND_SIGNAL(computer, COMSIG_TABLET_CHANGE_ID, usr_mob, new_ringtone) & COMPONENT_STOP_RINGTONE_CHANGE)
|
||||
return FALSE
|
||||
|
||||
ringtone = new_ringtone
|
||||
return TRUE
|
||||
return set_ringtone(new_ringtone, user)
|
||||
|
||||
if("PDA_toggleAlerts")
|
||||
alert_silenced = !alert_silenced
|
||||
@@ -451,18 +460,23 @@
|
||||
message = emoji_sanitize(message)
|
||||
|
||||
// check message against filter
|
||||
if(!check_pda_message_against_filter(message, sender))
|
||||
if(sender && !check_pda_message_against_filter(message, sender))
|
||||
return null
|
||||
|
||||
return message
|
||||
|
||||
/// Sends a message to targets via PDA. When sending to everyone, set `everyone` to true so the message is formatted accordingly
|
||||
/datum/computer_file/program/messenger/proc/send_message(mob/living/sender, message, list/targets, everyone = FALSE)
|
||||
/datum/computer_file/program/messenger/proc/send_message(atom/source, message, list/targets, everyone = FALSE)
|
||||
var/mob/living/sender
|
||||
if(isliving(source))
|
||||
sender = source
|
||||
else if(is_ic_filtered_for_pdas(message) || is_soft_ic_filtered_for_pdas(message))
|
||||
return FALSE
|
||||
message = sanitize_pda_message(message, sender)
|
||||
|
||||
if(!message)
|
||||
return FALSE
|
||||
|
||||
|
||||
// upgrade the image asset to a permanent key
|
||||
var/photo_asset_key = selected_image
|
||||
if(photo_asset_key == TEMP_IMAGE_PATH(REF(src)))
|
||||
@@ -474,7 +488,7 @@
|
||||
var/list/datum/computer_file/program/messenger/target_messengers = list()
|
||||
var/list/datum/pda_chat/target_chats = list()
|
||||
|
||||
var/should_alert = length(targets) == 1
|
||||
var/should_alert = length(targets) == 1 && sender
|
||||
|
||||
// filter out invalid targets
|
||||
for(var/target in targets)
|
||||
@@ -523,7 +537,7 @@
|
||||
target_chats += target_chat
|
||||
target_messengers += target_messenger
|
||||
|
||||
if(!send_message_signal(sender, message, target_messengers, photo_asset_key, everyone))
|
||||
if(!send_message_signal(source, message, target_messengers, photo_asset_key, everyone))
|
||||
return FALSE
|
||||
|
||||
// Log it in our logs
|
||||
@@ -553,8 +567,11 @@
|
||||
|
||||
return send_message_signal(sender, message, targets, fake_photo, FALSE, TRUE, fake_name, fake_job)
|
||||
|
||||
/datum/computer_file/program/messenger/proc/send_message_signal(mob/sender, message, list/datum/computer_file/program/messenger/targets, photo_path = null, everyone = FALSE, rigged = FALSE, fake_name = null, fake_job = null)
|
||||
if(!sender.can_perform_action(computer, ALLOW_RESTING))
|
||||
/datum/computer_file/program/messenger/proc/send_message_signal(atom/source, message, list/datum/computer_file/program/messenger/targets, photo_path = null, everyone = FALSE, rigged = FALSE, fake_name = null, fake_job = null)
|
||||
var/mob/sender
|
||||
if(ismob(source))
|
||||
sender = source
|
||||
if(sender && !sender.can_perform_action(computer, ALLOW_RESTING))
|
||||
return FALSE
|
||||
|
||||
if(!COOLDOWN_FINISHED(src, last_text))
|
||||
@@ -566,7 +583,8 @@
|
||||
// check for jammers
|
||||
if(is_within_radio_jammer_range(computer) && !rigged)
|
||||
// different message so people know it's a radio jammer
|
||||
to_chat(sender, span_notice("ERROR: Network unavailable, please try again later."))
|
||||
if(sender)
|
||||
to_chat(sender, span_notice("ERROR: Network unavailable, please try again later."))
|
||||
if(alert_able && !alert_silenced)
|
||||
playsound(computer, 'sound/machines/terminal_error.ogg', 15, TRUE)
|
||||
return FALSE
|
||||
@@ -596,38 +614,46 @@
|
||||
|
||||
// If it didn't reach, note that fact
|
||||
if (!signal.data["done"])
|
||||
to_chat(sender, span_notice("ERROR: Server is not responding."))
|
||||
if(sender)
|
||||
to_chat(sender, span_notice("ERROR: Server is not responding."))
|
||||
if(alert_able && !alert_silenced)
|
||||
playsound(computer, 'sound/machines/terminal_error.ogg', 15, TRUE)
|
||||
return FALSE
|
||||
|
||||
|
||||
// SKYRAT EDIT BEGIN - PDA messages show a visible message; again!
|
||||
sender.visible_message(span_notice("[sender]'s PDA rings out with the soft sound of keypresses"), vision_distance = COMBAT_MESSAGE_RANGE)
|
||||
// SKYRAT EDIT END
|
||||
|
||||
var/shell_addendum = ""
|
||||
if(istype(source, /obj/item/circuit_component))
|
||||
var/obj/item/circuit_component/circuit = source
|
||||
shell_addendum = "[circuit.parent.get_creator()] "
|
||||
|
||||
// Log in the talk log
|
||||
sender.log_talk(message, LOG_PDA, tag="[rigged ? "Rigged" : ""] PDA: [computer.saved_identification] to [signal.format_target()]")
|
||||
source.log_talk(message, LOG_PDA, tag="[shell_addendum][rigged ? "Rigged" : ""] PDA: [computer.saved_identification] to [signal.format_target()]")
|
||||
if(rigged)
|
||||
log_bomber(sender, "sent a rigged PDA message (Name: [fake_name]. Job: [fake_job]) to [english_list(stringified_targets)] [!is_special_character(sender) ? "(SENT BY NON-ANTAG)" : ""]")
|
||||
|
||||
message = emoji_parse(message) //already sent- this just shows the sent emoji as one to the sender in the to_chat
|
||||
|
||||
// Show it to ghosts
|
||||
var/ghost_message = span_game_say("[span_name("[sender]")] [rigged ? "(as [span_name(fake_name)]) Rigged " : ""]PDA Message --> [span_name("[signal.format_target()]")]: \"[signal.format_message()]\"")
|
||||
var/ghost_message = span_game_say("[span_name("[source]")] [rigged ? "(as [span_name(fake_name)]) Rigged " : ""]PDA Message --> [span_name("[signal.format_target()]")]: \"[signal.format_message()]\"")
|
||||
var/list/message_listeners = GLOB.dead_player_list + GLOB.current_observers_list
|
||||
for(var/mob/listener as anything in message_listeners)
|
||||
if(!(get_chat_toggles(listener) & CHAT_GHOSTPDA))
|
||||
continue
|
||||
to_chat(listener, "[FOLLOW_LINK(listener, sender)] [ghost_message]")
|
||||
to_chat(listener, "[FOLLOW_LINK(listener, source)] [ghost_message]")
|
||||
|
||||
to_chat(sender, span_info("PDA message sent to [signal.format_target()]: \"[message]\""))
|
||||
if(sender)
|
||||
to_chat(sender, span_info("PDA message sent to [signal.format_target()]: \"[message]\""))
|
||||
|
||||
if (alert_able && !alert_silenced)
|
||||
computer.send_sound()
|
||||
|
||||
COOLDOWN_START(src, last_text, 1 SECONDS)
|
||||
|
||||
SEND_SIGNAL(computer, COMSIG_MODULAR_PDA_MESSAGE_SENT, source, signal)
|
||||
|
||||
selected_image = null
|
||||
return TRUE
|
||||
|
||||
@@ -642,6 +668,7 @@
|
||||
|
||||
var/sender_ref = signal.data["ref"]
|
||||
|
||||
|
||||
// don't create a new chat for rigged messages, make it a one off notif
|
||||
if(!is_rigged)
|
||||
var/datum/pda_message/message = new(signal.data["message"], FALSE, station_time_timestamp(PDA_MESSAGE_TIMESTAMP_FORMAT), signal.data["photo"], signal.data["everyone"])
|
||||
@@ -662,6 +689,14 @@
|
||||
if(computer.loc && isliving(computer.loc))
|
||||
receievers += computer.loc
|
||||
|
||||
// resolving w/o nullcheck here, assume the messenger exists if a real person sent a message
|
||||
var/datum/computer_file/program/messenger/sender_messenger = chat.recipient?.resolve()
|
||||
|
||||
var/sender_title = is_fake_user ? STRINGIFY_PDA_TARGET(fake_name, fake_job) : get_messenger_name(sender_messenger)
|
||||
var/sender_name = is_fake_user ? fake_name : sender_messenger.computer.saved_identification
|
||||
|
||||
SEND_SIGNAL(computer, COMSIG_MODULAR_PDA_MESSAGE_RECEIVED, signal, fake_job || sender_messenger?.computer.saved_job , sender_name)
|
||||
|
||||
for(var/mob/living/messaged_mob as anything in receievers)
|
||||
if(messaged_mob.stat >= UNCONSCIOUS)
|
||||
continue
|
||||
@@ -675,11 +710,6 @@
|
||||
else
|
||||
reply = "(<a href='byond://?src=[REF(src)];choice=[reply_href];skiprefresh=1;target=[REF(chat)]'>Reply</a>)"
|
||||
|
||||
// resolving w/o nullcheck here, assume the messenger exists if a real person sent a message
|
||||
var/datum/computer_file/program/messenger/sender_messenger = chat.recipient?.resolve()
|
||||
|
||||
var/sender_title = is_fake_user ? STRINGIFY_PDA_TARGET(fake_name, fake_job) : get_messenger_name(sender_messenger)
|
||||
var/sender_name = is_fake_user ? fake_name : sender_messenger.computer.saved_identification
|
||||
|
||||
if (isAI(messaged_mob))
|
||||
sender_title = "<a href='?src=[REF(messaged_mob)];track=[html_encode(sender_name)]'>[sender_title]</a>"
|
||||
|
||||
@@ -27,4 +27,5 @@
|
||||
return newscaster_ui.ui_static_data(user)
|
||||
|
||||
/datum/computer_file/program/newscaster/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
return newscaster_ui.ui_act(action, params, ui, state)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
tgui_id = "NtosNotepad"
|
||||
program_icon = "book"
|
||||
can_run_on_flags = PROGRAM_ALL
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/notepad
|
||||
|
||||
var/written_note = "Congratulations on your station upgrading to the new NtOS and Thinktronic based collaboration effort, \
|
||||
bringing you the best in electronics and software since 2467!\n\
|
||||
@@ -19,7 +20,8 @@
|
||||
Quarter - Either sides of Aft\n\
|
||||
Bow - Either sides of Fore"
|
||||
|
||||
/datum/computer_file/program/notepad/ui_act(action, list/params, datum/tgui/ui)
|
||||
/datum/computer_file/program/notepad/ui_act(action, list/params, datum/tgui/ui, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("UpdateNote")
|
||||
written_note = params["newnote"]
|
||||
@@ -31,3 +33,34 @@
|
||||
data["note"] = written_note
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/circuit_component/mod_program/notepad
|
||||
associated_program = /datum/computer_file/program/notepad
|
||||
///When the input is received, the written note will be set to its value.
|
||||
var/datum/port/input/set_text
|
||||
///The written note output, sent everytime notes are updated.
|
||||
var/datum/port/output/updated_text
|
||||
|
||||
/obj/item/circuit_component/mod_program/notepad/populate_ports()
|
||||
. = ..()
|
||||
set_text = add_input_port("Set Notes", PORT_TYPE_STRING)
|
||||
updated_text = add_output_port("Updated Notes", PORT_TYPE_STRING)
|
||||
|
||||
/obj/item/circuit_component/mod_program/notepad/register_shell(atom/movable/shell)
|
||||
. = ..()
|
||||
RegisterSignal(associated_program, COMSIG_UI_ACT, PROC_REF(on_note_updated))
|
||||
|
||||
/obj/item/circuit_component/mod_program/notepad/unregister_shell()
|
||||
UnregisterSignal(associated_program, COMSIG_UI_ACT)
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/mod_program/notepad/proc/on_note_updated(datum/source, mob/user, action, list/params)
|
||||
SIGNAL_HANDLER
|
||||
if(action == "UpdateNote")
|
||||
updated_text.set_output(params["newnote"])
|
||||
|
||||
/obj/item/circuit_component/mod_program/notepad/input_received(datum/port/port)
|
||||
var/datum/computer_file/program/notepad/pad = associated_program
|
||||
pad.written_note = set_text.value
|
||||
SStgui.update_uis(pad.computer)
|
||||
updated_text.set_output(pad.written_note)
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
#define NT_PAY_STATUS_NO_ACCOUNT 0
|
||||
#define NT_PAY_STATUS_DEPT_ACCOUNT 1
|
||||
#define NT_PAY_STATUS_INVALID_TOKEN 2
|
||||
#define NT_PAY_SATUS_SENDER_IS_RECEIVER 3
|
||||
#define NT_PAY_STATUS_INVALID_MONEY 4
|
||||
#define NT_PAY_STATUS_SUCCESS 5
|
||||
|
||||
/datum/computer_file/program/nt_pay
|
||||
filename = "ntpay"
|
||||
filedesc = "Nanotrasen Pay System"
|
||||
@@ -8,45 +15,19 @@
|
||||
tgui_id = "NtosPay"
|
||||
program_icon = "money-bill-wave"
|
||||
can_run_on_flags = PROGRAM_ALL
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/nt_pay
|
||||
///Reference to the currently logged in user.
|
||||
var/datum/bank_account/current_user
|
||||
///Pay token, by which we can send credits
|
||||
var/token
|
||||
///Amount of credits, which we sends
|
||||
var/money_to_send = 0
|
||||
///Pay token what we want to find
|
||||
var/wanted_token
|
||||
|
||||
/datum/computer_file/program/nt_pay/ui_act(action, list/params, datum/tgui/ui)
|
||||
/datum/computer_file/program/nt_pay/ui_act(action, list/params, datum/tgui/ui, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("Transaction")
|
||||
if(IS_DEPARTMENTAL_ACCOUNT(current_user))
|
||||
return to_chat(usr, span_notice("The app is unable to withdraw from that card."))
|
||||
|
||||
token = params["token"]
|
||||
money_to_send = params["amount"]
|
||||
var/datum/bank_account/recipient
|
||||
if(!token)
|
||||
return to_chat(usr, span_notice("You need to enter your transfer target's pay token."))
|
||||
if(!money_to_send)
|
||||
return to_chat(usr, span_notice("You need to specify how much you're sending."))
|
||||
if(token == current_user.pay_token)
|
||||
return to_chat(usr, span_notice("You can't send credits to yourself."))
|
||||
|
||||
for(var/account as anything in SSeconomy.bank_accounts_by_id)
|
||||
var/datum/bank_account/acc = SSeconomy.bank_accounts_by_id[account]
|
||||
if(acc.pay_token == token)
|
||||
recipient = acc
|
||||
break
|
||||
|
||||
if(!recipient)
|
||||
return to_chat(usr, span_notice("The app can't find who you're trying to pay. Did you enter the pay token right?"))
|
||||
if(!current_user.has_money(money_to_send) || money_to_send < 1)
|
||||
return current_user.bank_card_talk("You cannot afford it.")
|
||||
|
||||
recipient.bank_card_talk("You received [money_to_send] credit(s). Reason: transfer from [current_user.account_holder]")
|
||||
recipient.transfer_money(current_user, money_to_send)
|
||||
current_user.bank_card_talk("You send [money_to_send] credit(s) to [recipient.account_holder]. Now you have [current_user.account_balance] credit(s)")
|
||||
var/token = params["token"]
|
||||
var/money_to_send = params["amount"]
|
||||
make_payment(token, money_to_send, usr)
|
||||
|
||||
if("GetPayToken")
|
||||
wanted_token = null
|
||||
@@ -58,8 +39,6 @@
|
||||
if(!wanted_token)
|
||||
return wanted_token = "Account \"[params["wanted_name"]]\" not found."
|
||||
|
||||
|
||||
|
||||
/datum/computer_file/program/nt_pay/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
@@ -74,3 +53,99 @@
|
||||
data["transaction_list"] = current_user.transaction_history
|
||||
|
||||
return data
|
||||
|
||||
///Wrapper and signal for the main payment function of this program
|
||||
/datum/computer_file/program/nt_pay/proc/make_payment(token, money_to_send, mob/user)
|
||||
var/payment_result = _pay(token, money_to_send, user)
|
||||
SEND_SIGNAL(computer, COMSIG_MODULAR_COMPUTER_NT_PAY_RESULT, payment_result)
|
||||
|
||||
/datum/computer_file/program/nt_pay/proc/_pay(token, money_to_send, mob/user)
|
||||
if(IS_DEPARTMENTAL_ACCOUNT(current_user))
|
||||
if(user)
|
||||
to_chat(user, span_notice("The app is unable to withdraw from that card."))
|
||||
return NT_PAY_STATUS_DEPT_ACCOUNT
|
||||
|
||||
var/datum/bank_account/recipient
|
||||
if(!token)
|
||||
if(user)
|
||||
to_chat(user, span_notice("You need to enter your transfer target's pay token."))
|
||||
return NT_PAY_STATUS_INVALID_TOKEN
|
||||
if(money_to_send <= 0)
|
||||
if(user)
|
||||
to_chat(user, span_notice("You need to specify how much you're sending."))
|
||||
return NT_PAY_STATUS_INVALID_MONEY
|
||||
if(token == current_user.pay_token)
|
||||
if(user)
|
||||
to_chat(user, span_notice("You can't send credits to yourself."))
|
||||
return NT_PAY_SATUS_SENDER_IS_RECEIVER
|
||||
|
||||
for(var/account as anything in SSeconomy.bank_accounts_by_id)
|
||||
var/datum/bank_account/acc = SSeconomy.bank_accounts_by_id[account]
|
||||
if(acc.pay_token == token)
|
||||
recipient = acc
|
||||
break
|
||||
|
||||
if(!recipient)
|
||||
if(user)
|
||||
to_chat(user, span_notice("The app can't find who you're trying to pay. Did you enter the pay token right?"))
|
||||
return NT_PAY_STATUS_INVALID_TOKEN
|
||||
if(!current_user.has_money(money_to_send) || money_to_send < 1)
|
||||
current_user.bank_card_talk("You cannot afford it.")
|
||||
return NT_PAY_STATUS_INVALID_MONEY
|
||||
|
||||
recipient.bank_card_talk("You received [money_to_send] credit(s). Reason: transfer from [current_user.account_holder]")
|
||||
recipient.transfer_money(current_user, money_to_send)
|
||||
current_user.bank_card_talk("You send [money_to_send] credit(s) to [recipient.account_holder]. Now you have [current_user.account_balance] credit(s)")
|
||||
|
||||
return NT_PAY_STATUS_SUCCESS
|
||||
|
||||
|
||||
/obj/item/circuit_component/mod_program/nt_pay
|
||||
associated_program = /datum/computer_file/program/nt_pay
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
|
||||
|
||||
///Circuit variables. This one is for the token we want to pay
|
||||
var/datum/port/input/token_port
|
||||
///The port for the money to send
|
||||
var/datum/port/input/money_port
|
||||
///Let's us know if the payment has gone through or not.
|
||||
var/datum/port/output/payment_status
|
||||
|
||||
/obj/item/circuit_component/mod_program/nt_pay/register_shell(atom/movable/shell)
|
||||
. = ..()
|
||||
RegisterSignal(associated_program.computer, COMSIG_MODULAR_COMPUTER_NT_PAY_RESULT, PROC_REF(on_payment_result))
|
||||
|
||||
/obj/item/circuit_component/mod_program/nt_pay/unregister_shell()
|
||||
UnregisterSignal(associated_program.computer, COMSIG_MODULAR_COMPUTER_NT_PAY_RESULT)
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/mod_program/nt_pay/populate_ports()
|
||||
. = ..()
|
||||
token_port = add_input_port("Token", PORT_TYPE_STRING)
|
||||
money_port = add_input_port("Amount", PORT_TYPE_NUMBER)
|
||||
payment_status = add_output_port("Status", PORT_TYPE_NUMBER)
|
||||
|
||||
/obj/item/circuit_component/mod_program/nt_pay/get_ui_notices()
|
||||
. = ..()
|
||||
. += create_ui_notice("NT-Pay Statuses:")
|
||||
. += create_ui_notice("Fail (No Account) - [NT_PAY_STATUS_NO_ACCOUNT]", "red")
|
||||
. += create_ui_notice("Fail (Dept Account) - [NT_PAY_STATUS_DEPT_ACCOUNT]", "red")
|
||||
. += create_ui_notice("Fail (Invalid Token) - [NT_PAY_STATUS_INVALID_TOKEN]", "red")
|
||||
. += create_ui_notice("Fail (Sender = Receiver) - [NT_PAY_SATUS_SENDER_IS_RECEIVER]", "red")
|
||||
. += create_ui_notice("Fail (Invalid Amount) - [NT_PAY_STATUS_INVALID_MONEY]", "red")
|
||||
. += create_ui_notice("Success - [NT_PAY_STATUS_SUCCESS]", "green")
|
||||
|
||||
/obj/item/circuit_component/mod_program/nt_pay/input_received(datum/port/port)
|
||||
var/datum/computer_file/program/nt_pay/program = associated_program
|
||||
program.make_payment(token_port.value, money_port.value)
|
||||
|
||||
/obj/item/circuit_component/mod_program/nt_pay/proc/on_payment_result(datum/source, payment_result)
|
||||
SIGNAL_HANDLER
|
||||
payment_status.set_output(payment_result)
|
||||
|
||||
#undef NT_PAY_STATUS_NO_ACCOUNT
|
||||
#undef NT_PAY_STATUS_DEPT_ACCOUNT
|
||||
#undef NT_PAY_STATUS_INVALID_TOKEN
|
||||
#undef NT_PAY_SATUS_SENDER_IS_RECEIVER
|
||||
#undef NT_PAY_STATUS_INVALID_MONEY
|
||||
#undef NT_PAY_STATUS_SUCCESS
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
download_completion += download_netspeed
|
||||
|
||||
/datum/computer_file/program/ntnetdownload/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_downloadfile")
|
||||
if(!downloaded_file)
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
)
|
||||
|
||||
/datum/computer_file/program/portrait_printer/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("search")
|
||||
if(search_string != params["to_search"])
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
///The selected target is not trackable
|
||||
#define RADAR_NOT_TRACKABLE 0
|
||||
///The selected target is trackable
|
||||
#define RADAR_TRACKABLE 1
|
||||
///The selected target is trackable, even if subtypes would normally consider it untrackable.
|
||||
#define RADAR_TRACKABLE_ANYWAY 2
|
||||
|
||||
///If the target is something it shouldn't be normally tracking, this is the maximum distance within with it an be tracked.
|
||||
#define MAX_RADAR_CIRCUIT_DISTANCE 18
|
||||
|
||||
/datum/computer_file/program/radar //generic parent that handles most of the process
|
||||
filename = "genericfinder"
|
||||
filedesc = "debug_finder"
|
||||
@@ -58,12 +68,13 @@
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/radar/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("selecttarget")
|
||||
var/selected_new_ref = params["ref"]
|
||||
if(selected_new_ref in trackable_object_refs())
|
||||
selected = selected_new_ref
|
||||
SEND_SIGNAL(computer, COMSIG_MODULAR_COMPUTER_RADAR_SELECTED, selected)
|
||||
return TRUE
|
||||
|
||||
if("scan")
|
||||
@@ -133,13 +144,22 @@
|
||||
**arg1 is the atom being evaluated.
|
||||
*/
|
||||
/datum/computer_file/program/radar/proc/trackable(atom/movable/signal)
|
||||
if(!signal || !computer)
|
||||
return FALSE
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(isnull(signal) || isnull(computer))
|
||||
return RADAR_NOT_TRACKABLE
|
||||
var/turf/here = get_turf(computer)
|
||||
var/turf/there = get_turf(signal)
|
||||
if(!here || !there)
|
||||
return FALSE //I was still getting a runtime even after the above check while scanning, so fuck it
|
||||
return (there.z == here.z) || (is_station_level(here.z) && is_station_level(there.z))
|
||||
return RADAR_NOT_TRACKABLE //I was still getting a runtime even after the above check while scanning, so fuck it
|
||||
if(there.z != here.z && (!is_station_level(here.z) || !is_station_level(there.z)))
|
||||
return RADAR_NOT_TRACKABLE
|
||||
var/trackable_signal = SEND_SIGNAL(computer, COMSIG_MODULAR_COMPUTER_RADAR_TRACKABLE, signal, here, there)
|
||||
switch(trackable_signal)
|
||||
if(COMPONENT_RADAR_TRACK_ANYWAY)
|
||||
return RADAR_TRACKABLE_ANYWAY
|
||||
if(COMPONENT_RADAR_DONT_TRACK)
|
||||
return RADAR_NOT_TRACKABLE
|
||||
return RADAR_TRACKABLE
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -168,7 +188,10 @@
|
||||
*return an atom reference.
|
||||
*/
|
||||
/datum/computer_file/program/radar/proc/find_atom()
|
||||
return
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
var/list/atom_container = list(null)
|
||||
SEND_SIGNAL(computer, COMSIG_MODULAR_COMPUTER_RADAR_FIND_ATOM, atom_container)
|
||||
return atom_container[1]
|
||||
|
||||
//We use SSfastprocess for the program icon state because it runs faster than process_tick() does.
|
||||
/datum/computer_file/program/radar/process()
|
||||
@@ -221,9 +244,10 @@
|
||||
program_flags = PROGRAM_ON_NTNET_STORE | PROGRAM_REQUIRES_NTNET
|
||||
download_access = list(ACCESS_MEDICAL)
|
||||
program_icon = "heartbeat"
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/radar/medical
|
||||
|
||||
/datum/computer_file/program/radar/lifeline/find_atom()
|
||||
return locate(selected) in GLOB.human_list
|
||||
return ..() || (locate(selected) in GLOB.human_list)
|
||||
|
||||
/datum/computer_file/program/radar/lifeline/scan()
|
||||
objects = list()
|
||||
@@ -243,14 +267,16 @@
|
||||
objects += list(crewinfo)
|
||||
|
||||
/datum/computer_file/program/radar/lifeline/trackable(mob/living/carbon/human/humanoid)
|
||||
. = ..()
|
||||
if(. == RADAR_TRACKABLE_ANYWAY)
|
||||
return RADAR_TRACKABLE_ANYWAY
|
||||
if(!humanoid || !istype(humanoid))
|
||||
return FALSE
|
||||
if(..())
|
||||
if (istype(humanoid.w_uniform, /obj/item/clothing/under))
|
||||
var/obj/item/clothing/under/uniform = humanoid.w_uniform
|
||||
if(uniform.has_sensor && uniform.sensor_mode >= SENSOR_COORDS) // Suit sensors must be on maximum
|
||||
return TRUE
|
||||
return FALSE
|
||||
return RADAR_NOT_TRACKABLE
|
||||
if(!istype(humanoid.w_uniform, /obj/item/clothing/under))
|
||||
return RADAR_NOT_TRACKABLE
|
||||
var/obj/item/clothing/under/uniform = humanoid.w_uniform
|
||||
if(uniform.has_sensor && uniform.sensor_mode >= SENSOR_COORDS) // Suit sensors must be on maximum
|
||||
return RADAR_TRACKABLE
|
||||
|
||||
///Tracks all janitor equipment
|
||||
/datum/computer_file/program/radar/custodial_locator
|
||||
@@ -262,9 +288,10 @@
|
||||
program_icon = "broom"
|
||||
size = 2
|
||||
detomatix_resistance = DETOMATIX_RESIST_MINOR
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/radar/janitor
|
||||
|
||||
/datum/computer_file/program/radar/custodial_locator/find_atom()
|
||||
return locate(selected) in GLOB.janitor_devices
|
||||
return ..() || (locate(selected) in GLOB.janitor_devices)
|
||||
|
||||
/datum/computer_file/program/radar/custodial_locator/scan()
|
||||
objects = list()
|
||||
@@ -306,6 +333,7 @@
|
||||
program_icon = "bomb"
|
||||
arrowstyle = "ntosradarpointerS.png"
|
||||
pointercolor = "red"
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/radar/nukie
|
||||
|
||||
/datum/computer_file/program/radar/fission360/on_start(mob/living/user)
|
||||
. = ..()
|
||||
@@ -323,7 +351,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/computer_file/program/radar/fission360/find_atom()
|
||||
return SSpoints_of_interest.get_poi_atom_by_ref(selected)
|
||||
return ..() || SSpoints_of_interest.get_poi_atom_by_ref(selected)
|
||||
|
||||
/datum/computer_file/program/radar/fission360/scan()
|
||||
objects = list()
|
||||
@@ -379,3 +407,129 @@
|
||||
span_danger("[computer] vibrates and lets out an ominous alarm. Uh oh."),
|
||||
span_notice("[computer] begins to vibrate rapidly. Wonder what that means..."),
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* Base circuit for the radar program.
|
||||
* The abstract radar doesn't have this, nor this one is associated to it, so
|
||||
* make sure to specify the associate_program and circuit_comp_type of subtypes,
|
||||
*/
|
||||
/obj/item/circuit_component/mod_program/radar
|
||||
|
||||
///The target to track
|
||||
var/datum/port/input/target
|
||||
///The selected target, from the app
|
||||
var/datum/port/output/selected_by_app
|
||||
/// The result from the output
|
||||
var/datum/port/output/x_pos
|
||||
var/datum/port/output/y_pos
|
||||
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL|CIRCUIT_FLAG_OUTPUT_SIGNAL
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/populate_ports()
|
||||
. = ..()
|
||||
target = add_input_port("Target", PORT_TYPE_ATOM)
|
||||
selected_by_app = add_output_port("Selected From Program", PORT_TYPE_ATOM)
|
||||
x_pos = add_output_port("X", PORT_TYPE_NUMBER)
|
||||
y_pos = add_output_port("Y", PORT_TYPE_NUMBER)
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/register_shell(atom/movable/shell)
|
||||
. = ..()
|
||||
RegisterSignal(associated_program.computer, COMSIG_MODULAR_COMPUTER_RADAR_TRACKABLE, PROC_REF(can_track))
|
||||
RegisterSignal(associated_program.computer, COMSIG_MODULAR_COMPUTER_RADAR_FIND_ATOM, PROC_REF(get_atom))
|
||||
RegisterSignal(associated_program.computer, COMSIG_MODULAR_COMPUTER_RADAR_SELECTED, PROC_REF(on_selected))
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/unregister_shell()
|
||||
UnregisterSignal(associated_program.computer, list(
|
||||
COMSIG_MODULAR_COMPUTER_RADAR_TRACKABLE,
|
||||
COMSIG_MODULAR_COMPUTER_RADAR_FIND_ATOM,
|
||||
COMSIG_MODULAR_COMPUTER_RADAR_SELECTED,
|
||||
))
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/get_ui_notices()
|
||||
. = ..()
|
||||
. += create_ui_notice("Max range for unsupported entities: [MAX_RADAR_CIRCUIT_DISTANCE] tiles", "orange", FA_ICON_BULLSEYE)
|
||||
|
||||
///Set the selected ref of the program to the target (if it exists) and update the x/y pos ports (if trackable) when triggered.
|
||||
/obj/item/circuit_component/mod_program/radar/input_received(datum/port/port)
|
||||
var/datum/computer_file/program/radar/radar = associated_program
|
||||
var/atom/radar_atom = radar.find_atom()
|
||||
if(target.value != radar_atom)
|
||||
radar.selected = REF(target.value)
|
||||
SStgui.update_uis(radar.computer)
|
||||
if(radar.trackable(radar_atom))
|
||||
var/turf/turf = get_turf(radar_atom)
|
||||
x_pos.set_value(turf.x)
|
||||
y_pos.set_value(turf.y)
|
||||
else
|
||||
x_pos.set_value(null)
|
||||
y_pos.set_value(null)
|
||||
|
||||
/**
|
||||
* Check if we can track the object. When making different definitions of this proc for subtypes, include typical
|
||||
* targets as an exception to this (e.g humans for lifeline) so that even if they're coming from a circuit input
|
||||
* they won't get filtered by the maximum distance, because they're "supported entities".
|
||||
*/
|
||||
/obj/item/circuit_component/mod_program/radar/proc/can_track(datum/source, atom/signal, signal_turf, computer_turf)
|
||||
SIGNAL_HANDLER
|
||||
if(target.value && get_dist_euclidian(computer_turf, signal_turf) > MAX_RADAR_CIRCUIT_DISTANCE)
|
||||
return COMPONENT_RADAR_DONT_TRACK
|
||||
return COMPONENT_RADAR_TRACK_ANYWAY
|
||||
|
||||
///Return the value of the target port.
|
||||
/obj/item/circuit_component/mod_program/radar/proc/get_atom(datum/source, list/atom_container)
|
||||
SIGNAL_HANDLER
|
||||
atom_container[1] = target.value
|
||||
|
||||
/**
|
||||
* When a target is selected by the app, reset the target port, update the x/pos ports (if trackable)
|
||||
* and set selected_by_app port to the target atom.
|
||||
*/
|
||||
/obj/item/circuit_component/mod_program/radar/proc/on_selected(datum/source, selected_ref)
|
||||
SIGNAL_HANDLER
|
||||
target.set_value(null)
|
||||
var/datum/computer_file/program/radar/radar = associated_program
|
||||
var/atom/selected_atom = radar.find_atom()
|
||||
selected_by_app.set_value(selected_atom)
|
||||
if(radar.trackable(selected_atom))
|
||||
var/turf/turf = get_turf(radar.selected)
|
||||
x_pos.set_value(turf.x)
|
||||
y_pos.set_value(turf.y)
|
||||
else
|
||||
x_pos.set_value(null)
|
||||
y_pos.set_value(null)
|
||||
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/medical
|
||||
associated_program = /datum/computer_file/program/radar/lifeline
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/medical/can_track(datum/source, atom/signal, signal_turf, computer_turf)
|
||||
if(target.value in GLOB.human_list)
|
||||
return NONE
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/janitor
|
||||
associated_program = /datum/computer_file/program/radar/custodial_locator
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/janitor/can_track(datum/source, atom/signal, signal_turf, computer_turf)
|
||||
if(target.value in GLOB.janitor_devices)
|
||||
return NONE
|
||||
return ..()
|
||||
/obj/item/circuit_component/mod_program/radar/nukie
|
||||
associated_program = /datum/computer_file/program/radar/fission360
|
||||
|
||||
/obj/item/circuit_component/mod_program/radar/nukie/can_track(datum/source, atom/signal, signal_turf, computer_turf)
|
||||
if(target.value in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/nuclearbomb))
|
||||
return NONE
|
||||
if(target.value in SSpoints_of_interest.real_nuclear_disks)
|
||||
return NONE
|
||||
if(target.value == SSshuttle.getShuttle("syndicate"))
|
||||
return NONE
|
||||
return ..()
|
||||
|
||||
#undef MAX_RADAR_CIRCUIT_DISTANCE
|
||||
|
||||
#undef RADAR_NOT_TRACKABLE
|
||||
#undef RADAR_TRACKABLE
|
||||
#undef RADAR_TRACKABLE_ANYWAY
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/robocontrol/ui_act(action, list/params, datum/tgui/ui)
|
||||
/datum/computer_file/program/robocontrol/ui_act(action, list/params, datum/tgui/ui, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
var/mob/current_user = ui.user
|
||||
var/obj/item/card/id/id_card = computer?.computer_id_slot
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/robotact/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
//Implied type, memes
|
||||
var/obj/item/modular_computer/pda/silicon/tablet = computer
|
||||
var/mob/living/silicon/robot/cyborg = tablet.silicon_owner
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
tgui_id = "NtosSignaler"
|
||||
program_icon = "satellite-dish"
|
||||
can_run_on_flags = PROGRAM_PDA | PROGRAM_LAPTOP
|
||||
program_flags = /datum/computer_file/program::program_flags | PROGRAM_CIRCUITS_RUN_WHEN_CLOSED
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/signaler
|
||||
///What is the saved signal frequency?
|
||||
var/signal_frequency = FREQ_SIGNALER
|
||||
/// What is the saved signal code?
|
||||
@@ -36,10 +38,11 @@
|
||||
data["maxFrequency"] = MAX_FREE_FREQ
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/signal_commander/ui_act(action, list/params)
|
||||
/datum/computer_file/program/signal_commander/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("signal")
|
||||
INVOKE_ASYNC(src, PROC_REF(signal))
|
||||
INVOKE_ASYNC(src, PROC_REF(signal), usr)
|
||||
. = TRUE
|
||||
if("freq")
|
||||
var/new_signal_frequency = sanitize_frequency(unformat_frequency(params["freq"]), TRUE)
|
||||
@@ -56,27 +59,65 @@
|
||||
signal_code = initial(signal_code)
|
||||
. = TRUE
|
||||
|
||||
/datum/computer_file/program/signal_commander/proc/signal()
|
||||
/datum/computer_file/program/signal_commander/proc/signal(atom/source)
|
||||
if(!radio_connection)
|
||||
return
|
||||
|
||||
var/mob/user
|
||||
var/obj/item/circuit_component/signaling
|
||||
if(ismob(source))
|
||||
user = source
|
||||
else if(istype(source, /obj/item/circuit_component))
|
||||
signaling = source
|
||||
|
||||
if(!COOLDOWN_FINISHED(src, signal_cooldown))
|
||||
computer.balloon_alert(usr, "cooling down!")
|
||||
if(user)
|
||||
computer.balloon_alert(user, "cooling down!")
|
||||
return
|
||||
|
||||
COOLDOWN_START(src, signal_cooldown, signal_cooldown_time)
|
||||
computer.balloon_alert(usr, "signaled")
|
||||
if(user)
|
||||
computer.balloon_alert(user, "signaled")
|
||||
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
var/turf/T = get_turf(computer)
|
||||
|
||||
var/logging_data = "[time] <B>:</B> [key_name(usr)] used the computer '[initial(computer.name)]' @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(signal_frequency)]/[signal_code]"
|
||||
var/user_deets
|
||||
if(signaling)
|
||||
user_deets = "[signaling.parent.get_creator()]"
|
||||
else
|
||||
user_deets = "[key_name(usr)]"
|
||||
var/logging_data = "[time] <B>:</B> [user_deets] used the computer '[initial(computer.name)]' @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(signal_frequency)]/[signal_code]"
|
||||
add_to_signaler_investigate_log(logging_data)
|
||||
|
||||
var/datum/signal/signal = new(list("code" = signal_code), logging_data = logging_data)
|
||||
var/datum/signal/signal = new(list("code" = signal_code, "key" = signaling?.parent.owner_id), logging_data = logging_data)
|
||||
radio_connection.post_signal(computer, signal)
|
||||
|
||||
/datum/computer_file/program/signal_commander/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(computer, signal_frequency)
|
||||
signal_frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(computer, signal_frequency, RADIO_SIGNALER)
|
||||
|
||||
/obj/item/circuit_component/mod_program/signaler
|
||||
associated_program = /datum/computer_file/program/signal_commander
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
|
||||
|
||||
/// Frequency input
|
||||
var/datum/port/input/freq
|
||||
/// Signal input
|
||||
var/datum/port/input/code
|
||||
|
||||
/obj/item/circuit_component/mod_program/signaler/populate_ports()
|
||||
. = ..()
|
||||
freq = add_input_port("Frequency", PORT_TYPE_NUMBER, trigger = PROC_REF(set_freq), default = FREQ_SIGNALER)
|
||||
code = add_input_port("Code", PORT_TYPE_NUMBER, trigger = PROC_REF(set_code), default = DEFAULT_SIGNALER_CODE)
|
||||
|
||||
/obj/item/circuit_component/mod_program/signaler/proc/set_freq(datum/port/port)
|
||||
var/datum/computer_file/program/signal_commander/signaler = associated_program
|
||||
signaler.set_frequency(clamp(freq.value, MIN_FREE_FREQ, MAX_FREE_FREQ))
|
||||
|
||||
/obj/item/circuit_component/mod_program/signaler/proc/set_code(datum/port/port)
|
||||
var/datum/computer_file/program/signal_commander/signaler = associated_program
|
||||
signaler.signal_code = round(clamp(code.value, 1, 100))
|
||||
|
||||
/obj/item/circuit_component/mod_program/signaler/input_received(datum/port/port)
|
||||
INVOKE_ASYNC(associated_program, TYPE_PROC_REF(/datum/computer_file/program/signal_commander, signal), src)
|
||||
|
||||
@@ -50,7 +50,8 @@
|
||||
|
||||
return null
|
||||
|
||||
/datum/computer_file/program/skill_tracker/ui_act(action, params, datum/tgui/ui)
|
||||
/datum/computer_file/program/skill_tracker/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_reward")
|
||||
var/skill_type = find_skilltype(params["skill"])
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/supermatter_monitor/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_refresh")
|
||||
refresh()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
program_icon = "signal"
|
||||
program_open_overlay = "generic"
|
||||
size = 1
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/status
|
||||
|
||||
extended_desc = "An app used to change the message on the station status displays."
|
||||
tgui_id = "NtosStatus"
|
||||
@@ -42,16 +43,16 @@
|
||||
* * upper - Top text
|
||||
* * lower - Bottom text
|
||||
*/
|
||||
/datum/computer_file/program/status/proc/post_message(upper, lower)
|
||||
/datum/computer_file/program/status/proc/post_message(upper, lower, log_usr = key_name(usr))
|
||||
post_status("message", upper, lower)
|
||||
log_game("[key_name(usr)] has changed the station status display message to \"[upper] [lower]\" [loc_name(usr)]")
|
||||
log_game("[log_usr] has changed the station status display message to \"[upper] [lower]\" [loc_name(usr)]")
|
||||
|
||||
/**
|
||||
* Post a picture to status displays
|
||||
* Arguments:
|
||||
* * picture - The picture name
|
||||
*/
|
||||
/datum/computer_file/program/status/proc/post_picture(picture)
|
||||
/datum/computer_file/program/status/proc/post_picture(picture, log_usr = key_name(usr))
|
||||
if (!(picture in GLOB.status_display_approved_pictures))
|
||||
return
|
||||
if(picture in GLOB.status_display_state_pictures)
|
||||
@@ -80,9 +81,10 @@
|
||||
else
|
||||
post_status("alert", picture)
|
||||
|
||||
log_game("[key_name(usr)] has changed the station status display message to \"[picture]\" [loc_name(usr)]")
|
||||
log_game("[log_usr] has changed the station status display message to \"[picture]\" [loc_name(usr)]")
|
||||
|
||||
/datum/computer_file/program/status/ui_act(action, list/params, datum/tgui/ui)
|
||||
/datum/computer_file/program/status/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("setStatusMessage")
|
||||
upper_text = reject_bad_text(params["upperText"] || "", MAX_STATUS_LINE_LENGTH)
|
||||
@@ -104,3 +106,26 @@
|
||||
data["lowerText"] = lower_text
|
||||
|
||||
return data
|
||||
|
||||
|
||||
/obj/item/circuit_component/mod_program/status
|
||||
associated_program = /datum/computer_file/program/status
|
||||
circuit_flags = CIRCUIT_FLAG_INPUT_SIGNAL
|
||||
|
||||
///When the trigger is signaled, this will be the upper text of status displays.
|
||||
var/datum/port/input/upper_text
|
||||
///When the trigger is signaled, this will be the bottom text.
|
||||
var/datum/port/input/bottom_text
|
||||
///A list port that, when signaled, will set the status image to one of its values
|
||||
var/datum/port/input/status_display_pics
|
||||
|
||||
/obj/item/circuit_component/mod_program/status/populate_options()
|
||||
status_display_pics = add_option_port("Set Status Display Picture", GLOB.status_display_approved_pictures, trigger = PROC_REF(set_picture))
|
||||
|
||||
/obj/item/circuit_component/mod_program/status/proc/set_picture(datum/port/port)
|
||||
var/datum/computer_file/program/status/status = associated_program
|
||||
INVOKE_ASYNC(status, TYPE_PROC_REF(/datum/computer_file/program/status, post_picture), status_display_pics.value, parent.get_creator())
|
||||
|
||||
/obj/item/circuit_component/mod_program/status/input_received(datum/port/port)
|
||||
var/datum/computer_file/program/status/status = associated_program
|
||||
INVOKE_ASYNC(status, TYPE_PROC_REF(/datum/computer_file/program/status, post_message), upper_text.value, bottom_text.value, parent.get_creator())
|
||||
|
||||
@@ -88,7 +88,8 @@
|
||||
)
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/science/ui_act(action, list/params)
|
||||
/datum/computer_file/program/science/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
// Check if the console is locked to block any actions occuring
|
||||
if (locked && action != "toggleLock")
|
||||
computer.say("Console is locked, cannot perform further actions.")
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/themeify/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("PRG_change_theme")
|
||||
var/selected_theme = params["selected_theme"]
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
program_flags = PROGRAM_ON_NTNET_STORE | PROGRAM_REQUIRES_NTNET
|
||||
tgui_id = "NtosNetMonitor"
|
||||
program_icon = "network-wired"
|
||||
circuit_comp_type = /obj/item/circuit_component/mod_program/ntnetmonitor
|
||||
|
||||
/datum/computer_file/program/ntnetmonitor/ui_act(action, list/params, datum/tgui/ui)
|
||||
/datum/computer_file/program/ntnetmonitor/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
switch(action)
|
||||
if("resetIDS")
|
||||
SSmodular_computers.intrusion_detection_alarm = FALSE
|
||||
@@ -66,3 +68,64 @@
|
||||
data["tablets"] += list(tablet_data)
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/circuit_component/mod_program/ntnetmonitor
|
||||
associated_program = /datum/computer_file/program/ntnetmonitor
|
||||
///The stored NTnet relay or PDA to be used as the target of triggers
|
||||
var/datum/port/input/target
|
||||
///Sets `intrusion_detection_alarm` when triggered
|
||||
var/datum/port/input/toggle_ids
|
||||
///Toggles the target ntnet relay on/off when triggered
|
||||
var/datum/port/input/toggle_relay
|
||||
///Purges modpc logs when triggered
|
||||
var/datum/port/input/purge_logs
|
||||
///Toggles the spam mode of the target PDA when triggered
|
||||
var/datum/port/input/toggle_mass_pda
|
||||
///Toggle mime mode of the target PDA when triggered
|
||||
var/datum/port/input/toggle_mime_mode
|
||||
///Returns a list of all PDA Messengers when the "Get Messengers" input is pinged
|
||||
var/datum/port/output/all_messengers
|
||||
///See above
|
||||
var/datum/port/input/get_pdas
|
||||
|
||||
/obj/item/circuit_component/mod_program/ntnetmonitor/populate_ports()
|
||||
. = ..()
|
||||
target = add_input_port("Target Messenger/Relay", PORT_TYPE_DATUM, order = 0.5)
|
||||
toggle_ids = add_input_port("Toggle IDS Status", PORT_TYPE_SIGNAL, trigger = PROC_REF(toggle_ids))
|
||||
toggle_relay = add_input_port("Toggle NTnet Relay", PORT_TYPE_SIGNAL, trigger = PROC_REF(toggle_relay))
|
||||
purge_logs = add_input_port("Purge Logs", PORT_TYPE_SIGNAL, trigger = PROC_REF(purge_logs))
|
||||
toggle_mass_pda = add_input_port("Toggle Mass Messenger", PORT_TYPE_SIGNAL, trigger = PROC_REF(toggle_pda_stuff))
|
||||
toggle_mime_mode = add_input_port("Toggle Mime Mode", PORT_TYPE_SIGNAL, trigger = PROC_REF(toggle_pda_stuff))
|
||||
get_pdas = add_input_port("Get PDAs", PORT_TYPE_SIGNAL, trigger = PROC_REF(get_pdas))
|
||||
all_messengers = add_output_port("List of PDAs", PORT_TYPE_LIST(PORT_TYPE_ATOM))
|
||||
|
||||
/obj/item/circuit_component/mod_program/ntnetmonitor/proc/get_pdas(datum/port/port)
|
||||
var/list/computers_with_messenger = list()
|
||||
for(var/messenger_ref as anything in GLOB.pda_messengers)
|
||||
var/datum/computer_file/program/messenger/messenger = GLOB.pda_messengers[messenger_ref]
|
||||
computers_with_messenger += messenger.computer
|
||||
all_messengers.set_value(computers_with_messenger)
|
||||
|
||||
/obj/item/circuit_component/mod_program/ntnetmonitor/proc/toggle_ids(datum/port/port)
|
||||
SSmodular_computers.intrusion_detection_enabled = !SSmodular_computers.intrusion_detection_enabled
|
||||
|
||||
/obj/item/circuit_component/mod_program/ntnetmonitor/proc/toggle_relay(datum/port/port)
|
||||
var/obj/machinery/ntnet_relay/target_relay = target.value
|
||||
if(!istype(target_relay))
|
||||
return
|
||||
target_relay.set_relay_enabled(!target_relay.relay_enabled)
|
||||
|
||||
/obj/item/circuit_component/mod_program/ntnetmonitor/proc/purge_logs(datum/port/port)
|
||||
SSmodular_computers.purge_logs()
|
||||
|
||||
/obj/item/circuit_component/mod_program/ntnetmonitor/proc/toggle_pda_stuff(datum/port/port)
|
||||
var/obj/item/modular_computer/computer = target.value
|
||||
if(!istype(computer))
|
||||
return
|
||||
var/datum/computer_file/program/messenger/target_messenger = locate() in computer.stored_files
|
||||
if(isnull(target_messenger))
|
||||
return
|
||||
if(COMPONENT_TRIGGERED_BY(toggle_mass_pda, port))
|
||||
target_messenger.spam_mode = !target_messenger.spam_mode
|
||||
if(COMPONENT_TRIGGERED_BY(toggle_mime_mode, port))
|
||||
target_messenger.mime_mode = !target_messenger.mime_mode
|
||||
|
||||
Reference in New Issue
Block a user