Automated Announcement System refactor (#89276)

I standardized stuff in AASs code, and all current reference to it. Also
added interactions for bounty cubes, weather reports and request
consoles, all of it can be changed from AASs UI.
Also it's easier now to add new config entries for AAS to proceed, and
it's now downstream friendly.
Well, because kind of order in code and because it's funny to make
custom messages for... Almost everything?
BTW any entry can be blocked from ingame changes, by default you can't
change Broken Arrival shuttle and Security Officer arrival
announcements, how it was before. But may be we should allow it - it's
an open question.
🆑
add: Many things now handles via AAS: Bounty Cubes, Request Consoles,
Brig Cells, Vending Machines and Orion Trails alerts, Weather Reports,
Cargo Order Console
code: Now anyone can make their own entry for AAS
refactor: AAS internals, also cleanup
/🆑
This commit is contained in:
Archemagus
2025-03-12 16:27:19 -04:00
committed by Roxy
parent 4bf0b95b78
commit 871dae7d19
30 changed files with 754 additions and 535 deletions
-9
View File
@@ -143,15 +143,6 @@
/// Max length of a status line in the status display
#define MAX_STATUS_LINE_LENGTH 40
///Define for automated system arrival announcement
#define AUTO_ANNOUNCE_ARRIVAL "ARRIVAL"
///Define for automated system announcement when a head of staff arrives
#define AUTO_ANNOUNCE_NEWHEAD "NEWHEAD"
///Define for automated system announcement for when the arrival shuttle is broken
#define AUTO_ANNOUNCE_ARRIVALS_BROKEN "ARRIVALS_BROKEN"
///Define for automated system announcement for researched nodes
#define AUTO_ANNOUNCE_NODE "NODE"
/// Blank Status Display
#define SD_BLANK 0
/// Shows the emergency shuttle timer
+2 -17
View File
@@ -235,23 +235,8 @@
return
var/area/player_area = get_area(character)
deadchat_broadcast(span_game(" has arrived at the station at [span_name(player_area.name)]."), span_game("[span_name(character.real_name)] ([rank])"), follow_target = character, message_type=DEADCHAT_ARRIVALRATTLE)
if(!character.mind)
return
if(!GLOB.announcement_systems.len)
return
if(!(character.mind.assigned_role.job_flags & JOB_ANNOUNCE_ARRIVAL))
return
var/obj/machinery/announcement_system/announcer
var/list/available_machines = list()
for(var/obj/machinery/announcement_system/announce as anything in GLOB.announcement_systems)
if(announce.arrival_toggle)
available_machines += announce
break
if(!length(available_machines))
return
announcer = pick(available_machines)
announcer.announce(AUTO_ANNOUNCE_ARRIVAL, character.real_name, rank, list()) //make the list empty to make it announce it in common
if(character.mind && (character.mind.assigned_role.job_flags & JOB_ANNOUNCE_ARRIVAL))
aas_config_announce(/datum/aas_config_entry/arrival, list("PERSON" = character.real_name,"RANK" = rank))
///Check if the turf pressure allows specialized equipment to work
/proc/lavaland_equipment_pressure_check(turf/turf_to_check)
@@ -41,9 +41,9 @@ SUBSYSTEM_DEF(modular_computers)
///Generate new coupon codes that can be redeemed with the Coupon Master App
/datum/controller/subsystem/modular_computers/proc/announce_coupon()
//If there's no way to announce the coupon, we may as well skip it.
if(!length(GLOB.announcement_systems))
var/obj/machinery/announcement_system/announcement_system = get_announcement_system()
if(!announcement_system)
return
var/obj/machinery/announcement_system/announcement_system = pick(GLOB.announcement_systems)
var/static/list/discounts = list("0.10" = 7, "0.15" = 16, "0.20" = 20, "0.25" = 16, "0.50" = 8, "0.66" = 1)
var/static/list/flash_discounts = list("0.30" = 3, "0.40" = 8, "0.50" = 8, "0.66" = 2, "0.75" = 1)
+20 -1
View File
@@ -80,7 +80,15 @@
if(previous_level == warning_level && previous_danger == is_weather_dangerous)
return // No change
var/atom/movable/speaker = parent
speaker.say(get_warning_message())
var/msg = get_warning_message()
var/obj/machinery/announcement_system/aas = get_announcement_system(/datum/aas_config_entry/weather, speaker)
// Active AAS will override default announcement lines
if (aas)
msg = aas.compile_config_message(/datum/aas_config_entry/weather, list(), !is_weather_dangerous ? 4 : warning_level + 1)
// Stop toggling on radios for it, please!
aas.broadcast(msg, list(RADIO_CHANNEL_SUPPLY))
// Still say it, because you can be not on our level
speaker.say(msg)
speaker.update_appearance(UPDATE_ICON)
update_light_color()
@@ -170,6 +178,17 @@
.=..()
UnregisterSignal(parent, COMSIG_ATOM_EXAMINE)
/datum/aas_config_entry/weather
name = "Cargo Alert: Weather Forecast"
general_tooltip = "Allows the radio to announce incoming weather."
announcement_lines_map = list(
"Clear" = "All clear, no weather alerts to report.",
"Incoming" = "Weather front incoming, begin to seek shelter.",
"Imminent or Active" = "Weather front imminent, find shelter immediately.",
"Safe" = "No risk expected from incoming weather front.",
)
#undef WEATHER_ALERT_CLEAR
#undef WEATHER_ALERT_INCOMING
#undef WEATHER_ALERT_IMMINENT_OR_ACTIVE
+3 -3
View File
@@ -12,8 +12,8 @@
var/message_stamped_by = ""
/// The priority of the message
var/priority = ""
/// The radio frequency the message should be broadcasted on
var/radio_freq = null
/// The radio channel the message should be broadcasted on
var/radio_channel = null
/// The type of the request
var/request_type = ""
/// A list to be appended after the message, for example, list of ores
@@ -26,7 +26,7 @@
message_verified_by = data["verified"]
message_stamped_by = data["stamped"]
priority = data["priority"]
radio_freq = data["notify_freq"]
radio_channel = data["notify_channel"]
request_type = data["ore_update"] ? ORE_UPDATE_REQUEST : data["request_type"]
var/list/data_appended_list = data["appended_list"]
if(data_appended_list && data_appended_list.len)
+274 -144
View File
@@ -16,194 +16,82 @@ GLOBAL_LIST_EMPTY(announcement_systems)
circuit = /obj/item/circuitboard/machine/announcement_system
///All possible announcements and their local configurations
var/list/datum/aas_config_entry/config_entries = list()
///The headset that we use for broadcasting
var/obj/item/radio/headset/radio
///The message that we send when someone is joining.
var/arrival = "%PERSON has signed up as %RANK"
///Whether the arrival message is sent
var/arrival_toggle = TRUE
///The message that we send when a department head arrives.
var/newhead = "%PERSON, %RANK, is the department head."
///Whether the newhead message is sent.
var/newhead_toggle = TRUE
///AIs headset support all stations channels, but it may require an override for away site or syndie AASs.
var/radio_type = /obj/item/radio/headset/silicon/ai
var/greenlight = "Light_Green"
var/pinklight = "Light_Pink"
var/errorlight = "Error_Red"
///If true, researched nodes will be announced to the appropriate channels
var/announce_research_node = TRUE
/// The text that we send when announcing researched nodes.
var/node_message = "The %NODE techweb node has been researched"
/obj/machinery/announcement_system/Initialize(mapload)
. = ..()
GLOB.announcement_systems += src
radio = new /obj/item/radio/headset/silicon/ai(src)
radio = new radio_type(src)
config_entries = init_subtypes(/datum/aas_config_entry, list())
update_appearance()
/obj/machinery/announcement_system/randomize_language_if_on_station()
return
/obj/machinery/announcement_system/update_icon_state()
icon_state = "[base_icon_state]_[is_operational ? "On" : "Off"][panel_open ? "_Open" : null]"
icon_state = "[base_icon_state]_[is_operational && !(machine_stat & EMPED) ? "On" : "Off"][panel_open ? "_Open" : null]"
return ..()
/obj/machinery/announcement_system/update_overlays()
. = ..()
if(arrival_toggle)
var/datum/aas_config_entry/entry = locate(/datum/aas_config_entry/arrival) in config_entries
if(entry && entry.enabled)
. += greenlight
if(newhead_toggle)
entry = locate(/datum/aas_config_entry/newhead) in config_entries
if(entry && entry.enabled)
. += pinklight
if(machine_stat & BROKEN)
if(machine_stat & EMPED)
. += errorlight
/obj/machinery/announcement_system/Destroy()
QDEL_NULL(radio)
QDEL_LAZYLIST(config_entries)
GLOB.announcement_systems -= src //"OH GOD WHY ARE THERE 100,000 LISTED ANNOUNCEMENT SYSTEMS?!!"
return ..()
/obj/machinery/announcement_system/screwdriver_act(mob/living/user, obj/item/tool)
tool.play_tool_sound(src)
toggle_panel_open()
to_chat(user, span_notice("You [panel_open ? "open" : "close"] the maintenance hatch of [src]."))
update_appearance()
return TRUE
var/icon_state_assemble = "[base_icon_state]_[is_operational && !(machine_stat & EMPED) ? "On" : "Off"]"
if(default_deconstruction_screwdriver(user, "[icon_state_assemble]_Open", icon_state_assemble, tool))
return ITEM_INTERACT_SUCCESS
return ITEM_INTERACT_BLOCKING
/obj/machinery/announcement_system/crowbar_act(mob/living/user, obj/item/tool)
. = ..()
if(default_deconstruction_crowbar(tool))
return TRUE
return ITEM_INTERACT_SUCCESS
/obj/machinery/announcement_system/multitool_act(mob/living/user, obj/item/tool)
if(!panel_open || !(machine_stat & BROKEN))
return FALSE
if(!panel_open || !(machine_stat & EMPED))
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You reset [src]'s firmware."))
set_machine_stat(machine_stat & ~BROKEN)
set_machine_stat(machine_stat & ~EMPED)
update_appearance()
return ITEM_INTERACT_SUCCESS
/obj/machinery/announcement_system/proc/CompileText(str, user, rank) //replaces user-given variables with actual thingies.
str = replacetext(str, "%PERSON", "[user]")
str = replacetext(str, "%RANK", "[rank]")
return str
/obj/machinery/announcement_system/proc/announce(message_type, target, rank, list/channels)
if(!is_operational)
/// Does funny breakage stuff
/obj/machinery/announcement_system/proc/act_up()
if (machine_stat & EMPED)
return
var/message
switch(message_type)
if(AUTO_ANNOUNCE_ARRIVAL)
if(!arrival_toggle)
return
message = CompileText(arrival, target, rank)
if(AUTO_ANNOUNCE_NEWHEAD)
if(!newhead_toggle)
return
message = CompileText(newhead, target, rank)
if(AUTO_ANNOUNCE_ARRIVALS_BROKEN)
message = "The arrivals shuttle has been damaged. Docking for repairs..."
if(AUTO_ANNOUNCE_NODE)
message = replacetext(node_message, "%NODE", target)
broadcast(message, channels)
/// Announces a new security officer joining over the radio
/obj/machinery/announcement_system/proc/announce_officer(mob/officer, department)
if (!is_operational)
return
broadcast("Officer [officer.real_name] has been assigned to [department].", list(RADIO_CHANNEL_SECURITY))
/// Sends a message to the appropriate channels.
/obj/machinery/announcement_system/proc/broadcast(message, list/channels)
use_energy(active_power_usage)
if(channels.len == 0)
radio.talk_into(src, message, null)
else
for(var/channel in channels)
radio.talk_into(src, message, channel)
/obj/machinery/announcement_system/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AutomatedAnnouncement")
ui.open()
/obj/machinery/announcement_system/ui_data()
var/list/data = list()
data["arrival"] = arrival
data["arrivalToggle"] = arrival_toggle
data["newhead"] = newhead
data["newheadToggle"] = newhead_toggle
data["node_message"] = node_message
data["node_toggle"] = announce_research_node
return data
/obj/machinery/announcement_system/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
if(!usr.can_perform_action(src, ALLOW_SILICON_REACH))
return
if(machine_stat & BROKEN)
visible_message(span_warning("[src] buzzes."), span_hear("You hear a faint buzz."))
playsound(src.loc, 'sound/machines/buzz/buzz-two.ogg', 50, TRUE)
return
switch(action)
if("ArrivalText")
var/new_message = trim(html_encode(params["newText"]), MAX_MESSAGE_LEN)
if(new_message)
arrival = new_message
usr.log_message("updated the arrivals announcement to: [new_message]", LOG_GAME)
if("NewheadText")
var/new_message = trim(html_encode(params["newText"]), MAX_MESSAGE_LEN)
if(new_message)
newhead = new_message
usr.log_message("updated the head announcement to: [new_message]", LOG_GAME)
if("node_message")
var/new_message = trim(html_encode(params["newText"]), MAX_MESSAGE_LEN)
if(new_message)
node_message = new_message
usr.log_message("updated the researched node announcement to: [node_message]", LOG_GAME)
if("newhead_toggle")
newhead_toggle = !newhead_toggle
update_appearance()
if("arrivalToggle")
arrival_toggle = !arrival_toggle
update_appearance()
if("node_toggle")
announce_research_node = !announce_research_node
add_fingerprint(usr)
/obj/machinery/announcement_system/attack_robot(mob/living/silicon/user)
. = attack_ai(user)
/obj/machinery/announcement_system/attack_ai(mob/user)
if(!user.can_perform_action(src, ALLOW_SILICON_REACH))
return
if(machine_stat & BROKEN)
to_chat(user, span_warning("[src]'s firmware appears to be malfunctioning!"))
return
interact(user)
/obj/machinery/announcement_system/proc/act_up() //does funny breakage stuff
if(!atom_break()) // if badmins flag this unbreakable or its already broken
return
arrival = pick("#!@%ERR-34%2 CANNOT LOCAT@# JO# F*LE!", "CRITICAL ERROR 99.", "ERR)#: DA#AB@#E NOT F(*ND!")
newhead = pick("OV#RL()D: \[UNKNOWN??\] DET*#CT)D!", "ER)#R - B*@ TEXT F*O(ND!", "AAS.exe is not responding. NanoOS is searching for a solution to the problem.")
node_message = pick(list(
replacetext(/obj/machinery/announcement_system::node_message, "%NODE", /datum/techweb_node/mech_clown::display_name),
"R/NT1M3 A= ANNOUN-*#nt_SY!?EM.dm, LI%£ 86: N=0DE NULL!",
"BEPIS BEPIS BEPIS",
))
set_machine_stat(machine_stat | EMPED)
update_appearance()
for (var/datum/aas_config_entry/config in config_entries)
config.act_up()
/obj/machinery/announcement_system/emp_act(severity)
. = ..()
if(!(machine_stat & (NOPOWER|BROKEN)) && !(. & EMP_PROTECT_SELF))
if(!(machine_stat & (NOPOWER|EMPED|BROKEN)) && !(. & EMP_PROTECT_SELF))
act_up()
/obj/machinery/announcement_system/emag_act(mob/user, obj/item/card/emag/emag_card)
@@ -213,3 +101,245 @@ GLOBAL_LIST_EMPTY(announcement_systems)
act_up()
balloon_alert(user, "announcement strings corrupted")
return TRUE
/obj/machinery/announcement_system/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AutomatedAnnouncement")
ui.open()
/obj/machinery/announcement_system/ui_data()
var/list/configs = list()
for(var/datum/aas_config_entry/config in config_entries)
configs += list(list(
name = config.name,
entryRef = REF(config),
enabled = config.enabled,
modifiable = config.modifiable,
announcementLinesMap = config.announcement_lines_map,
generalTooltip = config.general_tooltip,
varsAndTooltipsMap = config.vars_and_tooltips_map
))
return list("config_entries" = configs)
/obj/machinery/announcement_system/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
if(!usr.can_perform_action(src, ALLOW_SILICON_REACH))
return
if(machine_stat & EMPED)
visible_message(span_warning("[src] buzzes."), span_hear("You hear a faint buzz."))
playsound(src.loc, 'sound/machines/buzz/buzz-two.ogg', 50, TRUE)
return
add_fingerprint(usr)
var/datum/aas_config_entry/config = locate(params["entryRef"]) in config_entries
if(!config || !config.modifiable)
return
switch(action)
if("Toggle")
config.enabled = !config.enabled
if (config.type in list(/datum/aas_config_entry/arrival, /datum/aas_config_entry/newhead))
update_appearance()
if("Text")
if(!(params["lineKey"] in config.announcement_lines_map))
message_admins("[ADMIN_LOOKUPFLW(usr)] tried to set announcement line for nonexisting line in the [config.name] for AAS. Probably href injection. Received line: [params["lineKey"]]")
log_game("[key_name(usr)] tried to mess with AAS. For [config.name] he tried to edit nonexistend [params["lineKey"]]")
return
var/new_message = trim(html_encode(params["newText"]), MAX_MESSAGE_LEN)
if(new_message)
config.announcement_lines_map[params["lineKey"]] = new_message
usr.log_message("updated [params["lineKey"]] line in the [config.name] to: [new_message]", LOG_GAME)
/obj/machinery/announcement_system/can_interact(mob/user)
. = ..()
if (!.)
return
if (machine_stat & EMPED)
to_chat(user, span_warning("[src]'s firmware appears to be malfunctioning!"))
if (!isAI(user)) // Deus Ex Machina goes without multitool in his default complectation.
to_chat(user, span_warning("However, you can reset it with [EXAMINE_HINT("multitool")], while its [EXAMINE_HINT("panel is open")]!"))
return FALSE
/// If AAS can't broadcast message, it shouldn't be picked by randomizer.
/obj/machinery/announcement_system/proc/has_supported_channels(list/channels)
if (!LAZYLEN(channels) || (RADIO_CHANNEL_COMMON in channels))
// Okay, I am not proud of this, but I don't want CentCom or Syndie AASs to broadcast on Common.
return src.type == /obj/machinery/announcement_system
for(var/channel in channels)
if(radio.channels[channel])
return TRUE
return FALSE
/// Can AAS receive request for broadcast from you?
/obj/machinery/announcement_system/proc/can_be_reached_from(atom/source)
if(!source || !istype(source))
return TRUE
var/turf/source_turf = get_turf(source)
if (!source_turf)
return TRUE
// Keep updated with broadcasting.dm (/datum/signal/subspace/vocal/New)
return z in SSmapping.get_connected_levels(source_turf)
/// Compiles the announcement message with the provided variables. Announcement line is optional.
/obj/machinery/announcement_system/proc/compile_config_message(aas_config_entry_type, list/variables_map, announcement_line, fail_if_disabled=FALSE)
var/datum/aas_config_entry/config = locate(aas_config_entry_type) in config_entries
if (!config || (fail_if_disabled && !config.enabled))
return
return config.compile_announce(variables_map, announcement_line)
/// Sends a message to the appropriate channels.
/obj/machinery/announcement_system/proc/broadcast(message, list/channels, command_span = FALSE)
use_energy(active_power_usage)
if(!LAZYLEN(channels))
radio.talk_into(src, message, null, command_span ? list(speech_span, SPAN_COMMAND) : null)
return
// For some reasons, radio can't recognize RADIO_CHANNEL_COMMON in channels, so we need to handle it separately.
if (RADIO_CHANNEL_COMMON in channels)
radio.talk_into(src, message, null, command_span ? list(speech_span, SPAN_COMMAND) : null)
channels -= RADIO_CHANNEL_COMMON
for(var/channel in channels)
radio.talk_into(src, message, channel, command_span ? list(speech_span, SPAN_COMMAND) : null)
/// Announces configs entry message with the provided variables. Channels and announcement_line are optional.
/obj/machinery/announcement_system/proc/announce(aas_config_entry_type, list/variables_map, list/channels, announcement_line, command_span)
var/msg = compile_config_message(aas_config_entry_type, variables_map, announcement_line, TRUE)
if (msg)
broadcast(msg, channels, command_span)
/// Returns a random announcement system that is operational, has the specified config entry, signal can reach source and radio supports any channel in list. Config entry, source and channels are optional.
/proc/get_announcement_system(aas_config_entry_type, source, list/channels)
if (!GLOB.announcement_systems.len)
return null
var/list/intact_aass = list()
for(var/obj/machinery/announcement_system/announce as anything in GLOB.announcement_systems)
if(!QDELETED(announce) && announce.is_operational && announce.has_supported_channels(channels) && announce.can_be_reached_from(source))
if(aas_config_entry_type)
var/datum/aas_config_entry/entry = locate(aas_config_entry_type) in announce.config_entries
if(!entry || !entry.enabled)
continue
intact_aass += announce
return intact_aass.len ? pick(intact_aass) : null
/// Announces the provided message with the provided variables and config entry type. Channels, announcement_line, command_span and source are optional.
/proc/aas_config_announce(aas_config_entry_type, list/variables_map, source, list/channels, announcement_line, command_span)
var/obj/machinery/announcement_system/announcer = get_announcement_system(aas_config_entry_type, source, channels)
if (!announcer)
return
announcer.announce(aas_config_entry_type, variables_map, channels, announcement_line, command_span)
/datum/aas_config_entry
var/name = "AAS configurable entry"
// Should we broadcast this announcement?
var/enabled = TRUE
// The announcement message. Key will be displayed in the UI.
var/list/announcement_lines_map = list("Message" = "This is a default announcement line.")
// Goes before tooltips for vars, mainly used if announcement has no replacable vars
var/general_tooltip
// Contains all replacable vars and their tooltips
var/list/vars_and_tooltips_map = list()
// Can be changed or disabled by players
var/modifiable = TRUE
/// Compiles the announcement message with the provided variables. Announcement line is optional.
/datum/aas_config_entry/proc/compile_announce(list/variables_map, announcement_line)
var/announcement_message = LAZYACCESS(announcement_lines_map, announcement_line)
// If index was provided LAZYACCESS will return us a key, not value
if (isnum(announcement_line))
announcement_message = announcement_lines_map[announcement_message]
// Fallback - first line
if (!announcement_message)
announcement_message = announcement_lines_map[announcement_lines_map[1]]
// Replace variables with their value
for(var/variable in vars_and_tooltips_map)
announcement_message = replacetext_char(announcement_message, "%[variable]", variables_map[variable] || "\[NO DATA\]")
return announcement_message
/// Called when the announcement system is emagged or EMPed.
/datum/aas_config_entry/proc/act_up()
SHOULD_CALL_PARENT(TRUE)
// Please do not mess with entries, that players can't fix.
if(!modifiable)
return TRUE
return FALSE
/*
Global config entries for the announcement system.
*/
/datum/aas_config_entry/arrival
name = "Arrival Announcement"
announcement_lines_map = list(
"Message" = "%PERSON has signed up as %RANK")
vars_and_tooltips_map = list(
"PERSON" = "will be replaced with their name.",
"RANK" = "with their job."
)
/datum/aas_config_entry/arrival/act_up()
. = ..()
if (.)
return
announcement_lines_map["Message"] = pick("#!@%ERR-34%2 CANNOT LOCAT@# JO# F*LE!",
"CRITICAL ERROR 99.",
"ERR)#: DA#AB@#E NOT F(*ND!")
/datum/aas_config_entry/newhead
name = "Departmental Head Announcement"
announcement_lines_map = list(
"Message" = "%PERSON, %RANK, is the department head.")
vars_and_tooltips_map = list(
"PERSON" = "will be replaced with their name.",
"RANK" = "with their job."
)
/datum/aas_config_entry/newhead/act_up()
. = ..()
if (.)
return
announcement_lines_map["Message"] = pick("OV#RL()D: \[UNKNOWN??\] DET*#CT)D!",
"ER)#R - B*@ TEXT F*O(ND!",
"AAS.exe is not responding. NanoOS is searching for a solution to the problem.")
/datum/aas_config_entry/researched_node
name = "Research Node Announcement"
announcement_lines_map = list(
"Message" = "The %NODE techweb node has been researched")
vars_and_tooltips_map = list(
"NODE" = "will be replaced with the researched node."
)
/datum/aas_config_entry/researched_node/act_up()
. = ..()
if (.)
return
announcement_lines_map["Message"] = pick(
replacetext(/datum/aas_config_entry/researched_node::announcement_lines_map["Message"], "%NODE", /datum/techweb_node/mech_clown::display_name),
"R/NT1M3 A= ANNOUN-*#nt_SY!?EM.dm, LI%£ 86: N=0DE NULL!",
"BEPIS BEPIS BEPIS",
"ERR)#R - B*@ TEXT F*O(ND!")
/datum/aas_config_entry/arrivals_broken
name = "Arrivals Shuttle Malfunction Announcement"
announcement_lines_map = list(
"Message" = "The arrivals shuttle has been damaged. Docking for repairs...")
general_tooltip = "Broadcasted, when arrivals shuttle docks for repairs. No replacable variables provided."
modifiable = FALSE
/datum/aas_config_entry/announce_officer
name = "Security Alert: Officer Arrival Announcement"
announcement_lines_map = list(
"Message" = "Officer %OFFICER has been assigned to %DEPARTMENT.")
vars_and_tooltips_map = list(
"OFFICER" = "will be replaced with the officer's name.",
"DEPARTMENT" = "with the department they were assigned to."
)
modifiable = FALSE
+38 -33
View File
@@ -309,25 +309,10 @@
var/datum/bank_account/bounty_holder_account
///Bank account of the person who receives the handling tip.
var/datum/bank_account/bounty_handler_account
///Our internal radio.
var/obj/item/radio/radio
///The key our internal radio uses.
var/radio_key = /obj/item/encryptionkey/headset_cargo
/obj/item/bounty_cube/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_NO_BARCODES, INNATE_TRAIT) // Don't allow anyone to override our pricetag component with a barcode
radio = new(src)
radio.keyslot = new radio_key
radio.set_listening(FALSE)
radio.recalculateChannels()
RegisterSignal(radio, COMSIG_ITEM_PRE_EXPORT, PROC_REF(on_export))
/obj/item/bounty_cube/Destroy()
if(radio)
UnregisterSignal(radio, COMSIG_ITEM_PRE_EXPORT)
QDEL_NULL(radio)
return ..()
/obj/item/bounty_cube/examine()
. = ..()
@@ -336,29 +321,20 @@
if(handler_tip && !bounty_handler_account)
. += span_notice("Scan this in the cargo shuttle with an export scanner to register your bank account for the <b>[bounty_value * handler_tip]</b> credit handling tip.")
/*
* Signal proc for [COMSIG_ITEM_EXPORTED], registered on the internal radio.
*
* Deletes the internal radio before being exported,
* to stop it from bring counted as an export.
*
* No 4 free credits for you!
*/
/obj/item/bounty_cube/proc/on_export(datum/source)
SIGNAL_HANDLER
QDEL_NULL(radio)
return COMPONENT_STOP_EXPORT // stops the radio from exporting, not the cube
/obj/item/bounty_cube/process(seconds_per_tick)
//if our nag cooldown has finished and we aren't on Centcom or in transit, then nag
if(COOLDOWN_FINISHED(src, next_nag_time) && !is_centcom_level(z) && !is_reserved_level(z))
//set up our nag message
//set up our fallback message, in case of AAS being broken it will be sent to card holders
var/nag_message = "[src] is unsent in [get_area(src)]."
//nag on Supply channel and reduce the speed bonus multiplier to nothing
var/speed_bonus_lost = "[speed_bonus ? " Speedy delivery bonus of [bounty_value * speed_bonus] credit\s lost." : ""]"
radio.talk_into(src, "[nag_message][speed_bonus_lost]", RADIO_CHANNEL_SUPPLY)
var/obj/machinery/announcement_system/aas = get_announcement_system(/datum/aas_config_entry/bounty_cube_unsent, src)
if (aas)
nag_message = aas.compile_config_message(/datum/aas_config_entry/bounty_cube_unsent, list("LOCATION" = get_area_name(src), "COST" = bounty_value), "Regular Message")
if (speed_bonus)
aas.announce(/datum/aas_config_entry/bounty_cube_unsent, list("LOCATION" = get_area_name(src), "COST" = bounty_value, "BONUSLOST" = bounty_value * speed_bonus), list(RADIO_CHANNEL_SUPPLY), "When Bonus Lost")
else
aas.broadcast("[nag_message]", list(RADIO_CHANNEL_SUPPLY))
speed_bonus = 0
//alert the holder
@@ -383,7 +359,13 @@
AddComponent(/datum/component/gps, "[src]")
START_PROCESSING(SSobj, src)
COOLDOWN_START(src, next_nag_time, nag_cooldown)
radio.talk_into(src,"Created in [get_area(src)] by [bounty_holder] ([bounty_holder_job]). Speedy delivery bonus lost in [time2text(next_nag_time - world.time,"mm:ss")].", RADIO_CHANNEL_SUPPLY)
aas_config_announce(/datum/aas_config_entry/bounty_cube_created, list(
"LOCATION" = get_area_name(src),
"PERSON" = bounty_holder,
"RANK" = bounty_holder_job,
"BONUSTIME" = time2text(next_nag_time - world.time,"mm:ss"),
"COST" = bounty_value
), src, list(RADIO_CHANNEL_SUPPLY))
//for when you need a REAL bounty cube to test with and don't want to do a bounty each time your code changes
/obj/item/bounty_cube/debug_cube
@@ -429,4 +411,27 @@
qdel(src)
uses--
/datum/aas_config_entry/bounty_cube_created
name = "Cargo Alert: Bounty Cube Created"
announcement_lines_map = list(
"Message" = "A %COST cr bounty cube has been created in %LOCATION by %PERSON (%RANK). Speedy delivery bonus lost in %BONUSTIME.")
vars_and_tooltips_map = list(
"LOCATION" = "will be replaced with the location of the cube.",
"PERSON" = "with who created the cube.",
"RANK" = "with their job.",
"BONUSTIME" = "with the time left for speedy delivery tip.",
"COST" = "with the cost of the cube.",
)
/datum/aas_config_entry/bounty_cube_unsent
name = "Cargo Alert: Bounty Cube Unsent"
announcement_lines_map = list(
"Regular Message" = "The %COST cr bounty cube is unsent in %LOCATION.",
"When Bonus Lost" = "The %COST cr bounty cube is unsent in %LOCATION. Speedy delivery bonus of %BONUSLOST credits lost.")
vars_and_tooltips_map = list(
"LOCATION" = "will be replaced with the location of the cube.",
"COST" = "with the cost of the cube.",
"BONUSLOST" = "with the lost bonus tip, it will be sent just for When Bonus Lost message!",
)
#undef CIV_BOUNTY_SPLIT
+21 -11
View File
@@ -28,7 +28,6 @@
var/spaceport_raided = FALSE
var/gameStatus = ORION_STATUS_START
var/obj/item/radio/radio
var/list/gamers = list()
var/killed_crew = 0
@@ -40,15 +39,12 @@
var/datum/orion_event/new_event = new path(src)
events[new_event] = new_event.weight
orion_events = events
radio = new /obj/item/radio(src)
radio.set_listening(FALSE)
setup_events()
/obj/machinery/computer/arcade/orion_trail/proc/setup_events()
events = orion_events.Copy()
/obj/machinery/computer/arcade/orion_trail/Destroy()
QDEL_NULL(radio)
events = null
return ..()
@@ -123,14 +119,15 @@
gamers[gamer]++ // How many times the player has 'prestiged' (massacred their crew)
if(gamers[gamer] > ORION_GAMER_REPORT_THRESHOLD && prob(20 * gamers[gamer]))
aas_config_announce(/datum/aas_config_entry/orion_violent_behavior_alert, list(
"PERSON" = gamer.name,
"LOCATION" = get_area_name(src),
"SOURCE" = name), src, list(RADIO_CHANNEL_SECURITY), RADIO_CHANNEL_SECURITY)
radio.set_frequency(FREQ_SECURITY)
radio.talk_into(src, "SECURITY ALERT: Crewmember [gamer] recorded displaying antisocial tendencies in [get_area(src)]. Please watch for violent behavior.", FREQ_SECURITY)
radio.set_frequency(FREQ_MEDICAL)
radio.talk_into(src, "PSYCH ALERT: Crewmember [gamer] recorded displaying antisocial tendencies in [get_area(src)]. Please schedule psych evaluation.", FREQ_MEDICAL)
remove_radio_all(radio)//so we dont keep transmitting sec and medical comms
aas_config_announce(/datum/aas_config_entry/orion_violent_behavior_alert, list(
"PERSON" = gamer.name,
"LOCATION" = get_area_name(src),
"SOURCE" = name), src, list(RADIO_CHANNEL_MEDICAL), RADIO_CHANNEL_MEDICAL)
gamers[gamer] = ORION_GAMER_PAMPHLET //next report send a pamph
@@ -547,4 +544,17 @@
dialogue_level++
addtimer(CALLBACK(src, PROC_REF(commit_explosion), dialogue_level), time_for_next_level)
/datum/aas_config_entry/orion_violent_behavior_alert
// Well we don't want to show that only Orion Trails reports violent behavior, eh-h?
name = "Violent Behavior Alert"
announcement_lines_map = list(
RADIO_CHANNEL_SECURITY = "SECURITY ALERT: Crewmember %PERSON recorded displaying antisocial tendencies in %LOCATION by %SOURCE. Please watch for violent behavior.",
RADIO_CHANNEL_MEDICAL = "PSYCH ALERT: Crewmember %PERSON recorded displaying antisocial tendencies in %LOCATION by %SOURCE. Please schedule psych evaluation.",
)
vars_and_tooltips_map = list(
"PERSON" = "will be replaced with the crewmember reported",
"LOCATION" = "with the area of violent behavior",
"SOURCE" = "with the reporter",
)
#undef ORION_TRAIL_WINTURN
@@ -8,12 +8,13 @@
CATEGORY_SAUCES_REAGENTS,
)
blackbox_key = "chef"
announcement_line = "The kitchen has ordered groceries which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!"
// Discount for items in the chefs category like mining/bitrunning consoles
cargo_cost_multiplier = 0.65
/obj/machinery/computer/order_console/cook/order_groceries(mob/living/purchaser, obj/item/card/id/card, list/groceries)
say("Thank you for your purchase! It will arrive on the next cargo shuttle!")
radio.talk_into(src, "The kitchen has ordered groceries which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!", radio_channel)
aas_config_announce(/datum/aas_config_entry/order_console, list(), src, list(radio_channel), capitalize(blackbox_key))
for(var/datum/orderable_item/ordered_item in groceries)
if(!(ordered_item.category_index in order_categories))
groceries.Remove(ordered_item)
@@ -24,6 +24,7 @@
CATEGORY_PKA,
)
blackbox_key = "mining"
announcement_line = "A shaft miner has ordered equipment which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!"
/obj/machinery/computer/order_console/mining/subtract_points(final_cost, obj/item/card/id/card)
if(final_cost <= card.registered_account.mining_points)
@@ -56,7 +57,7 @@
can_be_cancelled = FALSE,
)
say("Thank you for your purchase! It will arrive on the next cargo shuttle!")
radio.talk_into(src, "A shaft miner has ordered equipment which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!", radio_channel)
aas_config_announce(/datum/aas_config_entry/order_console, list(), src, list(radio_channel), capitalize(blackbox_key))
SSshuttle.shopping_list += new_order
/obj/machinery/computer/order_console/mining/retrieve_points(obj/item/card/id/id_card)
@@ -19,10 +19,10 @@ GLOBAL_LIST_EMPTY(order_console_products)
COOLDOWN_DECLARE(order_cooldown)
///Cooldown time between uses, express console will have extra time depending on express_cost_multiplier.
var/cooldown_time = 60 SECONDS
///The radio the console can speak into
var/obj/item/radio/radio
///The channel we will attempt to speak into through our radio.
var/radio_channel = RADIO_CHANNEL_SUPPLY
///What line we should announce on ordering_groceries
var/announcement_line
///The kind of cash does the console use.
var/credit_type = CREDIT_TYPE_CREDIT
@@ -41,11 +41,6 @@ GLOBAL_LIST_EMPTY(order_console_products)
/obj/machinery/computer/order_console/Initialize(mapload)
. = ..()
radio = new(src)
radio.set_frequency(FREQ_SUPPLY)
radio.subspace_transmission = TRUE
radio.canhear_range = 0
radio.recalculateChannels()
if(GLOB.order_console_products.len)
return
@@ -54,10 +49,6 @@ GLOBAL_LIST_EMPTY(order_console_products)
continue
GLOB.order_console_products += new path
/obj/machinery/computer/order_console/Destroy()
QDEL_NULL(radio)
return ..()
/obj/machinery/computer/order_console/proc/get_total_cost()
var/cost = 0
for(var/datum/orderable_item/item as anything in grocery_list)
@@ -244,4 +235,21 @@ GLOBAL_LIST_EMPTY(order_console_products)
/obj/machinery/computer/order_console/proc/order_groceries(mob/living/purchaser, obj/item/card/id/card, list/groceries)
return
/datum/aas_config_entry/order_console
name = "Local Ordering Console Announcements"
announcement_lines_map = list()
general_tooltip = "Used to make announces, when consoles listed here placing new order"
/datum/aas_config_entry/order_console/New()
. = ..()
for(var/obj/machinery/computer/order_console/subconsole as anything in subtypesof(/obj/machinery/computer/order_console))
if(subconsole.blackbox_key)
announcement_lines_map[capitalize(subconsole.blackbox_key)] = subconsole.announcement_line
/datum/aas_config_entry/order_console/compile_announce(list/variables_map, announcement_line)
if (!announcement_lines_map.len)
announcement_lines_map["Error"] = "Unknown Error happened, while we tried to procceed an order, please report this to Nanotrasen."
. = ..()
#undef CREDIT_TYPE_CREDIT
+12 -7
View File
@@ -35,15 +35,12 @@
var/list/flashers = list()
///List of weakrefs to nearby closets
var/list/closets = list()
///needed to send messages to sec radio
var/obj/item/radio/sec_radio
///Channel to report prisoneer's release
var/broadcast_channel = RADIO_CHANNEL_SECURITY
/obj/machinery/status_display/door_timer/Initialize(mapload)
. = ..()
sec_radio = new/obj/item/radio(src)
sec_radio.set_listening(FALSE)
if(id != null)
for(var/obj/machinery/door/window/brigdoor/M in urange(20, src))
if (M.id == id)
@@ -140,8 +137,7 @@
return 0
if(!forced)
sec_radio.set_frequency(FREQ_SECURITY)
sec_radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY)
aas_config_announce(/datum/aas_config_entry/brig_cell_release_announcement, list("CELL" = name), src, list(broadcast_channel))
timing = FALSE
activation_time = 0
@@ -284,6 +280,15 @@
continue
timer_end(forced = TRUE)
/datum/aas_config_entry/brig_cell_release_announcement
name = "Security Alert: Cell Timer Expired"
announcement_lines_map = list(
"Message" = "Timer for %CELL has expired. Releasing prisoner.",
)
vars_and_tooltips_map = list(
"CELL" = "will be replaced with the cell name.",
)
#undef PRESET_SHORT
#undef PRESET_MEDIUM
#undef PRESET_LONG
+58 -30
View File
@@ -43,8 +43,6 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
var/message_verified_by = ""
/// If a message is stamped, this will contain the stamp name
var/message_stamped_by = ""
/// Reference to the internal radio
var/obj/item/radio/radio
///If an emergency has been called by this device. Acts as both a cooldown and lets the responder know where it the emergency was triggered from
var/emergency
/// If ore redemption machines will send an update when it receives new ores.
@@ -124,13 +122,9 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
GLOB.req_console_all += src
GLOB.req_console_ckey_departments[ckey(department)] = department // and then we set ourselves a listed name
radio = new /obj/item/radio(src)
radio.set_listening(FALSE)
find_and_hang_on_wall()
/obj/machinery/requests_console/Destroy()
QDEL_NULL(radio)
QDEL_LIST(messages)
GLOB.req_console_all -= src
return ..()
@@ -168,20 +162,15 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
if("set_emergency")
if(emergency)
return
var/radio_freq
switch(params["emergency"])
if(REQ_EMERGENCY_SECURITY) //Security
radio_freq = FREQ_SECURITY
aas_config_announce(/datum/aas_config_entry/rc_emergency, list("LOCATION" = department), null, list(RADIO_CHANNEL_SECURITY), REQ_EMERGENCY_SECURITY)
if(REQ_EMERGENCY_ENGINEERING) //Engineering
radio_freq = FREQ_ENGINEERING
aas_config_announce(/datum/aas_config_entry/rc_emergency, list("LOCATION" = department), null, list(RADIO_CHANNEL_ENGINEERING), REQ_EMERGENCY_ENGINEERING)
if(REQ_EMERGENCY_MEDICAL) //Medical
radio_freq = FREQ_MEDICAL
if(radio_freq)
emergency = params["emergency"]
radio.set_frequency(radio_freq)
radio.talk_into(src,"[emergency] emergency in [department]!!",radio_freq)
update_appearance()
addtimer(CALLBACK(src, PROC_REF(clear_emergency)), 5 MINUTES)
aas_config_announce(/datum/aas_config_entry/rc_emergency, list("LOCATION" = department), null, list(RADIO_CHANNEL_MEDICAL), REQ_EMERGENCY_MEDICAL)
update_appearance()
addtimer(CALLBACK(src, PROC_REF(clear_emergency)), 5 MINUTES)
return TRUE
if("send_announcement")
if(!COOLDOWN_FINISHED(src, announcement_cooldown))
@@ -242,20 +231,22 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
///Sends the message from the request console
/obj/machinery/requests_console/proc/send_message(recipient, message, priority, request_type)
var/radio_freq
var/radio_channel
// They all naming them wrong, all the time... I'll probably rewrite this later in separate PR.
// Automatically from areas or via mapping helpers. (ther is no "Cargobay Request Console" in any map)
switch(ckey(recipient))
if("bridge")
radio_freq = FREQ_COMMAND
radio_channel = RADIO_CHANNEL_COMMAND
if("medbay")
radio_freq = FREQ_MEDICAL
radio_channel = RADIO_CHANNEL_MEDICAL
if("science")
radio_freq = FREQ_SCIENCE
radio_channel = RADIO_CHANNEL_SCIENCE
if("engineering")
radio_freq = FREQ_ENGINEERING
radio_channel = RADIO_CHANNEL_ENGINEERING
if("security")
radio_freq = FREQ_SECURITY
radio_channel = RADIO_CHANNEL_SECURITY
if("cargobay", "mining")
radio_freq = FREQ_SUPPLY
radio_channel = RADIO_CHANNEL_SUPPLY
var/datum/signal/subspace/messaging/rc/signal = new(src, list(
"sender_department" = department,
@@ -264,7 +255,7 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
"verified" = message_verified_by,
"stamped" = message_stamped_by,
"priority" = priority,
"notify_freq" = radio_freq,
"notify_channel" = radio_channel,
"request_type" = request_type,
))
signal.send_to_receivers()
@@ -347,15 +338,26 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
SStgui.update_uis(src)
var/alert = new_message.get_alert()
if(!silent)
playsound(src, 'sound/machines/beep/twobeep_high.ogg', 50, TRUE)
say(alert)
say(new_message.get_alert())
if(new_message.radio_freq)
radio.set_frequency(new_message.radio_freq)
radio.talk_into(src, "[alert]: <i>[new_message.content]</i>", new_message.radio_freq)
if(new_message.radio_channel)
var/authentication
var/announcement_line = "Unauthenticated"
if (new_message.message_verified_by)
authentication = new_message.message_verified_by
announcement_line = "Verified with ID"
else if (new_message.message_stamped_by)
authentication = new_message.message_stamped_by
announcement_line = "Stamped with stamp"
aas_config_announce(/datum/aas_config_entry/rc_new_message, list(
"AUTHENTICATION" = authentication,
"SENDER" = new_message.sender_department,
"RECEIVER" = department,
"MESSAGE" = new_message.content
), null, list(new_message.radio_channel), announcement_line, new_message.priority == REQ_EXTREME_MESSAGE_PRIORITY)
/obj/machinery/requests_console/crowbar_act(mob/living/user, obj/item/tool)
tool.play_tool_sound(src, 50)
@@ -412,6 +414,32 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/requests_console/auto_name, 30)
result_path = /obj/machinery/requests_console/auto_name
pixel_shift = 30
/datum/aas_config_entry/rc_emergency
name = "RC Alert: Emergency"
announcement_lines_map = list(
"Security" = "Security emergency in %LOCATION!!!",
"Engineering" = "Engineering emergency in %LOCATION!!!",
"Medical" = "Medical emergency in %LOCATION!!!",
)
vars_and_tooltips_map = list(
"LOCATION" = "will be replaced with the department name",
)
/datum/aas_config_entry/rc_new_message
name = "RC Alert: New Message "
// Yes, players can't use html tags, however they can use speech mods like | or +, but sh-sh-sh, don't tell them!
announcement_lines_map = list(
"Unauthenticated" = "Message from %SENDER to %RECEIVER: <i>%MESSAGE</i>",
"Verified with ID" = "Message from %SENDER to %RECEIVER, Verified by %AUTHENTICATION (Authenticated): <i>%MESSAGE</i>",
"Stamped with stamp" = "Message from %SENDER to %RECEIVER, Stamped by %AUTHENTICATION (Authenticated): <i>%MESSAGE</i>",
)
vars_and_tooltips_map = list(
"AUTHENTICATION" = "will be replaced with ID or stamp, if present",
"SENDER" = "with the sender department ",
"RECEIVER" = "with the receiver department",
"MESSAGE" = "with the message content",
)
#undef REQ_EMERGENCY_SECURITY
#undef REQ_EMERGENCY_ENGINEERING
#undef REQ_EMERGENCY_MEDICAL
@@ -101,9 +101,9 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)
var/datum/techweb/station_techweb = locate(/datum/techweb/science) in SSresearch.techwebs
if(station_techweb)
var/obj/machinery/announcement_system/announcement_system = pick(GLOB.announcement_systems)
var/obj/machinery/announcement_system/announcement_system = get_announcement_system()
if (!isnull(announcement_system))
announcement_system.broadcast("Additional research data received from Nanotrasen R&D Division following the emergency protocol.", list(RADIO_CHANNEL_SCIENCE))
announcement_system.broadcast("Additional research data received from Nanotrasen R&D Division following the emergency protocol.", list(RADIO_CHANNEL_SCIENCE), TRUE)
station_techweb.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS * 3))
qdel(src)
@@ -92,8 +92,6 @@
var/conduction_coefficient = 0.3
///The beaker usually contains cryoxadone that is pumped into the mob
var/obj/item/reagent_containers/cup/beaker = null
///Inform medical about cryo status over this radio
var/obj/item/radio/radio
/// Visual content - Occupant
var/atom/movable/visual/cryo_occupant/occupant_vis
///Cryo will continue to treat people with 0 damage but existing wounds, but will sound off when damage healing is done in case doctors want to directly treat the wounds instead
@@ -104,6 +102,8 @@
var/on = FALSE
/// The sound loop that can be heard when the generator is processing.
var/datum/looping_sound/cryo_cell/soundloop
/// For away sites, custom or admin events
var/broadcast_channel = RADIO_CHANNEL_MEDICAL
/datum/armor/unary_cryo_cell
energy = 100
@@ -113,12 +113,6 @@
/obj/machinery/cryo_cell/Initialize(mapload)
. = ..()
radio = new(src)
radio.keyslot = new /obj/item/encryptionkey/headset_med
radio.subspace_transmission = TRUE
radio.canhear_range = 0
radio.recalculateChannels()
occupant_vis = new(mapload, src)
vis_contents += occupant_vis
internal_connector = new(loc, src, dir, CELL_VOLUME * 0.5)
@@ -131,7 +125,6 @@
vis_contents.Cut()
QDEL_NULL(occupant_vis)
QDEL_NULL(radio)
QDEL_NULL(beaker)
QDEL_NULL(internal_connector)
QDEL_NULL(soundloop)
@@ -416,12 +409,10 @@
mob_occupant.extinguish_mob()
if(mob_occupant.stat == DEAD) // Notify doctors and potentially eject if the patient is dead
set_on(FALSE)
var/msg = "Patient is deceased."
aas_config_announce(/datum/aas_config_entry/medical_cryo_announcements, list("EJECTING" = autoeject), src, list(broadcast_channel), "Deceased")
if(autoeject) // Eject if configured.
msg += " Auto ejecting patient now."
open_machine()
playsound(src, 'sound/machines/cryo_warning.ogg', 100)
radio.talk_into(src, msg, RADIO_CHANNEL_MEDICAL)
return PROCESS_KILL
// Don't bother with fully healed people.
@@ -432,18 +423,16 @@
if(!treating_wounds) // if we have wounds and haven't already alerted the doctors we're only dealing with the wounds, let them know
treating_wounds = TRUE
playsound(src, 'sound/machines/cryo_warning.ogg', 100) // Bug the doctors.
radio.talk_into(src, "Patient vitals fully recovered, continuing automated wound treatment.", RADIO_CHANNEL_MEDICAL)
aas_config_announce(/datum/aas_config_entry/medical_cryo_announcements, list(), src, list(broadcast_channel), "Wound Treatment")
else // otherwise if we were only treating wounds and now we don't have any, turn off treating_wounds so we can boot 'em out
treating_wounds = FALSE
if(!treating_wounds)
set_on(FALSE)
playsound(src, 'sound/machines/cryo_warning.ogg', 100) // Bug the doctors.
var/msg = "Patient fully restored."
aas_config_announce(/datum/aas_config_entry/medical_cryo_announcements, list("EJECTING" = autoeject), src, list(broadcast_channel), "Fully Recovered")
if(autoeject) // Eject if configured.
msg += " Auto ejecting patient now."
open_machine()
radio.talk_into(src, msg, RADIO_CHANNEL_MEDICAL)
return PROCESS_KILL
var/datum/gas_mixture/air1 = internal_connector.gas_connector.airs[1]
@@ -464,11 +453,9 @@
//check for workable conditions
if(!internal_connector.gas_connector.nodes[1] || !air1 || !air1.gases.len || air1.total_moles() < CRYO_MIN_GAS_MOLES) // Turn off if the machine won't work.
set_on(FALSE)
var/msg = "Insufficient cryogenic gas, shutting down."
aas_config_announce(/datum/aas_config_entry/medical_cryo_announcements, list("EJECTING" = autoeject), src, list(broadcast_channel), "Insufficient Gas")
if(autoeject) // Eject if configured.
msg += " Auto ejecting patient now."
open_machine()
radio.talk_into(src, msg, RADIO_CHANNEL_MEDICAL)
return PROCESS_KILL
//take damage from high temperatures
@@ -679,6 +666,26 @@
/obj/machinery/cryo_cell/get_remote_view_fullscreens(mob/user)
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
/datum/aas_config_entry/medical_cryo_announcements
name = "Medical Alert: Cryogenics Reports"
announcement_lines_map = list(
"Autoejecting" = "Auto ejecting patient now.",
"Deceased" = "Cryogenics report: Patient is deceased. %AUTOEJECTING",
"Fully Recovered" = "Cryogenics report: Patient fully restored. %AUTOEJECTING",
"Insufficient Gas" = "Cryogenics report: Insufficient cryogenic gas, shutting down. %AUTOEJECTING",
"Wound Treatment" = "Cryogenics report: Patient vitals fully recovered, continuing automated wound treatment."
)
vars_and_tooltips_map = list(
"AUTOEJECTING" = "will be replaced with Autoejecting line, if system reports it's necessity"
)
/datum/aas_config_entry/medical_cryo_announcements/compile_announce(list/variables_map, announcement_line)
variables_map["AUTOEJECTING"] = variables_map["EJECTING"] ? announcement_lines_map["Autoejecting"] : ""
. = ..()
// Why double replacetext_char? Well, to handle cases where variable in the middle of sentence like "also %AUTOEJECTING this", so there will be no double spaces
// Yeah I am bad, at this, sorry (it should be a perfect place for regex usage, but I am weak)
. = trim(replacetext_char(replacetext_char(., "\[NO DATA\] ", ""), "\[NO DATA\]", ""))
#undef MAX_TEMPERATURE
#undef CRYO_MULTIPLY_FACTOR
#undef CRYO_TX_QTY
+2 -1
View File
@@ -23,6 +23,7 @@
CATEGORY_BEPIS,
)
blackbox_key = "bitrunning"
announcement_line = "A bitrunner has ordered equipment which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!"
/obj/machinery/computer/order_console/bitrunning/subtract_points(final_cost, obj/item/card/id/card)
if(final_cost <= card.registered_account.bitrunning_points)
@@ -56,7 +57,7 @@
can_be_cancelled = FALSE,
)
say("Thank you for your purchase! It will arrive on the next cargo shuttle!")
radio.talk_into(src, "A bitrunner has ordered equipment which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!", radio_channel)
aas_config_announce(/datum/aas_config_entry/order_console, list(), src, list(radio_channel), capitalize(blackbox_key))
SSshuttle.shopping_list += new_order
/obj/machinery/computer/order_console/bitrunning/retrieve_points(obj/item/card/id/id_card)
+7 -8
View File
@@ -28,8 +28,6 @@
var/list/datum/weakref/spawned_threat_refs = list()
/// Scales loot with extra players
var/multiplayer_bonus = 1.1
///The radio the console can speak into
var/obj/item/radio/radio
/// The amount of points in the system, used to purchase maps
var/points = 0
/// Keeps track of the number of times someone has built a hololadder
@@ -54,11 +52,6 @@
/obj/machinery/quantum_server/post_machine_initialize()
. = ..()
radio = new(src)
radio.keyslot = new /obj/item/encryptionkey/headset_cargo()
radio.set_listening(FALSE)
radio.recalculateChannels()
RegisterSignals(src, list(COMSIG_MACHINERY_BROKEN, COMSIG_MACHINERY_POWER_LOST), PROC_REF(on_broken))
RegisterSignal(src, COMSIG_QDELETING, PROC_REF(on_delete))
@@ -70,7 +63,6 @@
spawned_threat_refs.Cut()
QDEL_NULL(exit_turfs)
QDEL_NULL(generated_domain)
QDEL_NULL(radio)
/obj/machinery/quantum_server/examine(mob/user)
. = ..()
@@ -178,3 +170,10 @@
servo_bonus = servo_rating
return ..()
/datum/aas_config_entry/bitrunning_QS_ready_announcement
name = "Cargo Alert: Bitrunning QS Ready"
general_tooltip = "Announces when the quantum server is ready to be used. No variables provided"
announcement_lines_map = list(
"Message" = "Quantum Server report: Thermal systems within operational parameters. Proceeding to domain configuration."
)
+7 -4
View File
@@ -132,12 +132,15 @@
/obj/machinery/quantum_server/proc/station_spawn(mob/living/antag, obj/machinery/byteforge/chosen_forge)
antag.balloon_alert(antag, "scanning...")
chosen_forge.setup_particles(angry = TRUE)
radio.talk_into(src, "SECURITY BREACH: Unauthorized entry sequence detected.", RADIO_CHANNEL_SUPPLY)
var/obj/machinery/announcement_system/aas = get_announcement_system(source = src)
if (aas)
aas.broadcast("QUANTUM SERVER ALERT: Security breach detected. Unauthorized entry sequence in progress...", list(RADIO_CHANNEL_SUPPLY))
SEND_SIGNAL(src, COMSIG_BITRUNNER_STATION_SPAWN)
var/timeout = 2 SECONDS
if(!ishuman(antag))
radio.talk_into(src, "Fabrication protocols have crashed unexpectedly. Please evacuate the area.", RADIO_CHANNEL_SUPPLY)
if (aas)
aas.broadcast("QUANTUM SERVER ALERT: Fabrication protocols have crashed unexpectedly. Please evacuate the area.", list(RADIO_CHANNEL_SUPPLY))
timeout = 10 SECONDS
if(!do_after(antag, timeout) || QDELETED(chosen_forge) || QDELETED(antag) || QDELETED(src) || !is_ready || !is_operational)
@@ -159,8 +162,8 @@
if(ishuman(antag))
reset_equipment(antag)
else
radio.talk_into(src, "CRITICAL ALERT: Unregistered mechanical entity deployed.")
else if (aas)
aas.broadcast("QUANTUM SERVER CRITICAL ALERT: Unregistered mechanical entity deployed.", list())
var/datum/antagonist/antag_datum = antag.mind?.has_antag_datum(/datum/antagonist/bitrunning_glitch)
if(istype(antag_datum))
+1 -1
View File
@@ -12,7 +12,7 @@
balloon_alert_to_viewers("cooldown has completed")
return
//BUBBER ADDITION END
radio.talk_into(src, "Thermal systems within operational parameters. Proceeding to domain configuration.", RADIO_CHANNEL_SUPPLY)
aas_config_announce(/datum/aas_config_entry/bitrunning_QS_ready_announcement, list(), src, list(RADIO_CHANNEL_SUPPLY))
/// If there are hosted minds, attempts to get a list of their current virtual bodies w/ vitals
+11 -12
View File
@@ -17,8 +17,6 @@
human remains, classified nuclear weaponry, mail, undelivered departmental order crates, syndicate bombs, \
homing beacons, unstable eigenstates, fax machines, or machinery housing any form of artificial intelligence."
var/blockade_warning = "Bluespace instability detected. Shuttle movement impossible."
/// radio used by the console to send messages on supply channel
var/obj/item/radio/headset/radio
/// var that tracks message cooldown
var/message_cooldown
var/list/loaded_coupons
@@ -46,14 +44,6 @@
can_approve_requests = FALSE
requestonly = TRUE
/obj/machinery/computer/cargo/Initialize(mapload)
. = ..()
radio = new /obj/item/radio/headset/headset_cargo(src)
/obj/machinery/computer/cargo/Destroy()
QDEL_NULL(radio)
return ..()
/obj/machinery/computer/cargo/attacked_by(obj/item/I, mob/living/user)
if(istype(I,/obj/item/trade_chip))
var/obj/item/trade_chip/contract = I
@@ -311,8 +301,7 @@
if(self_paid)
say("Order processed. The price will be charged to [account.account_holder]'s bank account on delivery.")
if(requestonly && message_cooldown < world.time)
var/message = amount == 1 ? "A new order has been requested." : "[amount] order has been requested."
radio.talk_into(src, message, RADIO_CHANNEL_SUPPLY)
aas_config_announce(/datum/aas_config_entry/cargo_orders_announcement, list("AMOUNT" = amount), src, list(RADIO_CHANNEL_SUPPLY), amount == 1 ? "Single Order" : "Multiple Orders")
message_cooldown = world.time + 30 SECONDS
. = TRUE
@@ -487,3 +476,13 @@
var/datum/signal/status_signal = new(list("command" = command))
frequency.post_signal(src, status_signal)
/datum/aas_config_entry/cargo_orders_announcement
name = "Cargo Alert: New Orders"
announcement_lines_map = list(
"Single Order" = "A new order has been requested.",
"Multiple Orders" = "%AMOUNT orders have been requested.",
)
vars_and_tooltips_map = list(
"AMOUNT" = "will be replaced wuth number of orders.",
)
+4 -14
View File
@@ -253,20 +253,10 @@
dna.species.pre_equip_species_outfit(equipping, src, visual_only)
equip_outfit_and_loadout(equipping.get_outfit(consistent), player_client?.prefs, visual_only, equipping) // SKYRAT EDIT CHANGE - Add equipping param
/datum/job/proc/announce_head(mob/living/carbon/human/human, channels, job_title) //tells the given channel that the given mob is the new department head. See communications.dm for valid channels. // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES
if(!human)
return
var/obj/machinery/announcement_system/system
var/list/available_machines = list()
for(var/obj/machinery/announcement_system/announce as anything in GLOB.announcement_systems)
if(announce.newhead_toggle)
available_machines += announce
break
if(!length(available_machines))
return
system = pick(available_machines)
//timer because these should come after the captain announcement
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(_addtimer), CALLBACK(system, TYPE_PROC_REF(/obj/machinery/announcement_system, announce), AUTO_ANNOUNCE_NEWHEAD, human.real_name, job_title, channels), 1)) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES
/datum/job/proc/announce_head(mob/living/carbon/human/human, channels) //tells the given channel that the given mob is the new department head. See communications.dm for valid channels. // BUBBER EDIT CHANGE - ALTERNATIVE_JOB_TITLES
if(human)
//timer because these should come after the captain announcement
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(_addtimer), CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(aas_config_announce), /datum/aas_config_entry/newhead, list("PERSON" = human.real_name, "RANK" = job_title), null, channels, null, TRUE), 1)) // BUBBER EDIT CHANGE - ALTERNATIVE_JOB_TITLES
//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1
/datum/job/proc/player_old_enough(client/player)
@@ -165,11 +165,14 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
department,
distribution,
)
var/obj/machinery/announcement_system/announcement_system = pick(GLOB.announcement_systems)
var/obj/machinery/announcement_system/announcement_system = get_announcement_system(/datum/aas_config_entry/announce_officer)
if (isnull(announcement_system))
return
announcement_system.announce_officer(officer, department)
announcement_system.announce(/datum/aas_config_entry/announce_officer, list(
"OFFICER" = officer.real_name,
"DEPARTMENT" = department,
), list(RADIO_CHANNEL_SECURITY))
var/list/targets = list()
@@ -190,10 +193,14 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
if (!targets.len)
return
// I thought it would be great, if AAS also modifies PDA messages. Especially because it's AASs message.
var/datum/signal/subspace/messaging/tablet_message/signal = new(announcement_system, list(
"fakename" = "Security Department Update",
"fakejob" = "Automated Announcement System",
"message" = "Officer [officer.real_name] has been assigned to your department, [department].",
"message" = announcement_system.compile_config_message(/datum/aas_config_entry/announce_officer, list(
"OFFICER" = officer.real_name,
"DEPARTMENT" = department,
)),
"targets" = targets,
"automated" = TRUE,
))
+15 -8
View File
@@ -104,21 +104,16 @@ GLOBAL_DATUM_INIT(lost_crew_manager, /datum/lost_crew_manager, new)
/// Give medbay a happy announcement and put some money into their budget
/datum/lost_crew_manager/proc/award_succes(datum/mind/revived_mind, list/death_lore)
var/obj/item/radio/headset/radio = new /obj/item/radio/headset/silicon/ai(revived_mind.current) //radio cant be in nullspace or brit shakes
radio.set_frequency(FREQ_MEDICAL)
radio.name = "Medical Announcer"
// i am incredibly disappointed in you
// I am incredibly disappointed in you
if(revived_mind.current.stat == DEAD)
radio.talk_into(radio, "Sensors indicate lifesigns of [revived_mind.name] have seized. Please inform their family of your failure.", RADIO_CHANNEL_MEDICAL)
aas_config_announce(/datum/aas_config_entry/medical_lost_crew_reward, list("PERSON" = revived_mind.name, "AWARD" = 0), null, list(RADIO_CHANNEL_MEDICAL), "Deceased")
return
// You are a credit to society
radio.talk_into(radio, "Sensors indicate continued survival of [revived_mind.name]. Well done, [credits_on_succes]cr has been transferred to the medical budget.", RADIO_CHANNEL_MEDICAL)
aas_config_announce(/datum/aas_config_entry/medical_lost_crew_reward, list("PERSON" = revived_mind.name, "AWARD" = credits_on_succes), null, list(RADIO_CHANNEL_MEDICAL), "Revived")
var/datum/bank_account/medical_budget = SSeconomy.get_dep_account(ACCOUNT_MED)
medical_budget.adjust_money(credits_on_succes)
qdel(radio)
/// A box for recovered items that can only be opened by the new crewmember
/obj/item/storage/lockbox/mind
@@ -162,3 +157,15 @@ GLOBAL_DATUM_INIT(lost_crew_manager, /datum/lost_crew_manager, new)
return NONE
context[SCREENTIP_CONTEXT_LMB] = "Use in-hand to unlock"
return CONTEXTUAL_SCREENTIP_SET
/datum/aas_config_entry/medical_lost_crew_reward
name = "Medical Alert: Lost Crew Revival Program"
announcement_lines_map = list(
"Deceased" = "Sensors indicate lifesigns of %PERSON have seized. Please inform their family of your failure.",
"Revived" = "Sensors indicate continued survival of %PERSON. Well done, %AWARDcr has been transferred to the medical budget."
)
vars_and_tooltips_map = list(
"PERSON" = "will be replaced with body's name",
"AWARD" = "with money that medical department receive, if any"
)
modifiable = FALSE
+10 -7
View File
@@ -10,8 +10,6 @@
density = FALSE
/// Connected stacking machine
var/obj/machinery/mineral/stacking_machine/laborstacker/stacking_machine
/// Needed to send messages to sec radio
var/obj/item/radio/security_radio
/// Whether the claim console initiated the launch.
var/initiated_launch = FALSE
/// Cooldown for console says.
@@ -19,8 +17,6 @@
/obj/machinery/mineral/labor_claim_console/Initialize(mapload)
. = ..()
security_radio = new /obj/item/radio(src)
security_radio.set_listening(FALSE)
locate_stacking_machine()
if(!SSshuttle.initialized)
RegisterSignal(SSshuttle, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(register_shuttle_signal))
@@ -37,7 +33,6 @@
UnregisterSignal(SSshuttle, COMSIG_SUBSYSTEM_POST_INITIALIZE)
/obj/machinery/mineral/labor_claim_console/Destroy()
QDEL_NULL(security_radio)
if(stacking_machine)
stacking_machine.labor_console = null
stacking_machine = null
@@ -130,11 +125,10 @@
COOLDOWN_START(src, say_cooldown, 2 SECONDS)
else
if(!(obj_flags & EMAGGED))
security_radio.set_frequency(FREQ_SECURITY)
var/datum/record/crew/target = find_record(user_mob.real_name)
target?.wanted_status = WANTED_PAROLE
security_radio.talk_into(src, "[user_mob.name] returned to the station. Minerals and Prisoner ID card ready for retrieval.", FREQ_SECURITY)
aas_config_announce(/datum/aas_config_entry/security_labor_stacker, list("PERSON" = user_mob.real_name), src, list(RADIO_CHANNEL_SECURITY))
user_mob.log_message("has completed their labor points goal and is now sending the gulag shuttle back to the station.", LOG_GAME)
say("Labor sentence finished, shuttle returning.")
initiated_launch = TRUE
@@ -227,4 +221,13 @@
say("Points Collected: [prisoner_id.points] / [prisoner_id.goal].")
say("Collect points by bringing smelted minerals to the Labor Shuttle stacking machine. Reach your quota to earn your release.")
/datum/aas_config_entry/security_labor_stacker
name = "Security Alert: Labor Camp Release"
announcement_lines_map = list(
"Message" = "%PERSON returned to the station. Minerals and Prisoner ID card ready for retrieval."
)
vars_and_tooltips_map = list(
"PERSON" = "will be replaced with the name of the prisoner."
)
#undef SHEET_POINT_VALUE
@@ -32,18 +32,16 @@ GLOBAL_VAR(department_cd_override)
)
/// Reference to the order we've made UNTIL it gets sent on the supply shuttle. this is so heads can cancel it
VAR_PRIVATE/datum/supply_order/department_order
/// Our radio object we use to talk to our department.
VAR_PRIVATE/obj/item/radio/radio
/// The radio channel we will speak into by default.
VAR_PRIVATE/radio_channel
/// Maps what department gets what encryption key
/// Maps what department should report to what radio channel
/// I could've put this on the job department datum but it felt unnecessary
VAR_PRIVATE/static/list/dept_to_radio = list(
/datum/job_department/engineering = /obj/item/encryptionkey/headset_eng,
/datum/job_department/medical = /obj/item/encryptionkey/headset_med,
/datum/job_department/science = /obj/item/encryptionkey/headset_sci,
/datum/job_department/security = /obj/item/encryptionkey/headset_sec,
/datum/job_department/service = /obj/item/encryptionkey/headset_service,
VAR_PRIVATE/static/list/dept_to_radio_channel = list(
/datum/job_department/engineering = RADIO_CHANNEL_ENGINEERING,
/datum/job_department/medical = RADIO_CHANNEL_MEDICAL,
/datum/job_department/science = RADIO_CHANNEL_SCIENCE,
/datum/job_department/security = RADIO_CHANNEL_SECURITY,
/datum/job_department/service = RADIO_CHANNEL_SERVICE,
)
/// Sets the passed department type as the active department for this computer file.
@@ -56,22 +54,10 @@ GLOBAL_VAR(department_cd_override)
use_access |= linked_department_real.head_of_staff_access
use_access |= linked_department_real.department_access
// Also set up the radio
if(dept_to_radio[linked_department])
if(!isnull(radio))
QDEL_NULL(radio)
var/picked_key = dept_to_radio[linked_department] || /obj/item/encryptionkey/headset_cargo
radio = new(computer)
radio.keyslot = new picked_key()
radio.subspace_transmission = TRUE
radio.canhear_range = 0
radio.recalculateChannels()
radio_channel = radio.keyslot.channels[1]
if(dept_to_radio_channel[linked_department])
radio_channel = dept_to_radio_channel[linked_department] || RADIO_CHANNEL_SUPPLY
computer.update_static_data_for_all_viewers()
/datum/computer_file/program/department_order/Destroy()
QDEL_NULL(radio)
return ..()
/datum/computer_file/program/department_order/ui_interact(mob/user, datum/tgui/ui)
check_cooldown()
@@ -244,6 +230,9 @@ GLOBAL_VAR(department_cd_override)
SSshuttle.shopping_list += department_order
if(!already_signalled)
RegisterSignal(SSshuttle, COMSIG_SUPPLY_SHUTTLE_BUY, PROC_REF(finalize_department_order))
if(!alert_silenced && alert_able)
aas_config_announce(/datum/aas_config_entry/department_orders, list("ORDER" = pack.name, "PERSON" = name), computer.physical, list(radio_channel), "Order Placed")
aas_config_announce(/datum/aas_config_entry/department_orders_cargo, list("DEPARTMENT" = linked_department.department_name), computer.physical, list(RADIO_CHANNEL_SUPPLY))
computer.physical.say("Order processed. Cargo will deliver the crate when it comes in on their shuttle. NOTICE: Heads of staff may override the order.")
calculate_cooldown(pack.cost)
@@ -266,7 +255,7 @@ GLOBAL_VAR(department_cd_override)
/datum/computer_file/program/department_order/process_tick(seconds_per_tick)
if(!check_cooldown() || alert_silenced || !alert_able)
return
radio?.talk_into(computer, "Order cooldown has expired! A new order may now be placed!", radio_channel)
aas_config_announce(/datum/aas_config_entry/department_orders, list(), computer.physical, list(radio_channel), "Cooldown Reset")
computer.alert_call(src, "Order cooldown expired!", 'sound/machines/ping.ogg')
/// Checks if the cooldown is up and resets it if so.
@@ -275,3 +264,23 @@ GLOBAL_VAR(department_cd_override)
department_cooldowns[linked_department] = 0
return TRUE
return FALSE
/datum/aas_config_entry/department_orders
name = "Departmental Order Announcement"
announcement_lines_map = list(
"Order Placed" = "A department order has been placed by %PERSON for %ORDER.",
"Cooldown Reset" = "Department order cooldown has expired! A new order may now be placed!",
)
vars_and_tooltips_map = list(
"ORDER" = "will be replaced with the package name",
"PERSON" = "with the orderer's name",
)
/datum/aas_config_entry/department_orders_cargo
name = "Cargo Alert: New Departmental Order"
announcement_lines_map = list(
"Message" = "New %DEPARTMENT departmental order has been placed"
)
vars_and_tooltips_map = list(
"DEPARTMENT" = "will be replaced with orderer's department."
)
+11 -12
View File
@@ -411,8 +411,6 @@
var/damage = 0
///Used to calculate the max damage received per tick and if the alarm should be called
var/damage_archived = 0
///Our internal radio
var/obj/item/radio/radio
COOLDOWN_DECLARE(turbine_damage_alert)
@@ -420,17 +418,8 @@
//Volume of gas mixture is 3000
. = ..(mapload, gas_theoretical_volume = 3000)
radio = new(src)
radio.keyslot = new /obj/item/encryptionkey/headset_eng
radio.set_listening(FALSE)
radio.recalculateChannels()
new /obj/item/paper/guides/jobs/atmos/turbine(loc)
/obj/machinery/power/turbine/core_rotor/Destroy()
QDEL_NULL(radio)
return ..()
/obj/machinery/power/turbine/core_rotor/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if(. == NONE)
@@ -670,7 +659,7 @@
explosion(src, 2, 5, 7)
return PROCESS_KILL
radio.talk_into(src, "Warning, turbine at [get_area_name(src)] taking damage, current integrity at [integrity]%!", RADIO_CHANNEL_ENGINEERING)
aas_config_announce(/datum/aas_config_entry/engineering_turbine_failure, list("INTEGRITY" = integrity, "LOCATION" = get_area_name(src)), src, list(RADIO_CHANNEL_ENGINEERING))
playsound(src, 'sound/machines/engine_alert/engine_alert1.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
//================ROTOR WORKING============//
@@ -707,5 +696,15 @@
-Each tier increases the efficiency (more power), the max reachable RPM, and the max temperature that the machine can process without taking damage (up to fusion temperatures at the last tier!).<BR>\
-A word of warning, the machine is very inefficient in its gas consumption and many unburnt gases will pass through. If you want to be cheap you can either pre-burn the gases or add a filtering system to collect the unburnt gases and reuse them."
/datum/aas_config_entry/engineering_turbine_failure
name = "Engineering Alert: Turbine Failure"
announcement_lines_map = list(
"Message" = "Warning, turbine at %LOCATION taking damage, current integrity at %INTEGRITY%!",
)
vars_and_tooltips_map = list(
"LOCATION" = "will be replaced with location of the turbine.",
"INTEGRITY" = "with the current integrity of the turbine.",
)
#undef PRESSURE_MAX
#undef MINIMUM_TURBINE_PRESSURE
+2 -12
View File
@@ -125,15 +125,5 @@
return
if(board.obj_flags & EMAGGED)
channels_to_use = list(RADIO_CHANNEL_COMMON)
if(!length(channels_to_use) || starting_node)
return
var/obj/machinery/announcement_system/system
var/list/available_machines = list()
for(var/obj/machinery/announcement_system/announce as anything in GLOB.announcement_systems)
if(announce.announce_research_node)
available_machines += announce
break
if(!length(available_machines))
return
system = pick(available_machines)
system.announce(AUTO_ANNOUNCE_NODE, display_name, channels = channels_to_use)
if(length(channels_to_use) && !starting_node)
aas_config_announce(/datum/aas_config_entry/researched_node, list("NODE" = display_name), null, channels_to_use)
@@ -80,10 +80,7 @@
damaged = TRUE
if(console)
console.say("Alert, hull breach detected!")
if (length(GLOB.announcement_systems))
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
if(!QDELETED(announcer))
announcer.announce("ARRIVALS_BROKEN", channels = list())
aas_config_announce(/datum/aas_config_entry/arrivals_broken, list(), command_span=TRUE)
if(mode != SHUTTLE_CALL)
sound_played = FALSE
mode = SHUTTLE_IDLE
+18 -9
View File
@@ -217,9 +217,6 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock)
///Name of lighting mask for the vending machine
var/light_mask
/// used for narcing on underages
var/obj/item/radio/sec_radio
//the path of the fish_source datum to use for the fishing_spot component
var/fish_source_path = /datum/fish_source/vending
@@ -288,7 +285,6 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock)
/obj/machinery/vending/Destroy()
QDEL_NULL(coin)
QDEL_NULL(bill)
QDEL_NULL(sec_radio)
GLOB.vending_machines_to_restock -= src
return ..()
@@ -1441,11 +1437,12 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock)
if(age_restrictions && item_record.age_restricted && (!card_used.registered_age || card_used.registered_age < AGE_MINOR))
speak("You are not of legal age to purchase [item_record.name].")
if(!(usr in GLOB.narcd_underages))
if (isnull(sec_radio))
sec_radio = new (src)
sec_radio.set_listening(FALSE)
sec_radio.set_frequency(FREQ_SECURITY)
sec_radio.talk_into(src, "SECURITY ALERT: [usr] recorded attempting to purchase [item_record.name] in [get_area(src)]. Please watch for substance abuse.", FREQ_SECURITY) // SKYRAT EDIT CHANGE
aas_config_announce(/datum/aas_config_entry/vendomat_age_control, list(
"PERSON" = usr.name,
"LOCATION" = get_area_name(src),
"VENDOR" = name,
"PRODUCT" = item_record.name
), src, list(RADIO_CHANNEL_SECURITY))
GLOB.narcd_underages += usr
flick(icon_deny,src)
vend_ready = TRUE
@@ -1918,4 +1915,16 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock)
add_filter("vending_outline", 9, list("type" = "outline", "color" = COLOR_VERY_SOFT_YELLOW))
add_filter("vending_rays", 10, list("type" = "rays", "size" = 35, "color" = COLOR_VIVID_YELLOW))
/datum/aas_config_entry/vendomat_age_control
name = "Security Alert: Underaged Substance Abuse"
announcement_lines_map = list(
"Message" = "SECURITY ALERT: Underaged crewmember %PERSON recorded attempting to purchase %PRODUCT in %LOCATION by %VENDOR. Please watch for substance abuse."
)
vars_and_tooltips_map = list(
"PERSON" = "will be replaced with the name of the crewmember",
"PRODUCT" = "with the product, he attempted to purchase",
"LOCATION" = "with place of purchase",
"VENDOR" = "with the vending machine"
)
#undef MAX_VENDING_INPUT_AMOUNT
@@ -1,142 +1,158 @@
import { Button, Input, LabeledList, Section } from 'tgui-core/components';
import { filter, sortBy } from 'common/collections';
import { useState } from 'react';
import {
Button,
Input,
LabeledList,
NoticeBox,
Section,
Stack,
Table,
} from 'tgui-core/components';
import { BooleanLike } from 'tgui-core/react';
import { useBackend } from '../backend';
import { Window } from '../layouts';
const TOOLTIP_TEXT = `
%PERSON will be replaced with their name.
%RANK with their job.
`;
const TOOLTIP_NODE = `
%NODE will be replaced with the researched node.
`;
type AASConfigEntry = {
name: string;
entryRef: string;
enabled: BooleanLike;
modifiable: BooleanLike;
announcementLinesMap: Record<string, string>;
generalTooltip: string;
varsAndTooltipsMap: Record<string, string>;
};
type Data = {
arrivalToggle: BooleanLike;
arrival: string;
newheadToggle: BooleanLike;
newhead: string;
node_toggle: BooleanLike;
node_message: string;
config_entries: AASConfigEntry[];
};
export const AutomatedAnnouncement = (props) => {
const { act, data } = useBackend<Data>();
const {
arrivalToggle,
arrival,
newheadToggle,
newhead,
node_toggle,
node_message,
} = data;
const { config_entries = [] } = data;
const [search, setSearch] = useState('');
const isEntryMatch = (entry: AASConfigEntry, search: string) => {
if (!search) return true;
const { name, announcementLinesMap = [], varsAndTooltipsMap = [] } = entry;
switch (true) {
case name?.toLowerCase().includes(search?.toLowerCase()):
case Object.keys(announcementLinesMap).some((lineKey) =>
lineKey.toLowerCase().includes(search?.toLowerCase()),
):
case Object.values(announcementLinesMap).some((line) =>
line.toLowerCase().includes(search?.toLowerCase()),
):
case Object.keys(varsAndTooltipsMap).some((varName) =>
varName.toLowerCase().includes(search?.toLowerCase()),
):
return true;
default:
return false;
}
};
const errorMessage = !config_entries.length
? 'No configurable options detected! Please report this to Nanotrasen.'
: 'No match. Refine your search.';
const sorted = sortBy(
filter(config_entries, (entry) => isEntryMatch(entry, search)),
(entry) => entry.name,
);
return (
<Window title="Automated Announcement System" width={500} height={225}>
<Window title="Automated Announcement System" width={500} height={280}>
<Window.Content>
<Section
title="Arrival Announcement"
buttons={
<Button
icon={arrivalToggle ? 'power-off' : 'times'}
selected={arrivalToggle}
content={arrivalToggle ? 'On' : 'Off'}
onClick={() => act('ArrivalToggle')}
/>
}
>
<LabeledList>
<LabeledList.Item
label="Message"
buttons={
<Button
icon="info"
tooltip={TOOLTIP_TEXT}
tooltipPosition="left"
<Stack fill vertical>
<Stack.Item>
<LabeledList>
<LabeledList.Item label="Search">
<Input
fluid
placeholder="Name/Line/Var"
onInput={(event, value) => setSearch(value)}
/>
}
>
<Input
fluid
value={arrival}
onChange={(e, value) =>
act('ArrivalText', {
newText: value,
})
}
/>
</LabeledList.Item>
</LabeledList>
</Section>
<Section
title="Departmental Head Announcement"
buttons={
<Button
icon={newheadToggle ? 'power-off' : 'times'}
selected={newheadToggle}
content={newheadToggle ? 'On' : 'Off'}
onClick={() => act('NewheadToggle')}
/>
}
>
<LabeledList>
<LabeledList.Item
label="Message"
buttons={
<Button
icon="info"
tooltip={TOOLTIP_TEXT}
tooltipPosition="left"
/>
}
>
<Input
fluid
value={newhead}
onChange={(e, value) =>
act('NewheadText', {
newText: value,
})
}
/>
</LabeledList.Item>
</LabeledList>
</Section>
<Section
title="Research Node Announcement"
buttons={
<Button
icon={node_toggle ? 'power-off' : 'times'}
selected={node_toggle}
content={node_toggle ? 'On' : 'Off'}
onClick={() => act('node_toggle')}
/>
}
>
<LabeledList>
<LabeledList.Item
label="Message"
buttons={
<Button
icon="info"
tooltip={TOOLTIP_NODE}
tooltipPosition="left"
/>
}
>
<Input
fluid
value={node_message}
onChange={(e, value) =>
act('node_message', {
newText: value,
})
}
/>
</LabeledList.Item>
</LabeledList>
</Section>
</LabeledList.Item>
</LabeledList>
</Stack.Item>
<Stack.Item grow>
{!sorted.length ? (
<NoticeBox>{errorMessage}</NoticeBox>
) : (
<Section fill scrollable>
{sorted.map((entry, index) => (
<Section
key={entry.entryRef}
title={entry.name}
buttons={
<>
<Button
icon="info"
tooltip={
(entry.generalTooltip
? entry.generalTooltip + '\n'
: '') +
Object.entries(entry.varsAndTooltipsMap)
.map(
([varName, tooltip]) =>
'%' + varName + ' ' + tooltip,
)
.join('\n')
}
tooltipPosition="left"
/>
<Button
icon={entry.enabled ? 'power-off' : 'times'}
selected={entry.enabled}
disabled={!entry.modifiable}
tooltip={
!entry.modifiable
? 'Editing disabled by CentCom!'
: undefined
}
onClick={() =>
act('Toggle', { entryRef: entry.entryRef })
}
>
{entry.enabled ? 'On' : 'Off'}
</Button>
</>
}
>
<Table>
{Object.entries(entry.announcementLinesMap).map(
([lineKey, announcementLine]) => (
<Table.Row key={lineKey}>
<Table.Cell collapsing color="label">
{lineKey}:
</Table.Cell>
<Table.Cell>
<Input
key={entry.entryRef + lineKey}
fluid
value={announcementLine}
disabled={!entry.modifiable}
onChange={(e, value) =>
act('Text', {
entryRef: entry.entryRef,
lineKey,
newText: value,
})
}
/>
</Table.Cell>
</Table.Row>
),
)}
</Table>
</Section>
))}
</Section>
)}
</Stack.Item>
</Stack>
</Window.Content>
</Window>
);