From ad167dc54190fbba032cda86f49401afde43d7a5 Mon Sep 17 00:00:00 2001 From: Markolie Date: Mon, 16 Feb 2015 19:03:29 +0100 Subject: [PATCH 01/15] Announcement system overhaul, crew monitor system overhaul, add portable crew monitor --- code/__HELPERS/text.dm | 34 +++- code/__HELPERS/unsorted.dm | 8 +- code/_onclick/hud/screen_objects.dm | 3 +- code/_onclick/observer.dm | 2 +- code/controllers/configuration.dm | 17 ++ .../emergency_shuttle_controller.dm | 22 +-- code/datums/periodic_news.dm | 13 +- code/defines/procs/announce.dm | 121 +++++++++++++++ code/defines/procs/captain_announce.dm | 5 - code/defines/procs/command_alert.dm | 11 -- code/game/gamemodes/blob/blob.dm | 7 +- code/game/gamemodes/epidemic/epidemic.dm | 2 +- code/game/gamemodes/events.dm | 41 ++--- code/game/gamemodes/events/PortalStorm.dm | 2 +- code/game/gamemodes/events/VirusEpidemic.dm | 7 +- code/game/gamemodes/events/clang.dm | 2 +- code/game/gamemodes/events/miniblob.dm | 5 +- code/game/gamemodes/events/power_failure.dm | 12 +- code/game/gamemodes/events/wormholes.dm | 2 +- code/game/gamemodes/game_mode.dm | 5 +- .../game/gamemodes/malfunction/malfunction.dm | 5 +- .../mutiny/emergency_authentication_device.dm | 2 +- code/game/gamemodes/mutiny/mutiny.dm | 4 +- code/game/gamemodes/nations/nations.dm | 2 +- code/game/gamemodes/xenos/xenos.dm | 2 +- code/game/jobs/job/supervisor.dm | 3 +- code/game/jobs/job_controller.dm | 1 + .../game/machinery/computer/communications.dm | 32 ++-- code/game/machinery/computer/crew.dm | 108 +------------ code/game/machinery/newscaster.dm | 29 ++-- code/game/machinery/requests_console.dm | 25 +-- code/game/machinery/slotmachine.dm | 3 +- code/game/machinery/vending.dm | 2 +- code/game/objects/items/devices/PDA/PDA.dm | 9 +- .../objects/items/devices/sensor_device.dm | 18 +++ .../objects/items/weapons/storage/belt.dm | 3 +- code/game/objects/objs.dm | 12 +- .../crates_lockers/closets/secure/medical.dm | 2 + code/game/response_team.dm | 4 +- code/modules/admin/topic.dm | 10 +- code/modules/admin/verbs/randomverbs.dm | 8 +- .../awaymissions/bluespaceartillery.dm | 4 +- .../computer3/computers/communications.dm | 18 ++- code/modules/economy/Economy.dm | 8 + code/modules/events/alien_infestation.dm | 3 +- code/modules/events/blob.dm | 7 +- code/modules/events/borers.dm | 3 +- code/modules/events/brand_intelligence.dm | 2 +- code/modules/events/cargobonus.dm | 2 +- code/modules/events/carp_migration.dm | 2 +- code/modules/events/comms_blackout.dm | 2 +- .../modules/events/communications_blackout.dm | 2 +- code/modules/events/disease_outbreak.dm | 3 +- code/modules/events/electrical_storm.dm | 2 +- code/modules/events/event_container.dm | 22 +-- code/modules/events/event_dynamic.dm | 7 +- code/modules/events/grid_check.dm | 4 +- code/modules/events/infestation.dm | 2 +- code/modules/events/ion_storm.dm | 4 +- code/modules/events/mass_hallucination.dm | 2 +- code/modules/events/meteors.dm | 11 +- code/modules/events/prison_break.dm | 4 +- code/modules/events/radiation_storm.dm | 7 +- code/modules/events/rogue_drones.dm | 6 +- code/modules/events/sayuevents/meaty_ores.dm | 5 +- code/modules/events/sayuevents/wormholes.dm | 5 +- code/modules/events/spider_infestation.dm | 4 +- code/modules/events/tear.dm | 2 +- code/modules/events/tgevents/anomaly.dm | 2 +- .../events/tgevents/anomaly_bluespace.dm | 4 +- code/modules/events/tgevents/anomaly_flux.dm | 2 +- code/modules/events/tgevents/anomaly_grav.dm | 2 +- code/modules/events/tgevents/anomaly_pyro.dm | 2 +- .../modules/events/tgevents/anomaly_vortex.dm | 2 +- .../events/tgevents/brand_intelligence.dm | 2 +- code/modules/events/tgevents/immovable_rod.dm | 2 +- .../events/tgevents/mass_hallucination.dm | 2 +- .../events/tgevents/spider_infestation.dm | 33 ---- code/modules/events/tgevents/vent_clog.dm | 2 +- code/modules/events/viral_infection.dm | 3 +- code/modules/events/viral_outbreak.dm | 3 +- code/modules/events/wallrot.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 16 +- code/modules/mob/living/silicon/ai/ai.dm | 143 +++++++++++++---- .../mob/living/silicon/ai/freelook/eye.dm | 2 +- code/modules/mob/living/silicon/ai/nano.dm | 10 ++ code/modules/mob/living/silicon/ai/say.dm | 137 +++++++---------- code/modules/mob/mob_helpers.dm | 6 + code/modules/nano/modules/crew_monitor.dm | 88 +++++++++++ code/modules/nano/nanomanager.dm | 11 +- code/modules/nano/nanoprocs.dm | 11 ++ code/modules/nano/nanoui.dm | 145 ++++++++++++++---- .../security levels/security levels.dm | 26 ++-- code/modules/shuttles/shuttle_emergency.dm | 4 +- code/modules/shuttles/shuttles_multi.dm | 4 +- code/setup.dm | 8 +- config/example/config.txt | 12 ++ icons/obj/device.dmi | Bin 27223 -> 27805 bytes nano/debug.html | 2 +- paradise.dme | 9 +- sound/misc/notice1.ogg | Bin 0 -> 53513 bytes sound/misc/notice2.ogg | Bin 0 -> 6218 bytes 102 files changed, 882 insertions(+), 563 deletions(-) create mode 100644 code/defines/procs/announce.dm delete mode 100644 code/defines/procs/captain_announce.dm delete mode 100644 code/defines/procs/command_alert.dm create mode 100644 code/game/objects/items/devices/sensor_device.dm delete mode 100644 code/modules/events/tgevents/spider_infestation.dm create mode 100644 code/modules/mob/living/silicon/ai/nano.dm create mode 100644 code/modules/nano/modules/crew_monitor.dm create mode 100644 code/modules/nano/nanoprocs.dm create mode 100644 sound/misc/notice1.ogg create mode 100644 sound/misc/notice2.ogg diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 1553550e362..cb2fad75ddb 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -82,7 +82,7 @@ // Used to get a sanitized input. /proc/stripped_input(var/mob/user, var/message = "", var/title = "", var/default = "", var/max_length=MAX_MESSAGE_LEN) var/name = input(user, message, title, default) - return strip_html_simple(name, max_length) + return strip_html_properly(name, max_length) //Filters out undesirable characters from names /proc/reject_bad_name(var/t_in, var/allow_numbers=0, var/max_length=MAX_NAME_LEN) @@ -311,4 +311,34 @@ proc/checkhtml(var/t) var/new_text = "" for(var/i = length(text); i > 0; i--) new_text += copytext(text, i, i+1) - return new_text + return new_text + +//This proc strips html properly, but it's not lazy like the other procs. +//This means that it doesn't just remove < and > and call it a day. +//Also limit the size of the input, if specified. +/proc/strip_html_properly(var/input, var/max_length = MAX_MESSAGE_LEN) + if(!input) + return + var/opentag = 1 //These store the position of < and > respectively. + var/closetag = 1 + while(1) + opentag = findtext(input, "<") + closetag = findtext(input, ">") + if(closetag && opentag) + if(closetag < opentag) + input = copytext(input, (closetag + 1)) + else + input = copytext(input, 1, opentag) + copytext(input, (closetag + 1)) + else if(closetag || opentag) + if(opentag) + input = copytext(input, 1, opentag) + else + input = copytext(input, (closetag + 1)) + else + break + if(max_length) + input = copytext(input,1,max_length) + return sanitize(input) + +/proc/trim_strip_html_properly(var/input, var/max_length = MAX_MESSAGE_LEN) + return trim(strip_html_properly(input, max_length)) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index ac841e220df..fec0900cf1b 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -411,13 +411,7 @@ Turf and target are seperate in case you want to teleport some distance from a t //world << "[newname] is the AI!" //world << sound('sound/AI/newAI.ogg') // Set eyeobj name - if(A.eyeobj) - A.eyeobj.name = "[newname] (AI Eye)" - - // Set ai pda name - if(A.aiPDA) - A.aiPDA.owner = newname - A.aiPDA.name = newname + " (" + A.aiPDA.ownjob + ")" + A.SetName(newname) fully_replace_character_name(oldname,newname) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 52b16ad6dcf..1e07b13142a 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -503,8 +503,7 @@ if("Crew Monitoring") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - var/obj/machinery/computer/crew/C = locate(/obj/machinery/computer/crew) - C.attack_ai(AI) + AI.nano_crew_monitor() if("Show Crew Manifest") if(isAI(usr)) diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 1fd31a5bd18..d8b5617d2a1 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -66,7 +66,7 @@ /obj/machinery/teleport/hub/attack_ghost(mob/user as mob) var/atom/l = loc var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z)) - if(com.locked) + if(com && com.locked) user.loc = get_turf(com.locked) /obj/effect/portal/attack_ghost(mob/user as mob) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 5806da2e51a..160137a2e5b 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -135,6 +135,11 @@ var/default_laws = 0 //Controls what laws the AI spawns with. + var/list/station_levels = list(1) // Defines which Z-levels the station exists on. + var/list/admin_levels= list(2) // Defines which Z-levels which are for admin functionality, for example including such areas as Central Command and the Syndicate Shuttle + var/list/contact_levels = list(1, 5) // Defines which Z-levels which, for example, a Code Red announcement may affect + var/list/player_levels = list(1, 3, 4, 5, 6) // Defines all Z-levels a character can typically reach + var/const/minutes_to_ticks = 60 * 10 // Event settings var/expected_round_length = 60 * 2 * minutes_to_ticks // 2 hours @@ -458,6 +463,18 @@ if("max_maint_drones") config.max_maint_drones = text2num(value) + if("station_levels") + config.station_levels = text2numlist(value, ";") + + if("admin_levels") + config.admin_levels = text2numlist(value, ";") + + if("contact_levels") + config.contact_levels = text2numlist(value, ";") + + if("player_levels") + config.player_levels = text2numlist(value, ";") + if("expected_round_length") config.expected_round_length = MinutesToTicks(text2num(value)) diff --git a/code/controllers/emergency_shuttle_controller.dm b/code/controllers/emergency_shuttle_controller.dm index 55b325eba3c..83a9d379434 100644 --- a/code/controllers/emergency_shuttle_controller.dm +++ b/code/controllers/emergency_shuttle_controller.dm @@ -18,7 +18,10 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle var/deny_shuttle = 0 //allows admins to prevent the shuttle from being called var/departed = 0 //if the shuttle has left the station at least once - + + var/datum/announcement/priority/emergency_shuttle_docked = new(0, new_sound = sound('sound/AI/shuttledock.ogg')) + var/datum/announcement/priority/emergency_shuttle_called = new(0, new_sound = sound('sound/AI/shuttlecalled.ogg')) + var/datum/announcement/priority/emergency_shuttle_recalled = new(0, new_sound = sound('sound/AI/shuttlerecalled.ogg')) /datum/emergency_shuttle_controller/proc/process() if (wait_for_launch) @@ -29,7 +32,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle if (!shuttle.location) //leaving from the station if(is_stranded()) - captain_announce("Hostile environment detected. Departure has been postponed indefinitely pending conflict resolution.") + priority_announcement.Announce("Hostile environment detected. Departure has been postponed indefinitely pending conflict resolution.") wait_for_launch = 0 return //launch the pods! @@ -49,10 +52,9 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle set_launch_countdown(SHUTTLE_LEAVETIME) //get ready to return if (evac) - captain_announce("The Emergency Shuttle has docked with the station. You have approximately [round(estimate_launch_time()/60,1)] minutes to board the Emergency Shuttle.") - world << sound('sound/AI/shuttledock.ogg') + emergency_shuttle_docked.Announce("The Emergency Shuttle has docked with the station. You have approximately [round(estimate_launch_time()/60,1)] minutes to board the Emergency Shuttle.") else - captain_announce("The scheduled Crew Transfer Shuttle has docked with the station. It will depart in approximately [round(emergency_shuttle.estimate_launch_time()/60,1)] minutes.") + priority_announcement.Announce("The scheduled Crew Transfer Shuttle has docked with the station. It will depart in approximately [round(emergency_shuttle.estimate_launch_time()/60,1)] minutes.") //arm the escape pods if (evac) @@ -81,8 +83,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle shuttle.move_time = SHUTTLE_TRANSIT_DURATION evac = 1 - captain_announce("An emergency evacuation shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.") - world << sound('sound/AI/shuttlecalled.ogg') + emergency_shuttle_called.Announce("An emergency evacuation shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.") for(var/area/A in world) if(istype(A, /area/hallway)) A.readyalert() @@ -101,7 +102,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle //reset the shuttle transit time if we need to shuttle.move_time = SHUTTLE_TRANSIT_DURATION - captain_announce("A crew transfer has been scheduled. The shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.") + priority_announcement.Announce("A crew transfer has been scheduled. The shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.") //recalls the shuttle /datum/emergency_shuttle_controller/proc/recall() @@ -111,15 +112,14 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle shuttle.cancel_launch(src) if (evac) - captain_announce("The emergency shuttle has been recalled.") - world << sound('sound/AI/shuttlerecalled.ogg') + emergency_shuttle_recalled.Announce("The emergency shuttle has been recalled.") for(var/area/A in world) if(istype(A, /area/hallway)) A.readyreset() evac = 0 else - captain_announce("The scheduled crew transfer has been cancelled.") + priority_announcement.Announce("The scheduled crew transfer has been cancelled.") /datum/emergency_shuttle_controller/proc/can_call() if (deny_shuttle) diff --git a/code/datums/periodic_news.dm b/code/datums/periodic_news.dm index 976ef536cb4..ffa52bffdc6 100644 --- a/code/datums/periodic_news.dm +++ b/code/datums/periodic_news.dm @@ -8,6 +8,7 @@ author = "Nanotrasen Editor" channel_name = "Tau Ceti Daily" can_be_redacted = 0 + message_type = "Story" revolution_inciting_event @@ -129,12 +130,6 @@ proc/check_for_newscaster_updates(type) proc/announce_newscaster_news(datum/news_announcement/news) - var/datum/feed_message/newMsg = new /datum/feed_message - newMsg.author = news.author - newMsg.is_admin_message = !news.can_be_redacted - - newMsg.body = news.message - var/datum/feed_channel/sendto for(var/datum/feed_channel/FC in news_network.network_channels) if(FC.channel_name == news.channel_name) @@ -148,6 +143,12 @@ proc/announce_newscaster_news(datum/news_announcement/news) sendto.locked = 1 sendto.is_admin_channel = 1 news_network.network_channels += sendto + + var/datum/feed_message/newMsg = new /datum/feed_message + newMsg.author = news.author ? news.author : sendto.author + newMsg.is_admin_message = !news.can_be_redacted + newMsg.body = news.message + newMsg.message_type = news.message_type sendto.messages += newMsg diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm new file mode 100644 index 00000000000..7cb7799a372 --- /dev/null +++ b/code/defines/procs/announce.dm @@ -0,0 +1,121 @@ +/var/datum/announcement/priority/priority_announcement = new(do_log = 0) +/var/datum/announcement/priority/command/command_announcement = new(do_log = 0, do_newscast = 1) + +/datum/announcement + var/title = "Attention" + var/announcer = "" + var/log = 0 + var/sound + var/newscast = 0 + var/channel_name = "Station Announcements" + var/announcement_type = "Announcement" + var/disable_newscasts = 1 // Bay also adds announcements to their newscaster system - set this to 0 to also use that system + +/datum/announcement/New(var/do_log = 0, var/new_sound = null, var/do_newscast = 0) + sound = new_sound + log = do_log + newscast = do_newscast + +/datum/announcement/priority/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0) + ..(do_log, new_sound, do_newscast) + title = "Priority Announcement" + announcement_type = "Priority Announcement" + +/datum/announcement/priority/command/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0) + ..(do_log, new_sound, do_newscast) + title = "[command_name()] Update" + announcement_type = "[command_name()] Update" + +/datum/announcement/priority/security/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0) + ..(do_log, new_sound, do_newscast) + title = "Security Announcement" + announcement_type = "Security Announcement" + +/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast) + if(!message) + return + var/tmp/message_title = new_title ? new_title : title + var/tmp/message_sound = new_sound ? sound(new_sound) : sound + + message = trim_strip_html_properly(message) + message_title = html_encode(message_title) + + Message(message, message_title) + if(do_newscast) + NewsCast(message, message_title) + Sound(message_sound) + Log(message, message_title) + +datum/announcement/proc/Message(message as text, message_title as text) + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player) && !isdeaf(M)) + M << "

[title]

" + M << "[message]" + if (announcer) + M << " -[html_encode(announcer)]" + +datum/announcement/minor/Message(message as text, message_title as text) + world << "[message]" + +datum/announcement/priority/Message(message as text, message_title as text) + world << "

[message_title]

" + world << "[message]" + if(announcer) + world << " -[html_encode(announcer)]" + world << "
" + +datum/announcement/priority/command/Message(message as text, message_title as text) + var/command + command += "

[command_name()] Update

" + if (message_title) + command += "

[message_title]

" + + command += "
[message]
" + command += "
" + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player) && !isdeaf(M)) + M << command + +datum/announcement/priority/security/Message(message as text, message_title as text) + world << "[message_title]" + world << "[message]" + +datum/announcement/proc/NewsCast(message as text, message_title as text) + if(disable_newscasts) + return + if(!newscast) + return + + var/datum/news_announcement/news = new + news.channel_name = channel_name + news.author = announcer + news.message = message + news.message_type = announcement_type + news.can_be_redacted = 0 + announce_newscaster_news(news) + +datum/announcement/proc/PlaySound(var/message_sound) + if(!message_sound) + return + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player) && !isdeaf(M)) + M << message_sound + +datum/announcement/proc/Sound(var/message_sound) + PlaySound(message_sound) + +datum/announcement/priority/Sound(var/message_sound) + if(sound) + world << sound + +datum/announcement/priority/command/Sound(var/message_sound) + PlaySound(message_sound) + +datum/announcement/proc/Log(message as text, message_title as text) + if(log) + log_say("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]") + message_admins("[key_name_admin(usr)] has made \a [announcement_type].", 1) + +/proc/GetNameAndAssignmentFromId(var/obj/item/weapon/card/id/I) + // Format currently matches that of newscaster feeds: Registered Name (Assigned Rank) + return I.assignment ? "[I.registered_name] ([I.assignment])" : I.registered_name diff --git a/code/defines/procs/captain_announce.dm b/code/defines/procs/captain_announce.dm deleted file mode 100644 index 9b91705ea56..00000000000 --- a/code/defines/procs/captain_announce.dm +++ /dev/null @@ -1,5 +0,0 @@ -/proc/captain_announce(var/text) - world << "

Priority Announcement

" - world << "[html_encode(text)]" - world << "
" - diff --git a/code/defines/procs/command_alert.dm b/code/defines/procs/command_alert.dm deleted file mode 100644 index 6545307fa1a..00000000000 --- a/code/defines/procs/command_alert.dm +++ /dev/null @@ -1,11 +0,0 @@ -/proc/command_alert(var/text, var/title = "") - var/command - command += "

[command_name()] Update

" - if (title && length(title) > 0) - command += "

[html_encode(title)]

" - - command += "
[html_encode(text)]
" - command += "
" - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << command diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index ccbff9b326d..32fb4496670 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -175,14 +175,11 @@ var/list/blob_nodes = list() return if (1) - command_alert("Nanotrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined.", "Biohazard Alert") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/blob_confirmed.ogg') + command_announcement.Announce("Nanotrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined.", "Biohazard Alert", new_sound = 'sound/AI/blob_confirmed.ogg') return if (2) - command_alert("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [get_nuke_code()] ", "Biohazard Alert") + command_announcement.Announce("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [get_nuke_code()] ", "Biohazard Alert", new_sound = 'sound/AI/blob_confirmed.ogg') set_security_level("gamma") var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world if(V && V.z == 1) diff --git a/code/game/gamemodes/epidemic/epidemic.dm b/code/game/gamemodes/epidemic/epidemic.dm index b541e9b1b03..e64100e2a12 100644 --- a/code/game/gamemodes/epidemic/epidemic.dm +++ b/code/game/gamemodes/epidemic/epidemic.dm @@ -149,7 +149,7 @@ announce_to_kill_crew() stage = 2 else if(stage == 2 && cruiser_seconds() <= 60 * 5) - command_alert("Inbound cruiser detected on collision course. Scans indicate the ship to be armed and ready to fire. Estimated time of arrival: 5 minutes.", "[station_name()] Early Warning System") + command_announcement.Announce("Inbound cruiser detected on collision course. Scans indicate the ship to be armed and ready to fire. Estimated time of arrival: 5 minutes.", "[station_name()] Early Warning System") stage = 3 else if(stage == 3 && cruiser_seconds() <= 0) crew_lose() diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index d8002530031..a2563b01a73 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -30,10 +30,7 @@ eventNumbersToPickFrom += 3 switch(pick(eventNumbersToPickFrom)) if(1) - command_alert("Meteors have been detected on collision course with the station.", "Meteor Alert") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/meteors.ogg') + command_announcement.Announce("Meteors have been detected on collision course with the station.", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg') spawn(100) meteor_wave() spawn_meteors() @@ -42,18 +39,14 @@ spawn_meteors() if(2) - command_alert("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/granomalies.ogg') + command_announcement.Announce("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert", new_sound = 'sound/AI/granomalies.ogg') var/turf/T = pick(blobstart) var/obj/effect/bhole/bh = new /obj/effect/bhole( T.loc, 30 ) spawn(rand(50, 300)) del(bh) /* if(3) //Leaving the code in so someone can try and delag it, but this event can no longer occur randomly, per SoS's request. --NEO - command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert") - world << sound('sound/AI/spanomalies.ogg') + command_announcement.Announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", new_sound = 'sound/AI/spanomalies.ogg') var/list/turfs = new var/turf/picked for(var/turf/simulated/floor/T in world) @@ -107,8 +100,7 @@ /* /proc/viral_outbreak(var/virus = null) -// command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") -// world << sound('sound/AI/outbreak7.ogg') +// command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg') var/virus_type if(!virus) virus_type = pick(/datum/disease/dnaspread,/datum/disease/advance/flu,/datum/disease/advance/cold,/datum/disease/brainrot,/datum/disease/magnitis,/datum/disease/pierrot_throat) @@ -167,14 +159,11 @@ H.viruses += D break spawn(rand(1500, 3000)) //Delayed announcements to keep the crew on their toes. - command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - for(var/mob/M in player_list) - M << sound('sound/AI/outbreak7.ogg') + command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg') */ /proc/alien_infestation(var/spawncount = 1) // -- TLE - //command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") - //world << sound('sound/AI/aliens.ogg') + //command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') var/list/vents = list() for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines) if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network) @@ -197,7 +186,7 @@ spawncount-- spawn(rand(5000, 6000)) //Delayed announcements to keep the crew on their toes. - command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") + command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') for(var/mob/M in player_list) M << sound('sound/AI/aliens.ogg') @@ -217,6 +206,8 @@ if(T.z != 1) continue if(istype(H,/mob/living/carbon/human)) + if(H.species.flags & IS_SYNTHETIC) + return H.apply_effect((rand(15,75)),IRRADIATE,0) if (prob(5)) H.apply_effect((rand(90,150)),IRRADIATE,0) @@ -235,9 +226,7 @@ continue M.apply_effect((rand(15,75)),IRRADIATE,0) sleep(100) - command_alert("High levels of radiation detected near the station. Please report to the Med-bay if you feel strange.", "Anomaly Alert") - for(var/mob/M in player_list) - M << sound('sound/AI/radiation.ogg') + command_announcement.Announce("High levels of radiation detected near the station. Please report to the Med-bay if you feel strange.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg') @@ -276,9 +265,9 @@ temp_timer.releasetime = 1 sleep(150) - command_alert("Gr3y.T1d3 virus detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") + command_announcement.Announce("Gr3y.T1d3 virus detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") else - world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area." + world.log << "ERROR: Could not initate grey-tide virus. Unable find prison or brig area." /proc/carp_migration() // -- Darem for(var/obj/effect/landmark/C in landmarks_list) @@ -286,13 +275,11 @@ new /mob/living/simple_animal/hostile/carp(C.loc) //sleep(100) spawn(rand(300, 600)) //Delayed announcements to keep the crew on their toes. - command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") - for(var/mob/M in player_list) - M << sound('sound/AI/commandreport.ogg') + command_announcement.Announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert", new_sound = 'sound/AI/commandreport.ogg') /proc/lightsout(isEvent = 0, lightsoutAmount = 1,lightsoutRange = 25) //leave lightsoutAmount as 0 to break ALL lights if(isEvent) - command_alert("An Electrical storm has been detected in your area, please repair potential electronic overloads.","Electrical Storm Alert") + command_announcement.Announce("An Electrical storm has been detected in your area, please repair potential electronic overloads.","Electrical Storm Alert") if(lightsoutAmount) var/list/epicentreList = list() diff --git a/code/game/gamemodes/events/PortalStorm.dm b/code/game/gamemodes/events/PortalStorm.dm index 890755d6b8e..88e29f29032 100644 --- a/code/game/gamemodes/events/PortalStorm.dm +++ b/code/game/gamemodes/events/PortalStorm.dm @@ -1,7 +1,7 @@ /datum/event/portalstorm Announce() - command_alert("Subspace disruption detected around the vessel", "Anomaly Alert") + command_announcement.Announce("Subspace disruption detected around the vessel", "Anomaly Alert") LongTerm() var/list/turfs = list( ) diff --git a/code/game/gamemodes/events/VirusEpidemic.dm b/code/game/gamemodes/events/VirusEpidemic.dm index 54b9760a2f7..f6e005cef10 100644 --- a/code/game/gamemodes/events/VirusEpidemic.dm +++ b/code/game/gamemodes/events/VirusEpidemic.dm @@ -13,11 +13,11 @@ if(prob(100)) // no lethal diseases outside virus mode! infect_mob_random_lesser(H) if(prob(20))//don't want people to know that the virus alert = greater virus - command_alert("Probable outbreak of level [rand(1,6)] viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Virus Alert") + command_announcement.Announce("Probable outbreak of level [rand(1,6)] viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Virus Alert") else infect_mob_random_greater(H) if(prob(80)) - command_alert("Probable outbreak of level [rand(2,9)] viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Virus Alert") + command_announcement.Announce("Probable outbreak of level [rand(2,9)] viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Virus Alert") break //overall virus alert happens 26% of the time, might need to be higher else @@ -73,8 +73,7 @@ H.viruses += D break spawn(rand(3000, 6000)) //Delayed announcements to keep the crew on their toes. - command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - world << sound('sound/AI/outbreak7.ogg') + command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg') Tick() ActiveFor = Lifetime //killme diff --git a/code/game/gamemodes/events/clang.dm b/code/game/gamemodes/events/clang.dm index c74da4010e9..3eb1eece271 100644 --- a/code/game/gamemodes/events/clang.dm +++ b/code/game/gamemodes/events/clang.dm @@ -86,4 +86,4 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 for(var/obj/effect/immovablerod/imm in world) return sleep(50) - command_alert("What the fuck was that?!", "General Alert") \ No newline at end of file + command_announcement.Announce("What the fuck was that?!", "General Alert") \ No newline at end of file diff --git a/code/game/gamemodes/events/miniblob.dm b/code/game/gamemodes/events/miniblob.dm index 663dff0f2ed..127e877e96b 100644 --- a/code/game/gamemodes/events/miniblob.dm +++ b/code/game/gamemodes/events/miniblob.dm @@ -12,10 +12,7 @@ spawn(3000) blobevent = 0 spawn(rand(1000, 2000)) //Delayed announcements to keep the crew on their toes. - command_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/outbreak5.ogg') + command_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak5.ogg') /proc/dotheblobbaby() if (blobevent) diff --git a/code/game/gamemodes/events/power_failure.dm b/code/game/gamemodes/events/power_failure.dm index 141efd60412..202d30b737b 100644 --- a/code/game/gamemodes/events/power_failure.dm +++ b/code/game/gamemodes/events/power_failure.dm @@ -1,9 +1,7 @@ /proc/power_failure(var/announce = 1) if(announce) - command_alert("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure") - for(var/mob/M in player_list) - M << sound('sound/AI/poweroff.ogg') + command_announcement.Announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", new_sound = 'sound/AI/poweroff.ogg') var/list/skipped_areas = list(/area/turret_protected/ai) var/list/skipped_areas_apc = list(/area/engine/engineering) @@ -31,9 +29,7 @@ var/list/skipped_areas_apc = list(/area/engine/engineering) if(announce) - command_alert("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal") - for(var/mob/M in player_list) - M << sound('sound/AI/poweron.ogg') + command_announcement.Announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg') for(var/obj/machinery/power/apc/C in machines) var/area/current_area = get_area(C) if(current_area.type in skipped_areas_apc || C.z != 1) @@ -53,9 +49,7 @@ /proc/power_restore_quick(var/announce = 1) if(announce) - command_alert("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal") - for(var/mob/M in player_list) - M << sound('sound/AI/poweron.ogg') + command_announcement.Announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg') for(var/obj/machinery/power/smes/S in machines) if(S.z != 1) continue diff --git a/code/game/gamemodes/events/wormholes.dm b/code/game/gamemodes/events/wormholes.dm index 1ef19e24ac7..41604714dde 100644 --- a/code/game/gamemodes/events/wormholes.dm +++ b/code/game/gamemodes/events/wormholes.dm @@ -7,7 +7,7 @@ if(pick_turfs.len) //All ready. Announce that bad juju is afoot. - command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert") + command_announcement.Announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert") for(var/mob/M in player_list) if(!istype(M,/mob/new_player)) M << sound('sound/AI/spanomalies.ogg') diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index d23b4ec1958..6ad6d09c1c8 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -323,10 +323,7 @@ Implants; comm.messagetext.Add(intercepttext) /* world << sound('sound/AI/commandreport.ogg') */ - command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercepted. Security Level Elevated.") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/intercept.ogg') + command_announcement.Announce("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercepted. Security Level Elevated.", new_sound = 'sound/AI/intercept.ogg') if(security_level < SEC_LEVEL_BLUE) set_security_level(SEC_LEVEL_BLUE) diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 856a7421852..8091f775041 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -172,7 +172,7 @@ if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [ticker.mode:apcs] APCs.", "Takeover:", "Yes", "No") != "Yes") return - command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") + command_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg') set_security_level("delta") for(var/obj/item/weapon/pinpointer/point in world) @@ -184,9 +184,6 @@ ticker.mode:malf_mode_declared = 1 for(var/datum/mind/AI_mind in ticker.mode:malf_ai) AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/aimalf.ogg') /datum/game_mode/malfunction/proc/ai_win() diff --git a/code/game/gamemodes/mutiny/emergency_authentication_device.dm b/code/game/gamemodes/mutiny/emergency_authentication_device.dm index 8ddcaf47516..ba7f66345ee 100644 --- a/code/game/gamemodes/mutiny/emergency_authentication_device.dm +++ b/code/game/gamemodes/mutiny/emergency_authentication_device.dm @@ -42,7 +42,7 @@ if(emergency_shuttle.call_evac()) spawn(20 SECONDS) var/text = "[station_name()], we have confirmed your completion of Directive X. An evacuation shuttle is en route to receive your crew for debriefing." - command_alert(text, "Emergency Transmission") + command_announcement.Announce(text, "Emergency Transmission") /obj/machinery/emergency_authentication_device/attack_hand(mob/user) if(activated) diff --git a/code/game/gamemodes/mutiny/mutiny.dm b/code/game/gamemodes/mutiny/mutiny.dm index 50f72b727e2..2068f4ac09d 100644 --- a/code/game/gamemodes/mutiny/mutiny.dm +++ b/code/game/gamemodes/mutiny/mutiny.dm @@ -27,7 +27,7 @@ datum/game_mode/mutiny proc/reveal_directives() spawn(rand(1 MINUTES, 3 MINUTES)) - command_alert("Incoming emergency directive: Captain's office fax machine, [station_name()].","Emergency Transmission") + command_announcement.Announce("Incoming emergency directive: Captain's office fax machine, [station_name()].","Emergency Transmission") spawn(rand(3 MINUTES, 5 MINUTES)) send_pda_message() spawn(rand(3 MINUTES, 5 MINUTES)) @@ -67,7 +67,7 @@ datum/game_mode/mutiny "classified security operations", "science-defying raw elemental chaos" ) - command_alert("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time.","Emergency Transmission") + command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time.","Emergency Transmission") // Returns an array in case we want to expand on this later. proc/get_head_loyalist_candidates() diff --git a/code/game/gamemodes/nations/nations.dm b/code/game/gamemodes/nations/nations.dm index ec180e07279..afaab542d73 100644 --- a/code/game/gamemodes/nations/nations.dm +++ b/code/game/gamemodes/nations/nations.dm @@ -28,7 +28,7 @@ datum/game_mode/nations return ..() /datum/game_mode/nations/send_intercept() - command_alert("Due to recent and COMPLETELY UNFOUNDED allegations of massive fraud and insider trading \ + command_announcement.Announce("Due to recent and COMPLETELY UNFOUNDED allegations of massive fraud and insider trading \ affecting trillions of investors, the Nanotrasen Corporation has decided to liquidate all \ assets of the Centcom Division in order to pay the massive legal fees that will be incurred \ during the following centuries long court process. Therefore, all current employment contracts \ diff --git a/code/game/gamemodes/xenos/xenos.dm b/code/game/gamemodes/xenos/xenos.dm index 0d4c7f06b1b..261de0b2255 100644 --- a/code/game/gamemodes/xenos/xenos.dm +++ b/code/game/gamemodes/xenos/xenos.dm @@ -200,7 +200,7 @@ else if(playeralienratio >= gammaratio && !gammacalled) gammacalled = 1 - command_alert("The aliens have nearly succeeded in capturing the station and exterminating the crew. Activate the nuclear failsafe to stop the alien threat once and for all. The Nuclear Authentication Code is [get_nuke_code()] ", "Alien Lifeform Alert") + command_announcement.Announce("The aliens have nearly succeeded in capturing the station and exterminating the crew. Activate the nuclear failsafe to stop the alien threat once and for all. The Nuclear Authentication Code is [get_nuke_code()] ", "Alien Lifeform Alert") set_security_level("gamma") var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world if(V && V.z == 1) diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm index 87537e4a571..dc5eea006e1 100644 --- a/code/game/jobs/job/supervisor.dm +++ b/code/game/jobs/job/supervisor.dm @@ -1,3 +1,4 @@ +var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) /datum/job/captain title = "Captain" flag = CAPTAIN @@ -35,7 +36,7 @@ var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) L.imp_in = H L.implanted = 1 - world << "Captain [H.real_name] on deck!" + captain_announcement.Announce("All hands, captain [H.real_name] on deck!") var/datum/organ/external/affected = H.organs_by_name["head"] affected.implants += L L.part = affected diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 1e7dfe99d5f..f678b3afc1b 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -526,6 +526,7 @@ var/global/datum/controller/occupations/job_master var/obj/item/device/pda/pda = locate(/obj/item/device/pda,H) pda.owner = H.real_name pda.ownjob = C.assignment + pda.ownrank = C.rank pda.name = "PDA-[H.real_name] ([pda.ownjob])" return 1 diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 23a085675e5..c8d44e03dbd 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -55,8 +55,14 @@ var/shuttle_call/shuttle_calls[0] var/stat_msg1 var/stat_msg2 var/display_type="blank" + + var/datum/announcement/priority/crew_announcement = new l_color = "#0000FF" + +/obj/machinery/computer/communications/New() + ..() + crew_announcement.newscast = 1 /obj/machinery/computer/communications/Topic(href, href_list) if(..(href, href_list)) @@ -83,10 +89,12 @@ var/shuttle_call/shuttle_calls[0] if (I && istype(I)) if(src.check_access(I)) authenticated = 1 - if(20 in I.access) + if(access_captain in I.access) authenticated = 2 + crew_announcement.announcer = GetNameAndAssignmentFromId(I) if("logout") authenticated = 0 + crew_announcement.announcer = "" setMenuState(usr,COMM_SCREEN_MAIN) // ALART LAVUL @@ -127,14 +135,14 @@ var/shuttle_call/shuttle_calls[0] usr << "You need to swipe your ID." if("announce") - if(src.authenticated==2 && !issilicon(usr)) - if(message_cooldown) return - var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?") + if(src.authenticated==2) + if(message_cooldown) + usr << "Please allow at least one minute to pass between announcements" + return + var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") if(!input || !(usr in view(1,src))) return - captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain - log_say("[key_name(usr)] has made a captain announcement: [input]") - message_admins("[key_name_admin(usr)] has made a captain announcement.", 1) + crew_announcement.Announce(input) message_cooldown = 1 spawn(600)//One minute cooldown message_cooldown = 0 @@ -204,7 +212,7 @@ var/shuttle_call/shuttle_calls[0] if(centcomm_message_cooldown) usr << "Arrays recycling. Please stand by." return - var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") + var/input = input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "") if(!input || !(usr in view(1,src))) return Centcomm_announce(input, usr) @@ -398,7 +406,7 @@ var/shuttle_call/shuttle_calls[0] return if(emergency_shuttle.going_to_centcom()) - user << "The shuttle may not be called while returning to CentCom." + user << "The shuttle may not be called while returning to Central Command." return if(emergency_shuttle.online()) @@ -408,11 +416,11 @@ var/shuttle_call/shuttle_calls[0] // if force is 0, some things may stop the shuttle call if(!force) if(emergency_shuttle.deny_shuttle) - user << "Centcom does not currently have a shuttle available in your sector. Please try again later." + user << "Central Command does not currently have a shuttle available in your sector. Please try again later." return if(sent_strike_team == 1) - user << "Centcom will not allow the shuttle to be called. Consider all contracts terminated." + user << "Central Command will not allow the shuttle to be called. Consider all contracts terminated." return if(world.time < 54000) // 30 minute grace period to let the game get going @@ -426,8 +434,6 @@ var/shuttle_call/shuttle_calls[0] emergency_shuttle.call_transfer() log_game("[key_name(user)] has called the shuttle.") message_admins("[key_name_admin(user)] has called the shuttle - [formatJumpTo(user)].", 1) - captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [round(emergency_shuttle.estimate_arrival_time()/60)] minutes.") - return diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index c459b3d1e1a..084eb974688 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -1,18 +1,15 @@ /obj/machinery/computer/crew - name = "Crew Monitoring Computer" + name = "crew monitoring computer" desc = "Used to monitor active health sensors built into most of the crew's uniforms." icon_state = "crew" use_power = 1 idle_power_usage = 250 active_power_usage = 500 circuit = "/obj/item/weapon/circuitboard/crew" - var/list/tracked = list( ) - - l_color = "#0000FF" - + var/obj/nano_module/crew_monitor/crew_monitor /obj/machinery/computer/crew/New() - tracked = list() + crew_monitor = new(src) ..() @@ -27,6 +24,8 @@ return ui_interact(user) +/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + crew_monitor.ui_interact(user, ui_key, ui, force_open) /obj/machinery/computer/crew/update_icon() @@ -40,100 +39,5 @@ icon_state = initial(icon_state) stat &= ~NOPOWER - -/obj/machinery/computer/crew/Topic(href, href_list) - if(..()) - return 1 - if (src.z > 6) - usr << "\red Unable to establish a connection: \black You're too far away from the station!" - return 0 - if( href_list["close"] ) - var/mob/user = usr - var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") - usr.unset_machine() - ui.close() - return 0 - if(href_list["update"]) - src.updateDialog() - return 1 - /obj/machinery/computer/crew/interact(mob/user) - ui_interact(user) - -/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - if(stat & (BROKEN|NOPOWER)) - return - user.set_machine(src) - src.scan() - - var/data[0] - var/list/crewmembers = list() - - for(var/obj/item/clothing/under/C in src.tracked) - - - var/turf/pos = get_turf(C) - - if((C) && (C.has_sensor) && (pos) && (pos.z == src.z) && C.sensor_mode) - if(istype(C.loc, /mob/living/carbon/human)) - - var/mob/living/carbon/human/H = C.loc - - var/list/crewmemberData = list() - - crewmemberData["sensor_type"] = C.sensor_mode - crewmemberData["dead"] = H.stat > 1 - crewmemberData["oxy"] = round(H.getOxyLoss(), 1) - crewmemberData["tox"] = round(H.getToxLoss(), 1) - crewmemberData["fire"] = round(H.getFireLoss(), 1) - crewmemberData["brute"] = round(H.getBruteLoss(), 1) - - crewmemberData["name"] = "Unknown" - crewmemberData["rank"] = "Unknown" - if(H.wear_id && istype(H.wear_id, /obj/item/weapon/card/id) ) - var/obj/item/weapon/card/id/I = H.wear_id - crewmemberData["name"] = I.name - crewmemberData["rank"] = I.rank - else if(H.wear_id && istype(H.wear_id, /obj/item/device/pda) ) - var/obj/item/device/pda/P = H.wear_id - crewmemberData["name"] = (P.id ? P.id.name : "Unknown") - crewmemberData["rank"] = (P.id ? P.id.rank : "Unknown") - var/area/A = get_area(H) - crewmemberData["area"] = sanitize(A.name) - crewmemberData["x"] = pos.x - crewmemberData["y"] = pos.y - - // Works around list += list2 merging lists; it's not pretty but it works - crewmembers += "temporary item" - crewmembers[crewmembers.len] = crewmemberData - - crewmembers = sortByKey(crewmembers, "name") - - data["crewmembers"] = crewmembers - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800) - - // adding a template with the key "mapContent" enables the map ui functionality - ui.add_template("mapContent", "crew_monitor_map_content.tmpl") - // adding a template with the key "mapHeader" replaces the map header content - ui.add_template("mapHeader", "crew_monitor_map_header.tmpl") - - // we want to show the map by default - ui.set_show_map(1) - - ui.set_initial_data(data) - ui.open() - - // should make the UI auto-update; doesn't seem to? - ui.set_auto_update(1) - - -/obj/machinery/computer/crew/proc/scan() - for(var/mob/living/carbon/human/H in mob_list) - if(istype(H.w_uniform, /obj/item/clothing/under)) - var/obj/item/clothing/under/C = H.w_uniform - if (C.has_sensor) - tracked |= C - return 1 + crew_monitor.ui_interact(user) \ No newline at end of file diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 1c7f8ee64a0..dd0e408fd60 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -5,6 +5,7 @@ /datum/feed_message var/author ="" var/body ="" + var/message_type ="Story" //var/parent_channel var/backup_body ="" var/backup_author ="" @@ -39,6 +40,12 @@ src.backup_author = "" src.censored = 0 src.is_admin_channel = 0 + +/datum/feed_channel/proc/announce_news() + return "Breaking news from [channel_name]!" + +/datum/feed_channel/station/announce_news() + return "New Station Announcement Available" /datum/feed_network var/list/datum/feed_channel/network_channels = list() @@ -213,7 +220,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co switch(screen) if(0) dat += {"Welcome to Newscasting Unit #[src.unit_no].
Interface & News networks Operational. -
Property of Nanotransen Inc"} +
Property of Nanotrasen"} if(news_network.wanted_issue) dat+= "
Read Wanted Issue" dat+= {"

Create Feed Channel @@ -248,7 +255,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co dat+="No feed messages found in channel...

" else for(var/datum/feed_message/MESSAGE in CHANNEL.messages) - dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
"*/ + dat+="-[MESSAGE.body]
\[[MESSAGE.message_type] by [MESSAGE.author]\]
"*/ dat+="

Refresh" dat+="
Back" @@ -334,7 +341,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(MESSAGE.img) usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png") dat+="

" - dat+="\[Story by [MESSAGE.author]\]
" + dat+="\[[MESSAGE.message_type] by [MESSAGE.author]\]
" dat+="

Refresh" dat+="
Back" if(10) @@ -369,7 +376,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co dat+="No feed messages found in channel...
" else for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) - dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
" + dat+="-[MESSAGE.body]
\[[MESSAGE.message_type] by [MESSAGE.author]\]
" dat+="[(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")]
" dat+="
Back" if(13) @@ -383,7 +390,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co dat+="No feed messages found in channel...
" else for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) - dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
" + dat+="-[MESSAGE.body]
\[[MESSAGE.message_type] by [MESSAGE.author]\]
" dat+="
Back" if(14) @@ -516,7 +523,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co src.updateUsrDialog() else if(href_list["set_new_message"]) - src.msg = strip_html(input(usr, "Write your Feed story", "Network Channel Handler", "")) + src.msg = strip_html(input(usr, "Write your feed story", "Network Channel Handler", "")) while (findtext(src.msg," ") == 1) src.msg = copytext(src.msg,2,lentext(src.msg)+1) src.updateUsrDialog() @@ -535,13 +542,15 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(photo) newMsg.img = photo.img feedback_inc("newscaster_stories",1) + var/announcement = "" for(var/datum/feed_channel/FC in news_network.network_channels) if(FC.channel_name == src.channel_name) FC.messages += newMsg //Adding message to the network's appropriate feed_channel + announcement = FC.announce_news() break src.screen=4 for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - NEWSCASTER.newsAlert(src.channel_name) + NEWSCASTER.newsAlert(announcement) src.updateUsrDialog() @@ -986,11 +995,11 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob) ///obj/machinery/newscaster/process() //Was thinking of doing the icon update through process, but multiple iterations per second does not // return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list. -/obj/machinery/newscaster/proc/newsAlert(channel) //This isn't Agouri's work, for it is ugly and vile. +/obj/machinery/newscaster/proc/newsAlert(var/news_call) //This isn't Agouri's work, for it is ugly and vile. var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ - if(channel) + if(news_call) for(var/mob/O in hearers(world.view-1, T)) - O.show_message("[src.name] beeps, \"Breaking news from [channel]!\"",2) + O.show_message("[src.name] beeps, \"[news_call]\"",2) src.alert = 1 src.update_icon() spawn(300) diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index d358e39c67f..16d7b16572e 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -55,6 +55,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() var/dpt = ""; //the department which will be receiving the message var/priority = -1 ; //Priority of the message being sent luminosity = 0 + var/datum/announcement/announcement = new /obj/machinery/requests_console/power_change() ..() @@ -70,6 +71,10 @@ var/list/obj/machinery/requests_console/allConsoles = list() /obj/machinery/requests_console/New() ..() + + announcement.title = "[department] announcement" + announcement.newscast = 1 + name = "[department] Requests Console" allConsoles += src //req_console_departments += department @@ -189,7 +194,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() else //main menu screen = 0 - announceAuth = 0 + reset_announce() if (newmessagepriority == 1) dat += text("There are new messages
") if (newmessagepriority == 2) @@ -240,17 +245,13 @@ var/list/obj/machinery/requests_console/allConsoles = list() if("2") priority = 2 else priority = -1 else - message = "" - announceAuth = 0 + reset_announce() screen = 0 if(href_list["sendAnnouncement"]) if(!announcementConsole) return - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << "[department] announcement: [message]" - announceAuth = 0 - message = "" + announcement.Announce(message) + reset_announce() screen = 0 if( href_list["department"] && message ) @@ -389,8 +390,9 @@ var/list/obj/machinery/requests_console/allConsoles = list() var/obj/item/weapon/card/id/ID = O if (access_RC_announce in ID.GetAccess()) announceAuth = 1 + announcement.announcer = ID.assignment ? "[ID.assignment] [ID.registered_name]" : ID.registered_name else - announceAuth = 0 + reset_announce() user << "\red You are not authorized to send announcements." updateUsrDialog() if (istype(O, /obj/item/weapon/stamp)) @@ -399,3 +401,8 @@ var/list/obj/machinery/requests_console/allConsoles = list() msgStamped = text("Stamped with the [T.name]") updateUsrDialog() return + +/obj/machinery/requests_console/proc/reset_announce() + announceAuth = 0 + message = "" + announcement.announcer = "" diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm index d2d93afba2c..54355179c8e 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -1,3 +1,4 @@ +var/datum/announcement/minor/slotmachine_announcement = new(do_log = 0) /obj/machinery/slot_machine name = "Slot Machine" desc = "Gambling for the antisocial." @@ -55,7 +56,7 @@ if (roll == 1) for(var/mob/O in hearers(src, null)) O.show_message(text("[] says, 'JACKPOT! You win [src.money]!'", src), 1) - command_alert("Congratulations [usr.name] on winning the Jackpot!", "Jackpot Winner") + slotmachine_announcement.Announce("Congratulations [usr.name] on winning the Jackpot!", "Jackpot Winner") usr.mind.initial_account.money += src.money src.money = 0 else if (roll > 1 && roll <= 10) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 61139498d05..5c97db2693f 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -885,7 +885,7 @@ /obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4, /obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/syringe = 12, /obj/item/device/healthanalyzer = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4, /obj/item/weapon/reagent_containers/dropper = 2, - /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 2) + /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 2, /obj/item/device/sensor_device = 2) contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3,/obj/item/weapon/reagent_containers/pill/stox = 4,/obj/item/weapon/reagent_containers/pill/antitox = 6) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 826de6fd4c4..f077fe8d177 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -51,6 +51,7 @@ var/global/list/obj/item/device/pda/PDAs = list() var/obj/item/weapon/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both. var/ownjob = null //related to above + var/ownrank = null // this one is rank, never alt title var/obj/item/device/paicard/pai = null // A slot for a personal AI device @@ -217,9 +218,13 @@ var/global/list/obj/item/device/pda/PDAs = list() detonate = 0 -/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text) +/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text, newrank as null|text) owner = newname ownjob = newjob + if(newrank) + ownrank = newrank + else + ownrank = ownjob name = newname + " (" + ownjob + ")" @@ -575,6 +580,7 @@ var/global/list/obj/item/device/pda/PDAs = list() id_check(U, 1) if("UpdateInfo") ownjob = id.assignment + ownrank = id.rank name = "PDA-[owner] ([ownjob])" if("Eject")//Ejects the cart, only done from hub. if (!isnull(cartridge)) @@ -1069,6 +1075,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(!owner) owner = idcard.registered_name ownjob = idcard.assignment + ownrank = idcard.rank name = "PDA-[owner] ([ownjob])" user << "Card scanned." else diff --git a/code/game/objects/items/devices/sensor_device.dm b/code/game/objects/items/devices/sensor_device.dm new file mode 100644 index 00000000000..e32f489696b --- /dev/null +++ b/code/game/objects/items/devices/sensor_device.dm @@ -0,0 +1,18 @@ +/obj/item/device/sensor_device + name = "handheld crew monitor" + desc = "A miniature machine that tracks suit sensors across the station." + icon = 'icons/obj/device.dmi' + icon_state = "scanner" + w_class = 2.0 + slot_flags = SLOT_BELT + origin_tech = "programming=3;materials=3;magnets=3" + var/obj/nano_module/crew_monitor/crew_monitor + +/obj/item/device/sensor_device/New() + crew_monitor = new(src) + +/obj/item/device/sensor_device/attack_self(mob/user as mob) + ui_interact(user) + +/obj/item/device/sensor_device/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + crew_monitor.ui_interact(user, ui_key, ui, force_open) \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 938f9da5e72..fde55afe96a 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -95,7 +95,8 @@ "/obj/item/device/flashlight/pen", "/obj/item/clothing/mask/surgical", "/obj/item/clothing/gloves/color/latex", - "/obj/item/weapon/reagent_containers/hypospray/autoinjector" + "/obj/item/weapon/reagent_containers/hypospray/autoinjector", + "/obj/item/device/sensor_device" ) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index e50de9f2d44..6049d30bd51 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -21,11 +21,15 @@ // Reagent ID => friendly name var/list/reagents_to_log=list() -/obj/Topic(href, href_list, var/nowindow = 0) +/obj/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1) // Calling Topic without a corresponding window open causes runtime errors - if(nowindow) - return 0 - return ..() + if(!nowindow && ..()) + return 1 + + if(usr.can_interact_with_interface(nano_host(), checkrange) != STATUS_INTERACTIVE) + return 1 + add_fingerprint(usr) + return 0 /obj/Destroy() machines -= src diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index fcd8dafd77f..c223fa99314 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -234,4 +234,6 @@ sleep(2) new /obj/item/clothing/suit/space/eva/paramedic(src) new /obj/item/clothing/head/helmet/space/eva/paramedic(src) + new /obj/item/clothing/head/helmet/space/eva/paramedic(src) + new /obj/item/device/sensor_device(src) return \ No newline at end of file diff --git a/code/game/response_team.dm b/code/game/response_team.dm index 3b82543e80a..a576c38295f 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -142,11 +142,11 @@ proc/trigger_armed_response_team(var/force = 0) // there's only a certain chance a team will be sent if(!prob(send_team_chance)) - command_alert("It would appear that an emergency response team was requested for [station_name()]. Unfortunately, we were unable to send one at this time.", "Central Command") + command_announcement.Announce("It would appear that an emergency response team was requested for [station_name()]. Unfortunately, we were unable to send one at this time.", "Central Command") can_call_ert = 0 // Only one call per round, ladies. return - command_alert("It would appear that an emergency response team was requested for [station_name()]. We will prepare and send one as soon as possible.", "Central Command") + command_announcement.Announce("It would appear that an emergency response team was requested for [station_name()]. We will prepare and send one as soon as possible.", "Central Command") can_call_ert = 0 // Only one call per round, gentleman. send_emergency_team = 1 diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 7438f54195e..77ddef563fb 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2103,11 +2103,11 @@ if(gravity_is_on) log_admin("[key_name(usr)] toggled gravity on.", 1) message_admins("\blue [key_name_admin(usr)] toggled gravity on.", 1) - command_alert("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") + command_announcement.Announce("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") else log_admin("[key_name(usr)] toggled gravity off.", 1) message_admins("\blue [key_name_admin(usr)] toggled gravity off.", 1) - command_alert("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.") + command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.") if("wave") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","Meteor") @@ -2595,8 +2595,7 @@ if(W.z == 1 && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison)) W.req_access = list() message_admins("[key_name_admin(usr)] activated Egalitarian Station mode") - command_alert("Centcomm airlock control override activated. Please take this time to get acquainted with your coworkers.") - world << sound('sound/AI/commandreport.ogg') + command_announcement.Announce("Centcomm airlock control override activated. Please take this time to get acquainted with your coworkers.", new_sound = 'sound/AI/commandreport.ogg') if("dorf") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","DF") @@ -2611,8 +2610,7 @@ message_admins("[key_name_admin(usr)] triggered an ion storm") var/show_log = alert(usr, "Show ion message?", "Message", "Yes", "No") if(show_log == "Yes") - command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") - world << sound('sound/AI/ionstorm.ogg') + command_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", new_sound = 'sound/AI/ionstorm.ogg') if("carp") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","Crp") diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 9b9c26f7a68..43658f3c74c 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -209,8 +209,7 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0) var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No") if(show_log == "Yes") - command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") - world << sound('sound/AI/ionstorm.ogg') + command_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", new_sound = 'sound/AI/ionstorm.ogg') IonStorm(0) feedback_add_details("admin_verb","ION") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -642,8 +641,7 @@ Traitors and the like can also be revived with the previous role mostly intact. var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No") if(show_log == "Yes") - command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") - world << sound('sound/AI/ionstorm.ogg') + command_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", new_sound = 'sound/AI/ionstorm.ogg') feedback_add_details("admin_verb","IONC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/cmd_admin_rejuvenate(mob/living/M as mob in mob_list) @@ -686,7 +684,7 @@ Traitors and the like can also be revived with the previous role mostly intact. switch(alert("Should this be announced to the general population?",,"Yes","No")) if("Yes") - command_alert(input, customname); + command_announcement.Announce(input, customname); if("No") world << "\red New Nanotrasen Update available at all communication consoles." diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm index 06dfa6b5bcf..03509d38ac3 100644 --- a/code/modules/awaymissions/bluespaceartillery.dm +++ b/code/modules/awaymissions/bluespaceartillery.dm @@ -42,7 +42,7 @@ if (usr.stat || usr.restrained()) return if(src.reload < 180) return if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - command_alert("Bluespace artillery fire detected. Brace for impact.") + command_announcement.Announce("Bluespace artillery fire detected. Brace for impact.") message_admins("[key_name_admin(usr)] has launched an artillery strike.", 1) var/list/L = list() for(var/turf/T in get_area_turfs(thearea.type)) @@ -55,7 +55,7 @@ var/A A = input("Area to jump bombard", "Open Fire", A) in teleportlocs var/area/thearea = teleportlocs[A] - command_alert("Bluespace artillery fire detected. Brace for impact.") + command_announcement.Announce("Bluespace artillery fire detected. Brace for impact.") spawn(30) var/list/L = list() diff --git a/code/modules/computer3/computers/communications.dm b/code/modules/computer3/computers/communications.dm index 37437fdf6aa..5a32b40643a 100644 --- a/code/modules/computer3/computers/communications.dm +++ b/code/modules/computer3/computers/communications.dm @@ -42,6 +42,12 @@ var/status_display_freq = "1435" var/stat_msg1 var/stat_msg2 + + var/datum/announcement/priority/crew_announcement = new + + New() + ..() + crew_announcement.newscast = 1 Reset() ..() @@ -68,9 +74,11 @@ authenticated = 1 if(access_captain in I.GetAccess()) authenticated = 2 + crew_announcement.announcer = GetNameAndAssignmentFromId(I) if("logout" in href_list) authenticated = 0 + crew_announcement.announcer = "" if("swipeidseclevel" in href_list) var/mob/M = usr @@ -102,13 +110,13 @@ usr << "You need to swipe your ID." if("announce" in href_list) if(authenticated==2) - if(message_cooldown) return - var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?") + if(message_cooldown) + usr << "Please allow at least one minute to pass between announcements" + return + var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") if(!input || !interactable()) return - captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain - log_say("[key_name(usr)] has made a captain announcement: [input]") - message_admins("[key_name_admin(usr)] has made a captain announcement.", 1) + crew_announcement.Announce(input) message_cooldown = 1 spawn(600)//One minute cooldown message_cooldown = 0 diff --git a/code/modules/economy/Economy.dm b/code/modules/economy/Economy.dm index cf78723a683..b41a080d251 100644 --- a/code/modules/economy/Economy.dm +++ b/code/modules/economy/Economy.dm @@ -67,7 +67,15 @@ var/setup_economy = 0 /proc/setup_economy() if(setup_economy) return + var/datum/feed_channel/newChannel = new /datum/feed_channel + newChannel.channel_name = "Public Station Announcements" + newChannel.author = "Automated Announcement Listing" + newChannel.locked = 1 + newChannel.is_admin_channel = 1 + news_network.network_channels += newChannel + + newChannel = new /datum/feed_channel newChannel.channel_name = "Tau Ceti Daily" newChannel.author = "CentComm Minister of Information" newChannel.locked = 1 diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index 13da8de1661..c6601aac260 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -15,8 +15,7 @@ /datum/event/alien_infestation/announce() if(successSpawn) - command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") - world << sound('sound/AI/aliens.ogg') + command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') /datum/event/alien_infestation/start() diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm index 96729f0014c..64d02bfce1f 100644 --- a/code/modules/events/blob.dm +++ b/code/modules/events/blob.dm @@ -7,8 +7,7 @@ /datum/event/blob/announce() - command_alert("Confirmed outbreak of level 7 biohazard aboard [station_name()]. Nanotrasen has issued a directive 7-10. The station is to be considered quarantined.", "Biohazard Alert") - world << sound('sound/AI/blob_confirmed.ogg') + command_announcement.Announce("Confirmed outbreak of level 7 biohazard aboard [station_name()]. Nanotrasen has issued a directive 7-10. The station is to be considered quarantined.", "Biohazard Alert", new_sound = 'sound/AI/blob_confirmed.ogg') for (var/mob/living/silicon/ai/aiPlayer in player_list) if (aiPlayer.client) @@ -42,7 +41,7 @@ if(bomb && bomb.r_code && bomb.z == 1) nukecode = bomb.r_code - command_alert("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [nukecode] ", "Biohazard Alert") + command_announcement.Announce("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [nukecode] ", "Biohazard Alert") set_security_level("gamma") var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world @@ -64,7 +63,7 @@ spawn(10) if(Blob || blob_cores.len) return - command_alert("The level 7 biohazard aboard [station_name()] has been eliminated. Directive 7-10 has been lifted, and the station is no longer quarantined.", "Biohazard Update") + command_announcement.Announce("The level 7 biohazard aboard [station_name()] has been eliminated. Directive 7-10 has been lifted, and the station is no longer quarantined.", "Biohazard Update") for (var/mob/living/silicon/ai/aiPlayer in player_list) if (aiPlayer.client) diff --git a/code/modules/events/borers.dm b/code/modules/events/borers.dm index 4f89417c2df..fe7c51fc800 100644 --- a/code/modules/events/borers.dm +++ b/code/modules/events/borers.dm @@ -12,8 +12,7 @@ /datum/event/borer_infestation/announce() if(successSpawn) - command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") - world << sound('sound/AI/aliens.ogg') + command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') /datum/event/borer_infestation/start() var/list/vents = list() diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index a2436f2ac75..7bf1bada95b 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -8,7 +8,7 @@ var/obj/machinery/vending/originMachine /datum/event/brand_intelligence/announce() - command_alert("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert") + command_announcement.Announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert") /datum/event/brand_intelligence/start() for(var/obj/machinery/vending/V in machines) diff --git a/code/modules/events/cargobonus.dm b/code/modules/events/cargobonus.dm index f0c84b86f54..fb1a3ac277e 100644 --- a/code/modules/events/cargobonus.dm +++ b/code/modules/events/cargobonus.dm @@ -2,7 +2,7 @@ announceWhen = 5 /datum/event/cargo_bonus/announce() - command_alert("Congratulations! [station_name()] was chosen for supply limit increase, please contact local cargo department for details!", "Supply Alert") + command_announcement.Announce("Congratulations! [station_name()] was chosen for supply limit increase, please contact local cargo department for details!", "Supply Alert") /datum/event/cargo_bonus/start() supply_controller.points+=rand(100,500) \ No newline at end of file diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm index 7cf82ff1f67..303f5686e8e 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -8,7 +8,7 @@ endWhen = rand(600,1200) /datum/event/carp_migration/announce() - command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") + command_announcement.Announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") /datum/event/carp_migration/start() for(var/obj/effect/landmark/C in landmarks_list) diff --git a/code/modules/events/comms_blackout.dm b/code/modules/events/comms_blackout.dm index 2f5cbea97b3..6b948538d5d 100644 --- a/code/modules/events/comms_blackout.dm +++ b/code/modules/events/comms_blackout.dm @@ -1,6 +1,6 @@ /proc/communications_blackout(var/silent = 1) if(!silent) - command_alert("Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you-BZZT") + command_announcement.Announce("Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you-BZZT") else // AIs will always know if there's a comm blackout, rogue AIs could then lie about comm blackouts in the future while they shutdown comms for(var/mob/living/silicon/ai/A in player_list) A << "
" diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm index d437d85684e..d39517f5343 100644 --- a/code/modules/events/communications_blackout.dm +++ b/code/modules/events/communications_blackout.dm @@ -12,7 +12,7 @@ A << "
" if(prob(30)) //most of the time, we don't want an announcement, so as to allow AIs to fake blackouts. - command_alert(alert) + command_announcement.Announce(alert) /datum/event/communications_blackout/start() for(var/obj/machinery/telecomms/T in telecomms_list) diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index a12aa2147c5..082791999a3 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -3,8 +3,7 @@ oneShot = 1 /datum/event/disease_outbreak/announce() - command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - world << sound('sound/AI/outbreak7.ogg') + command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg') /datum/event/disease_outbreak/setup() announceWhen = rand(15, 30) diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm index 2b9b989e5e9..a8254d02c7a 100644 --- a/code/modules/events/electrical_storm.dm +++ b/code/modules/events/electrical_storm.dm @@ -3,7 +3,7 @@ var/lightsoutRange = 25 /datum/event/electrical_storm/announce() - command_alert("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert") + command_announcement.Announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert") /datum/event/electrical_storm/start() var/list/epicentreList = list() diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 622e62b5172..8fe305f774a 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -145,9 +145,9 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MODERATE, "Nothing", /datum/event/nothing, 1230), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 100, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SECURITY = 20), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 20, list(ASSIGNMENT_SECURITY = 20)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space vines", /datum/event/spacevine, 200, list(ASSIGNMENT_ENGINEER = 10)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Vines", /datum/event/spacevine, 200, list(ASSIGNMENT_ENGINEER = 10)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_shower, 0, list(ASSIGNMENT_ENGINEER = 20)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meaty Ores", /datum/event/dust/meaty, 0, list(ASSIGNMENT_ENGINEER = 20)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meaty Ores", /datum/event/dust/meaty, 0, list(ASSIGNMENT_ENGINEER = 30)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)), // new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 200, list(ASSIGNMENT_ENGINEER = 60)), @@ -156,18 +156,18 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 150)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ionstorm, 0, list(ASSIGNMENT_AI = 50, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5)), - new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Alien Infestation", /datum/event/alien_infestation, 2.5, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), - new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), + new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 20), 1), + new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 15), 1), // NON-BAY EVENTS - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 50, list(ASSIGNMENT_ENGINEER = 50)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 50, list(ASSIGNMENT_ENGINEER = 50)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Dimensional Tear", /datum/event/tear, 0, list(ASSIGNMENT_SECURITY = 25)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vent Clog", /datum/event/vent_clog, 250), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Wormholes", /datum/event/wormholes, 150), - - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Pyro Anomaly", /datum/event/anomaly/anomaly_pyro, 100, list(ASSIGNMENT_ENGINEER = 60)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vortex Anomaly", /datum/event/anomaly/anomaly_vortex, 50, list(ASSIGNMENT_ENGINEER = 25)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Bluespace Anomaly", /datum/event/anomaly/anomaly_bluespace, 50, list(ASSIGNMENT_ENGINEER = 25)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Flux Anomaly", /datum/event/anomaly/anomaly_flux, 50, list(ASSIGNMENT_ENGINEER = 50)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravitational Anomaly", /datum/event/anomaly/anomaly_grav, 200), +// new /datum/event_meta(EVENT_LEVEL_MODERATE, "Pyro Anomaly", /datum/event/anomaly/anomaly_pyro, 100, list(ASSIGNMENT_ENGINEER = 60)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vortex Anomaly", /datum/event/anomaly/anomaly_vortex, 50, list(ASSIGNMENT_ENGINEER = 25)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Bluespace Anomaly", /datum/event/anomaly/anomaly_bluespace, 50, list(ASSIGNMENT_ENGINEER = 25)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Flux Anomaly", /datum/event/anomaly/anomaly_flux, 50, list(ASSIGNMENT_ENGINEER = 50)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravitational Anomaly", /datum/event/anomaly/anomaly_grav, 200), ) /datum/event_container/major diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm index df494ddc245..1dd1956c7ab 100644 --- a/code/modules/events/event_dynamic.dm +++ b/code/modules/events/event_dynamic.dm @@ -79,7 +79,7 @@ var/global/list/possibleEvents = list() if(!spacevines_spawned) possibleEvents[/datum/event/spacevine] = 10 + 5 * active_with_role["Engineer"] if(minutes_passed >= 30) // Give engineers time to set up engine - possibleEvents[/datum/event/anomaly/anomaly_pyro] = 100 + 60 * active_with_role["Engineer"] +// possibleEvents[/datum/event/anomaly/anomaly_pyro] = 100 + 60 * active_with_role["Engineer"] possibleEvents[/datum/event/anomaly/anomaly_vortex] = 50 + 25 * active_with_role["Engineer"] possibleEvents[/datum/event/anomaly/anomaly_bluespace] = 50 + 25 * active_with_role["Engineer"] possibleEvents[/datum/event/anomaly/anomaly_flux] = 50 + 50 * active_with_role["Engineer"] @@ -152,10 +152,7 @@ var/global/list/possibleEvents = list() /*switch(picked_event) if("Meteor") - command_alert("Meteors have been detected on collision course with the station.", "Meteor Alert") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/meteors.ogg') + command_announcement.Announce("Meteors have been detected on collision course with the station.", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg') spawn(100) meteor_wave(10) spawn_meteors() diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm index 71d78d96e4a..c485827efbc 100644 --- a/code/modules/events/grid_check.dm +++ b/code/modules/events/grid_check.dm @@ -8,9 +8,7 @@ power_failure(0) /datum/event/grid_check/announce() - command_alert("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Automated Grid Check") - for(var/mob/M in player_list) - M << sound('sound/AI/poweroff.ogg') + command_announcement.Announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Automated Grid Check", new_sound = 'sound/AI/poweroff.ogg') /datum/event/grid_check/end() power_restore() diff --git a/code/modules/events/infestation.dm b/code/modules/events/infestation.dm index 8971db74853..444da4675ef 100644 --- a/code/modules/events/infestation.dm +++ b/code/modules/events/infestation.dm @@ -102,7 +102,7 @@ /datum/event/infestation/announce() - command_alert("Bioscans indicate that [vermstring] have been breeding in [locstring]. Clear them out, before this starts to affect productivity.", "Lifesign Alert") + command_announcement.Announce("Bioscans indicate that [vermstring] have been breeding in [locstring]. Clear them out, before this starts to affect productivity.", "Lifesign Alert") #undef LOC_KITCHEN #undef LOC_ATMOS diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index 7f66a4366a9..2f7703764eb 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -6,7 +6,7 @@ /datum/event/ionstorm/announce() endWhen = rand(500, 1500) -// command_alert("The station has entered an ion storm. Monitor all electronic equipment for malfunctions", "Anomaly Alert") +// command_announcement.Announce("The station has entered an ion storm. Monitor all electronic equipment for malfunctions", "Anomaly Alert") for (var/mob/living/carbon/human/player in world) if(player.client) players += player.real_name @@ -86,7 +86,7 @@ /datum/event/ionstorm/end() spawn(rand(5000,8000)) if(prob(50)) - command_alert("It has come to our attention that the station passed through an ion storm. Please monitor all electronic equipment for malfunctions.", "Anomaly Alert") + command_announcement.Announce("It has come to our attention that the station passed through an ion storm. Please monitor all electronic equipment for malfunctions.", "Anomaly Alert") /* /proc/IonStorm(botEmagChance = 10) diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm index 571a9ae7d1f..b3fbea5343c 100644 --- a/code/modules/events/mass_hallucination.dm +++ b/code/modules/events/mass_hallucination.dm @@ -3,4 +3,4 @@ if(!(C.species.flags & IS_SYNTHETIC)) C.hallucination += rand(50, 100) /datum/event/mass_hallucination/announce() - command_alert("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage") \ No newline at end of file + command_announcement.Announce("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage") \ No newline at end of file diff --git a/code/modules/events/meteors.dm b/code/modules/events/meteors.dm index 0f74d65b7d9..42b0b1eda1d 100644 --- a/code/modules/events/meteors.dm +++ b/code/modules/events/meteors.dm @@ -9,15 +9,14 @@ endWhen = rand(10,25) * 3 /datum/event/meteor_wave/announce() - command_alert("Meteors have been detected on collision course with the station.", "Meteor Alert") - world << sound('sound/AI/meteors.ogg') - + command_announcement.Announce("Meteors have been detected on collision course with the station.", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg') + /datum/event/meteor_wave/tick() if(IsMultiple(activeFor, 3)) spawn_meteors(rand(2,5)) /datum/event/meteor_wave/end() - command_alert("The station has cleared the meteor storm.", "Meteor Alert") + command_announcement.Announce("The station has cleared the meteor storm.", "Meteor Alert") // /datum/event/meteor_shower @@ -30,7 +29,7 @@ waves = rand(1,4) /datum/event/meteor_shower/announce() - command_alert("The station is now in a meteor shower.", "Meteor Alert") + command_announcement.Announce("The station is now in a meteor shower.", "Meteor Alert") //meteor showers are lighter and more common, /datum/event/meteor_shower/tick() @@ -44,4 +43,4 @@ endWhen = next_meteor + 1 /datum/event/meteor_shower/end() - command_alert("The station has cleared the meteor shower", "Meteor Alert") + command_announcement.Announce("The station has cleared the meteor shower", "Meteor Alert") diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm index 87135bda526..676661f2b7e 100644 --- a/code/modules/events/prison_break.dm +++ b/code/modules/events/prison_break.dm @@ -15,7 +15,7 @@ /datum/event/prison_break/announce() if(prisonAreas && prisonAreas.len > 0) - command_alert("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") + command_announcement.Announce("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") else world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area." kill() @@ -30,7 +30,7 @@ /datum/event/prison_break/announce() if(prisonAreas && prisonAreas.len > 0) - command_alert("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") + command_announcement.Announce("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") else world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area." kill() diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 58b5f60c2cc..5f57115cc11 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -22,8 +22,7 @@ /datum/event/radiation_storm/start() spawn() - world << sound('sound/AI/radiation.ogg') - command_alert("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert") + command_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg') for(var/area/A in world) if(A.z != 1 || is_safe_zone(A)) @@ -36,7 +35,7 @@ sleep(600) - command_alert("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert") + command_announcement.Announce("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert") for(var/i = 0, i < 10, i++) for(var/mob/living/carbon/human/H in living_mob_list) @@ -70,7 +69,7 @@ sleep(100) - command_alert("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert") + command_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert") for(var/area/A in world) if(A.z != 1 || is_safe_zone(A)) diff --git a/code/modules/events/rogue_drones.dm b/code/modules/events/rogue_drones.dm index d3ccaa4d89a..d96c80f60f8 100644 --- a/code/modules/events/rogue_drones.dm +++ b/code/modules/events/rogue_drones.dm @@ -30,7 +30,7 @@ msg = "Contact has been lost with a combat drone wing operating out of the NMV Icarus. If any are sighted in the area, approach with caution." else msg = "Unidentified hackers have targetted a combat drone wing deployed from the NMV Icarus. If any are sighted in the area, approach with caution." - command_alert(msg, "Rogue drone alert") + command_announcement.Announce(msg, "Rogue drone alert") /datum/event/rogue_drone/tick() @@ -49,6 +49,6 @@ num_recovered++ if(num_recovered > drones_list.len * 0.75) - command_alert("Icarus drone control reports the malfunctioning wing has been recovered safely.", "Rogue drone alert") + command_announcement.Announce("Icarus drone control reports the malfunctioning wing has been recovered safely.", "Rogue drone alert") else - command_alert("Icarus drone control registers disappointment at the loss of the drones, but the survivors have been recovered.", "Rogue drone alert") + command_announcement.Announce("Icarus drone control registers disappointment at the loss of the drones, but the survivors have been recovered.", "Rogue drone alert") diff --git a/code/modules/events/sayuevents/meaty_ores.dm b/code/modules/events/sayuevents/meaty_ores.dm index a44708693ef..d6e640934d9 100644 --- a/code/modules/events/sayuevents/meaty_ores.dm +++ b/code/modules/events/sayuevents/meaty_ores.dm @@ -1,9 +1,8 @@ /datum/event/dust/meaty/announce() if(prob(16)) - command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") + command_announcement.Announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") else - command_alert("Meaty ores have been detected on collision course with the station.", "Meaty Ore Alert") - world << sound('sound/AI/meteors.ogg') + command_announcement.Announce("Meaty ores have been detected on collision course with the station.", "Meaty Ore Alert",new_sound = 'sound/AI/meteors.ogg') /datum/event/dust/meaty/setup() qnty = rand(45,125) diff --git a/code/modules/events/sayuevents/wormholes.dm b/code/modules/events/sayuevents/wormholes.dm index e120d11630d..2755768ca79 100644 --- a/code/modules/events/sayuevents/wormholes.dm +++ b/code/modules/events/sayuevents/wormholes.dm @@ -21,10 +21,7 @@ wormholes += new /obj/effect/portal/wormhole(T, null, null, -1) /datum/event/wormholes/announce() - command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert") - for(var/mob/M in player_list) - if(!istype(M, /mob/new_player)) - M << sound('sound/AI/spanomalies.ogg') + command_announcement.Announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", new_sound = 'sound/AI/spanomalies.ogg') /datum/event/wormholes/tick() if(activeFor % shift_frequency == 0) diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm index 7a953d3fd40..43ee40fe1d7 100644 --- a/code/modules/events/spider_infestation.dm +++ b/code/modules/events/spider_infestation.dm @@ -12,9 +12,7 @@ sent_spiders_to_station = 1 /datum/event/spider_infestation/announce() - command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") - world << sound('sound/AI/aliens.ogg') - + command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') /datum/event/spider_infestation/start() diff --git a/code/modules/events/tear.dm b/code/modules/events/tear.dm index d5d572c3b6a..a11455b351d 100644 --- a/code/modules/events/tear.dm +++ b/code/modules/events/tear.dm @@ -5,7 +5,7 @@ var/obj/effect/tear/TE /datum/event/tear/announce() - command_alert("A tear in the fabric of space and time has opened. Expected location: [impact_area.name].", "Anomaly Alert") + command_announcement.Announce("A tear in the fabric of space and time has opened. Expected location: [impact_area.name].", "Anomaly Alert") /datum/event/tear/start() diff --git a/code/modules/events/tgevents/anomaly.dm b/code/modules/events/tgevents/anomaly.dm index 7ab1f25c9ca..a1f951f5747 100644 --- a/code/modules/events/tgevents/anomaly.dm +++ b/code/modules/events/tgevents/anomaly.dm @@ -15,7 +15,7 @@ setup(safety_loop) /datum/event/anomaly/announce() - command_alert("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert") + command_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert") /datum/event/anomaly/start() var/turf/T = pick(get_area_turfs(impact_area)) diff --git a/code/modules/events/tgevents/anomaly_bluespace.dm b/code/modules/events/tgevents/anomaly_bluespace.dm index 224f6f0e2de..9a36ca226c5 100644 --- a/code/modules/events/tgevents/anomaly_bluespace.dm +++ b/code/modules/events/tgevents/anomaly_bluespace.dm @@ -4,7 +4,7 @@ endWhen = 160 /datum/event/anomaly/anomaly_bluespace/announce() - command_alert("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") + command_announcement.Announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") /datum/event/anomaly/anomaly_bluespace/start() @@ -35,7 +35,7 @@ var/turf/TO = get_turf(chosen) // the turf of origin we're travelling TO playsound(TO, 'sound/effects/phasein.ogg', 100, 1) - command_alert("Massive bluespace translocation detected.", "Anomaly Alert") + command_announcement.Announce("Massive bluespace translocation detected.", "Anomaly Alert") var/list/flashers = list() for(var/mob/living/carbon/human/M in viewers(TO, null)) diff --git a/code/modules/events/tgevents/anomaly_flux.dm b/code/modules/events/tgevents/anomaly_flux.dm index bf2cb2d18cc..d02af07b3ef 100644 --- a/code/modules/events/tgevents/anomaly_flux.dm +++ b/code/modules/events/tgevents/anomaly_flux.dm @@ -4,7 +4,7 @@ endWhen = 180 /datum/event/anomaly/anomaly_flux/announce() - command_alert("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") + command_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") /datum/event/anomaly/anomaly_flux/start() var/turf/T = pick(get_area_turfs(impact_area)) diff --git a/code/modules/events/tgevents/anomaly_grav.dm b/code/modules/events/tgevents/anomaly_grav.dm index c5430625ea8..0c9f3776f82 100644 --- a/code/modules/events/tgevents/anomaly_grav.dm +++ b/code/modules/events/tgevents/anomaly_grav.dm @@ -4,7 +4,7 @@ endWhen = 70 /datum/event/anomaly/anomaly_grav/announce() - command_alert("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") + command_announcement.Announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") /datum/event/anomaly/anomaly_grav/start() var/turf/T = pick(get_area_turfs(impact_area)) diff --git a/code/modules/events/tgevents/anomaly_pyro.dm b/code/modules/events/tgevents/anomaly_pyro.dm index 4e7f6a0b947..df4805121cd 100644 --- a/code/modules/events/tgevents/anomaly_pyro.dm +++ b/code/modules/events/tgevents/anomaly_pyro.dm @@ -4,7 +4,7 @@ endWhen = 110 /datum/event/anomaly/anomaly_pyro/announce() - command_alert("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") + command_announcement.Announce("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") /datum/event/anomaly/anomaly_pyro/start() var/turf/T = pick(get_area_turfs(impact_area)) diff --git a/code/modules/events/tgevents/anomaly_vortex.dm b/code/modules/events/tgevents/anomaly_vortex.dm index 6f2f999e728..c950444978e 100644 --- a/code/modules/events/tgevents/anomaly_vortex.dm +++ b/code/modules/events/tgevents/anomaly_vortex.dm @@ -4,7 +4,7 @@ endWhen = 80 /datum/event/anomaly/anomaly_vortex/announce() - command_alert("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert") + command_announcement.Announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert") /datum/event/anomaly/anomaly_vortex/start() var/turf/T = pick(get_area_turfs(impact_area)) diff --git a/code/modules/events/tgevents/brand_intelligence.dm b/code/modules/events/tgevents/brand_intelligence.dm index 893cee98cf1..1cfeba0cd08 100644 --- a/code/modules/events/tgevents/brand_intelligence.dm +++ b/code/modules/events/tgevents/brand_intelligence.dm @@ -8,7 +8,7 @@ /datum/event/brand_intelligence/announce() - command_alert("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert") + command_announcement.Announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert") /datum/event/brand_intelligence/start() diff --git a/code/modules/events/tgevents/immovable_rod.dm b/code/modules/events/tgevents/immovable_rod.dm index 25c3d0308d4..ec86e89981f 100644 --- a/code/modules/events/tgevents/immovable_rod.dm +++ b/code/modules/events/tgevents/immovable_rod.dm @@ -12,7 +12,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 announceWhen = 5 /datum/event/immovable_rod/announce() - command_alert("What the fuck was that?!", "General Alert") + command_announcement.Announce("What the fuck was that?!", "General Alert") /datum/event/immovable_rod/start() var/startx = 0 diff --git a/code/modules/events/tgevents/mass_hallucination.dm b/code/modules/events/tgevents/mass_hallucination.dm index 6a34331acb3..f23a2c15510 100644 --- a/code/modules/events/tgevents/mass_hallucination.dm +++ b/code/modules/events/tgevents/mass_hallucination.dm @@ -6,4 +6,4 @@ if(!(C.species.flags & IS_SYNTHETIC)) C.hallucination += rand(50, 100) /datum/event/mass_hallucination/announce() - command_alert("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage") \ No newline at end of file + command_announcement.Announce("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage") \ No newline at end of file diff --git a/code/modules/events/tgevents/spider_infestation.dm b/code/modules/events/tgevents/spider_infestation.dm deleted file mode 100644 index 1f4cccdf418..00000000000 --- a/code/modules/events/tgevents/spider_infestation.dm +++ /dev/null @@ -1,33 +0,0 @@ -/var/global/sent_spiders_to_station = 0 - -/datum/event/spider_infestation - announceWhen = 400 - - var/spawncount = 1 - - -/datum/event/spider_infestation/setup() - announceWhen = rand(announceWhen, announceWhen + 50) - spawncount = round(num_players() * 1.5) - sent_spiders_to_station = 1 - -/datum/event/spider_infestation/announce() - command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") - world << sound('sound/AI/aliens.ogg') - - -/datum/event/spider_infestation/start() - - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world) - if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network) - if(temp_vent.network.normal_members.len > 50) - vents += temp_vent - - while((spawncount >= 1) && vents.len) - var/obj/vent = pick(vents) - var/obj/effect/spider/spiderling/S = new(vent.loc) - if(prob(66)) - S.grow_as = /mob/living/simple_animal/hostile/giant_spider/nurse - vents -= vent - spawncount-- \ No newline at end of file diff --git a/code/modules/events/tgevents/vent_clog.dm b/code/modules/events/tgevents/vent_clog.dm index 885552dff28..e66174cfa41 100755 --- a/code/modules/events/tgevents/vent_clog.dm +++ b/code/modules/events/tgevents/vent_clog.dm @@ -6,7 +6,7 @@ var/list/vents = list() /datum/event/vent_clog/announce() - command_alert("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert") + command_announcement.Announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert") /datum/event/vent_clog/setup() diff --git a/code/modules/events/viral_infection.dm b/code/modules/events/viral_infection.dm index 876e3453896..9ee3a47077a 100644 --- a/code/modules/events/viral_infection.dm +++ b/code/modules/events/viral_infection.dm @@ -8,8 +8,7 @@ datum/event/viral_infection/setup() severity = rand(1, 3) datum/event/viral_infection/announce() - command_alert("Confirmed outbreak of level five viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - world << sound('sound/AI/outbreak5.ogg') + command_announcement.Announce("Confirmed outbreak of level five viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak5.ogg') datum/event/viral_infection/start() var/list/candidates = list() //list of candidate keys diff --git a/code/modules/events/viral_outbreak.dm b/code/modules/events/viral_outbreak.dm index f11acd511f3..9e139f5742b 100644 --- a/code/modules/events/viral_outbreak.dm +++ b/code/modules/events/viral_outbreak.dm @@ -8,8 +8,7 @@ datum/event/viral_outbreak/setup() severity = rand(2, 4) datum/event/viral_outbreak/announce() - command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - world << sound('sound/AI/outbreak7.ogg') + command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg') datum/event/viral_outbreak/start() var/list/candidates = list() //list of candidate keys diff --git a/code/modules/events/wallrot.dm b/code/modules/events/wallrot.dm index 739ca92411b..b36f7f93760 100644 --- a/code/modules/events/wallrot.dm +++ b/code/modules/events/wallrot.dm @@ -3,7 +3,7 @@ datum/event/wallrot/setup() endWhen = announceWhen + 1 datum/event/wallrot/announce() - command_alert("Harmful fungi detected on station. Station structures may be contaminated.", "Biohazard Alert") + command_announcement.Announce("Harmful fungi detected on station. Station structures may be contaminated.", "Biohazard Alert") datum/event/wallrot/start() spawn() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ded2a3c949e..968fa181d89 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -538,7 +538,21 @@ var/obj/vehicle/V = AM V.RunOver(src) - +// Get rank from ID, ID inside PDA, PDA, ID in wallet, etc. +/mob/living/carbon/human/proc/get_authentification_rank(var/if_no_id = "No id", var/if_no_job = "No job") + var/obj/item/device/pda/pda = wear_id + if (istype(pda)) + if (pda.id) + return pda.id.rank + else + return pda.ownrank + else + var/obj/item/weapon/card/id/id = get_idcard() + if(id) + return id.rank ? id.rank : if_no_job + else + return if_no_id + //gets assignment from ID or ID inside PDA or PDA itself //Useful when player do something with computers /mob/living/carbon/human/proc/get_assignment(var/if_no_id = "No id", var/if_no_job = "No job") diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 47464bc12e4..75e4098c754 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1,3 +1,6 @@ +#define AI_CHECK_WIRELESS 1 +#define AI_CHECK_RADIO 2 + var/list/ai_list = list() //Not sure why this is necessary... @@ -77,8 +80,8 @@ var/list/ai_list = list() possibleNames -= pickedName pickedName = null - real_name = pickedName - name = real_name + aiPDA = new/obj/item/device/pda/ai(src) + SetName(pickedName) anchored = 1 canmove = 0 density = 1 @@ -96,11 +99,6 @@ var/list/ai_list = list() verbs += /mob/living/silicon/ai/proc/show_laws_verb - aiPDA = new/obj/item/device/pda/ai(src) - aiPDA.owner = name - aiPDA.ownjob = "AI" - aiPDA.name = name + " (" + aiPDA.ownjob + ")" - aiMulti = new(src) aiRadio = new(src) aiRadio.myAi = src @@ -112,7 +110,7 @@ var/list/ai_list = list() if (istype(loc, /turf)) verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ - /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_store_location, /mob/living/silicon/ai/proc/ai_goto_location, /mob/living/silicon/ai/proc/ai_remove_location) + /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_store_location, /mob/living/silicon/ai/proc/ai_goto_location, /mob/living/silicon/ai/proc/ai_remove_location, /mob/living/silicon/ai/proc/nano_crew_monitor) if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. @@ -155,11 +153,25 @@ var/list/ai_list = list() hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[NATIONS_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[NATIONS_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + init_subsystems() + ai_list += src ..() return + +/mob/living/silicon/ai/proc/SetName(pickedName as text) + real_name = pickedName + name = pickedName + if(eyeobj) + eyeobj.name = "[pickedName] (AI Eye)" + + // Set ai pda name + if(aiPDA) + aiPDA.ownjob = "AI" + aiPDA.owner = pickedName + aiPDA.name = pickedName + " (" + aiPDA.ownjob + ")" /mob/living/silicon/ai/Destroy() ai_list -= src @@ -301,14 +313,15 @@ var/list/ai_list = list() if(src.stat == 2) src << "You can't call the shuttle because you are dead!" return - if(istype(usr,/mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = src - if(AI.control_disabled) - usr << "Wireless control is disabled!" - return + + if(check_unable(AI_CHECK_WIRELESS)) + return var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No") + if(check_unable(AI_CHECK_WIRELESS)) + return + if(confirm == "Yes") call_shuttle_proc(src) @@ -324,14 +337,15 @@ var/list/ai_list = list() src.view_core() /mob/living/silicon/ai/verb/toggle_anchor() - set category = "AI Commands" - set name = "Toggle Floor Bolts" - if(!isturf(loc)) // if their location isn't a turf - return // stop - anchored = !anchored // Toggles the anchor + set category = "AI Commands" + set name = "Toggle Floor Bolts" + + if(!isturf(loc)) // if their location isn't a turf + return // stop + + anchored = !anchored // Toggles the anchor - src << "[anchored ? "You are now anchored." : "You are now unanchored."]" - // the message in the [] will change depending whether or not the AI is anchored + src << "[anchored ? "You are now anchored." : "You are now unanchored."]" /mob/living/silicon/ai/update_canmove() return 0 @@ -339,16 +353,35 @@ var/list/ai_list = list() /mob/living/silicon/ai/proc/ai_cancel_call() set category = "Malfunction" + if(src.stat == 2) src << "You can't send the shuttle back because you are dead!" return - if(istype(usr,/mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = src - if(AI.control_disabled) - src << "Wireless control is disabled!" - return - cancel_call_proc(src) - return + + if(check_unable(AI_CHECK_WIRELESS)) + return + + var/confirm = alert("Are you sure you want to recall the shuttle?", "Confirm Shuttle Recall", "Yes", "No") + + if(check_unable(AI_CHECK_WIRELESS)) + return + + if(confirm == "Yes") + cancel_call_proc(src) + +/mob/living/silicon/ai/proc/announcement() + set name = "Announcement" + set desc = "Create a vocal announcement by typing in the available words to create a sentence." + set category = "AI Commands" + + if(src.stat == 2) + src << "You can't call make an announcement because you are dead!" + return + + if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) + return + + ai_announcement() /mob/living/silicon/ai/check_eye(var/mob/user as mob) if (!current) @@ -581,9 +614,9 @@ var/list/ai_list = list() src << "Critical error. System offline." return - if(control_disabled) - src << "Wireless communication is disabled." + if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) return + var/ai_allowed_Zlevel = list(1,3,5) var/d var/area/bot_area @@ -704,6 +737,9 @@ var/list/ai_list = list() set name = "Jump To Network" unset_machine() var/cameralist[0] + + if(check_unable()) + return if(usr.stat == 2) usr << "You can't change your camera network because you are dead!" @@ -721,6 +757,9 @@ var/list/ai_list = list() cameralist[i] = i var/old_network = network network = input(U, "Which network would you like to view?") as null|anything in cameralist + + if(check_unable()) + return if(!U.eyeobj) U.view_core() @@ -752,8 +791,16 @@ var/list/ai_list = list() if(usr.stat == 2) usr <<"You cannot change your emotional status because you are dead!" return + + if(check_unable()) + return + var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer") var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions + + if(check_unable()) + return + for (var/obj/machinery/M in machines) //change status if(istype(M, /obj/machinery/ai_status_display)) var/obj/machinery/ai_status_display/AISD = M @@ -773,6 +820,9 @@ var/list/ai_list = list() set name = "Change Hologram" set desc = "Change the default hologram available to AI to something else." set category = "AI Commands" + + if(check_unable()) + return var/input if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member") @@ -827,6 +877,9 @@ var/list/ai_list = list() if(stat != CONSCIOUS) return + + if(check_unable()) + return camera_light_on = !camera_light_on src << "Camera lights [camera_light_on ? "activated" : "deactivated"]." @@ -904,8 +957,11 @@ var/list/ai_list = list() set name = "Radio Settings" set desc = "Allows you to change settings of your radio." set category = "AI Commands" - - src << "Accessing Subspace Transceiver control..." + + if(check_unable(AI_CHECK_RADIO)) + return + + src << "Accessing Subspace Transceiver control..." if (src.aiRadio) src.aiRadio.interact(src) @@ -956,4 +1012,25 @@ var/list/ai_list = list() src << "\red You deny the request." else src << "\red You've failed to open an airlock for [target]" - return \ No newline at end of file + return + + +/mob/living/silicon/ai/proc/check_unable(var/flags = 0) + if(stat == DEAD) + usr << "\red You are dead!" + return 1 + + if((flags & AI_CHECK_WIRELESS) && src.control_disabled) + usr << "\red Wireless control is disabled!" + return 1 + if((flags & AI_CHECK_RADIO) && src.aiRadio.disabledAi) + src << "\red System Error - Transceiver Disabled!" + return 1 + return 0 + +/mob/living/silicon/ai/proc/is_in_chassis() + return istype(loc, /turf) + +#undef AI_CHECK_WIRELESS +#undef AI_CHECK_RADIO + \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 8218bec993e..ec02433c46a 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -134,7 +134,7 @@ src << "ERROR: Eyeobj not found. Creating new eye..." src.eyeobj = new(src.loc) src.eyeobj.ai = src - src.eyeobj.name = "[src.name] (AI Eye)" // Give it a name + src.SetName(src.name) if(client && client.eye) client.eye = src diff --git a/code/modules/mob/living/silicon/ai/nano.dm b/code/modules/mob/living/silicon/ai/nano.dm new file mode 100644 index 00000000000..f9bb7a25d79 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/nano.dm @@ -0,0 +1,10 @@ +var/obj/nano_module/crew_monitor/crew_monitor + +/mob/living/silicon/ai/proc/init_subsystems() + crew_monitor = new(src) + +/mob/living/silicon/ai/proc/nano_crew_monitor() + set category = "AI Commands" + set name = "Crew Monitor" + + crew_monitor.ui_interact(usr) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index e535a2dedee..b596fd53541 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -1,32 +1,32 @@ /mob/living/silicon/ai/say(var/message) - if(parent && istype(parent) && parent.stat != 2) - parent.say(message) - return - //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead. - ..(message) + if(parent && istype(parent) && parent.stat != 2) + parent.say(message) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead. + return + + ..(message) /mob/living/silicon/ai/say_understands(var/other) - if (istype(other, /mob/living/carbon/human)) - return 1 - if (istype(other, /mob/living/silicon/robot)) - return 1 - if (istype(other, /mob/living/silicon/decoy)) - return 1 - if (istype(other, /mob/living/carbon/brain)) - return 1 - if (istype(other, /mob/living/silicon/pai)) - return 1 - return ..() + if (istype(other, /mob/living/carbon/human)) + return 1 + if (istype(other, /mob/living/silicon/robot)) + return 1 + if (istype(other, /mob/living/silicon/decoy)) + return 1 + if (istype(other, /mob/living/carbon/brain)) + return 1 + if (istype(other, /mob/living/silicon/pai)) + return 1 + return ..() /mob/living/silicon/ai/say_quote(var/text) - var/ending = copytext(text, length(text)) + var/ending = copytext(text, length(text)) - if (ending == "?") - return "queries, \"[text]\""; - else if (ending == "!") - return "declares, \"[text]\""; + if (ending == "?") + return "queries, \"[text]\""; + else if (ending == "!") + return "declares, \"[text]\""; - return "states, \"[text]\""; + return "states, \"[text]\""; /mob/living/silicon/ai/proc/IsVocal() @@ -36,44 +36,28 @@ var/const/VOX_DELAY = 100 var/const/VOX_PATH = "sound/vox_fem/" /mob/living/silicon/ai/verb/announcement_help() - - set name = "Announcement Help" - set desc = "Display a list of vocal words to announce to the crew." - set category = "AI Commands" - - - var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.
\ - \ - WARNING:
Misuse of the announcement system will get you job banned.
" - - var/index = 0 - for(var/word in vox_sounds) - index++ - dat += "[capitalize(word)]" - if(index != vox_sounds.len) - dat += " / " - - var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400) - popup.set_content(dat) - popup.open() - - -/mob/living/silicon/ai/proc/announcement() - - set name = "Announcement" - set desc = "Create a vocal announcement by typing in the available words to create a sentence." + set name = "Announcement Help" + set desc = "Display a list of vocal words to announce to the crew." set category = "AI Commands" - if(src.stat == 2) - src << "You can't call the shuttle because you are dead!" - return - if(istype(usr,/mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = src - if(AI.control_disabled) - usr << "Wireless control is disabled!" - return + var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.
\ + \ + WARNING:
Misuse of the announcement system will get you job banned.
" + + var/index = 0 + for(var/word in vox_sounds) + index++ + dat += "[capitalize(word)]" + if(index != vox_sounds.len) + dat += " / " + + var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400) + popup.set_content(dat) + popup.open() + +/mob/living/silicon/ai/proc/ai_announcement() if(announcing_vox > world.time) src << "Please wait [round((announcing_vox - world.time) / 10)] seconds." return @@ -112,27 +96,24 @@ var/const/VOX_PATH = "sound/vox_fem/" /proc/play_vox_word(var/word, var/z_level, var/mob/only_listener) + word = lowertext(word) + if(vox_sounds[word]) + var/sound_file = vox_sounds[word] + var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL) + voice.status = SOUND_STREAM - word = lowertext(word) - - if(vox_sounds[word]) - - var/sound_file = vox_sounds[word] - var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL) - voice.status = SOUND_STREAM - - // If there is no single listener, broadcast to everyone in the same z level - if(!only_listener) - // Play voice for all mobs in the z level - for(var/mob/M in player_list) - if(M.client) - var/turf/T = get_turf(M) - if(T.z == z_level) - M << voice - else - only_listener << voice - return 1 - return 0 + // If there is no single listener, broadcast to everyone in the same z level + if(!only_listener) + // Play voice for all mobs in the z level + for(var/mob/M in player_list) + if(M.client) + var/turf/T = get_turf(M) + if(T.z == z_level && !isdeaf(M)) + M << voice + else + only_listener << voice + return 1 + return 0 // VOX sounds moved to /code/defines/vox_sounds.dm diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index b652a106824..b5245c14a0b 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -158,6 +158,12 @@ proc/isnewplayer(A) proc/hasorgans(A) return ishuman(A) + +proc/isdeaf(A) + if(istype(A, /mob)) + var/mob/M = A + return (M.sdisabilities & DEAF) || M.ear_deaf + return 0 /proc/hsl2rgb(h, s, l) return diff --git a/code/modules/nano/modules/crew_monitor.dm b/code/modules/nano/modules/crew_monitor.dm new file mode 100644 index 00000000000..c27c0446395 --- /dev/null +++ b/code/modules/nano/modules/crew_monitor.dm @@ -0,0 +1,88 @@ +/obj/nano_module/crew_monitor + name = "Crew monitor" + var/list/tracked = new + +/obj/nano_module/crew_monitor/Topic(href, href_list) + if(..()) return + var/turf/T = get_turf(src) + if (!T || !(T.z in config.player_levels)) + usr << "Unable to establish a connection: You're too far away from the station!" + return 0 + if(href_list["close"] ) + var/mob/user = usr + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") + usr.unset_machine() + ui.close() + return 0 + if(href_list["update"]) + src.updateDialog() + return 1 + +/obj/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + user.set_machine(src) + src.scan() + + var/data[0] + var/turf/T = get_turf(src) + var/list/crewmembers = list() + for(var/obj/item/clothing/under/C in src.tracked) + + var/turf/pos = get_turf(C) + + if((C) && (C.has_sensor) && (pos) && (T && pos.z == T.z) && (C.sensor_mode != SUIT_SENSOR_OFF)) + if(istype(C.loc, /mob/living/carbon/human)) + + var/mob/living/carbon/human/H = C.loc + if(H.w_uniform != C) + continue + + var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1) + + crewmemberData["sensor_type"] = C.sensor_mode + crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown") + crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job") + crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job") + + if(C.sensor_mode >= SUIT_SENSOR_BINARY) + crewmemberData["dead"] = H.stat > 1 + + if(C.sensor_mode >= SUIT_SENSOR_VITAL) + crewmemberData["oxy"] = round(H.getOxyLoss(), 1) + crewmemberData["tox"] = round(H.getToxLoss(), 1) + crewmemberData["fire"] = round(H.getFireLoss(), 1) + crewmemberData["brute"] = round(H.getBruteLoss(), 1) + + if(C.sensor_mode >= SUIT_SENSOR_TRACKING) + var/area/A = get_area(H) + crewmemberData["area"] = sanitize(A.name) + crewmemberData["x"] = pos.x + crewmemberData["y"] = pos.y + + crewmembers[++crewmembers.len] = crewmemberData + + crewmembers = sortByKey(crewmembers, "name") + + data["crewmembers"] = crewmembers + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if(!ui) + ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800) + + // adding a template with the key "mapContent" enables the map ui functionality + ui.add_template("mapContent", "crew_monitor_map_content.tmpl") + // adding a template with the key "mapHeader" replaces the map header content + ui.add_template("mapHeader", "crew_monitor_map_header.tmpl") + + ui.set_initial_data(data) + ui.open() + + // should make the UI auto-update; doesn't seem to? + ui.set_auto_update(1) + +/obj/nano_module/crew_monitor/proc/scan() + for(var/mob/living/carbon/human/H in mob_list) + if(istype(H.w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/C = H.w_uniform + if (C.has_sensor) + tracked |= C + return 1 diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm index 2ce8de3b08b..36241b2ec75 100644 --- a/code/modules/nano/nanomanager.dm +++ b/code/modules/nano/nanomanager.dm @@ -1,8 +1,9 @@ // This is the window/UI manager for Nano UI // There should only ever be one (global) instance of nanomanger /datum/nanomanager - // the list of current open /nanoui UIs + // a list of current open /nanoui UIs, grouped by src_object and ui_key var/open_uis[0] + // a list of current open /nanoui UIs, not grouped, for use in processing var/list/processing_uis = list() // a list of asset filenames which are to be sent to the client on user logon var/list/asset_files = list() @@ -26,7 +27,8 @@ filenames = flist(path) for(var/filename in filenames) if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore - asset_files.Add(file(path + filename)) // add this file to asset_files for sending to clients when they connect + if(fexists(path + filename)) + asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect return @@ -85,7 +87,7 @@ /** * Update all /nanoui uis attached to src_object * - * @param src_object /obj|/mob The obj or mob which the uis belong to + * @param src_object /obj|/mob The obj or mob which the uis are attached to * * @return int The number of uis updated */ @@ -97,7 +99,7 @@ var/update_count = 0 for (var/ui_key in open_uis[src_object_key]) for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key]) - if(ui && ui.src_object && ui.user) + if(ui && ui.src_object && ui.user && ui.src_object.nano_host()) ui.process(1) update_count++ return update_count @@ -245,4 +247,3 @@ for(var/file in asset_files) client << browse_rsc(file) // send the file to the client - return 1 // success diff --git a/code/modules/nano/nanoprocs.dm b/code/modules/nano/nanoprocs.dm new file mode 100644 index 00000000000..81b939cf5c4 --- /dev/null +++ b/code/modules/nano/nanoprocs.dm @@ -0,0 +1,11 @@ +/atom/movable/proc/nano_host() + return src + +/obj/nano_module/nano_host() + return loc + +/atom/movable/proc/nano_can_update() + return 1 + +/obj/machinery/nano_can_update() + return !(stat & (NOPOWER|BROKEN)) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index 01792ad0c3d..6b37eb96948 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -6,11 +6,6 @@ nanoui class (or whatever Byond calls classes) nanoui is used to open and update nano browser uis **********************************************************/ - -#define STATUS_INTERACTIVE 2 // GREEN Visability -#define STATUS_UPDATE 1 // ORANGE Visability -#define STATUS_DISABLED 0 // RED Visability - /datum/nanoui // the user who opened this ui var/mob/user @@ -143,36 +138,122 @@ nanoui is used to open and update nano browser uis * @return nothing */ /datum/nanoui/proc/update_status(var/push_update = 0) - if (istype(user, /mob/living/silicon/ai)) - set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility) - else if (istype(user, /mob/living/silicon/robot)) - if (src_object in view(7, user)) // robots can see and interact with things they can see within 7 tiles - set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility) - else - set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility) + var/atom/movable/host = src_object.nano_host() + if(!host.nano_can_update()) + close() + return + + var/status = user.can_interact_with_interface(host.nano_host()) + if(status == STATUS_CLOSE) + close() else - var/dist = get_dist(src_object, user) + set_status(status, push_update) + +/* + Procs called by update_status() +*/ - if (dist > 4) - close() - return +/mob/living/silicon/pai/can_interact_with_interface(src_object) + if(src_object == src && !stat) + return STATUS_INTERACTIVE + else + return ..() - if ((allowed_user_stat > -1) && (user.stat > allowed_user_stat)) - set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility) - else if (user.restrained() || user.lying) - set_status(STATUS_UPDATE, push_update) // update only (orange visibility) - else if (istype(src_object, /obj/item/device/uplink/hidden)) // You know what if they have the uplink open let them use the UI - set_status(STATUS_INTERACTIVE, push_update) // Will build in distance checks on the topics for sanity. - else if (!(src_object in view(4, user))) // If the src object is not in visable, set status to 0 - set_status(STATUS_DISABLED, push_update) // interactive (green visibility) - else if (dist <= 1) - set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility) - else if (dist <= 2) - set_status(STATUS_UPDATE, push_update) // update only (orange visibility) - else if (istype(src_object, /obj/item/device/uplink/hidden)) // You know what if they have the uplink open let them use the UI - set_status(STATUS_INTERACTIVE, push_update) // Will build in distance checks on the topics for sanity. - else if (dist <= 4) - set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility) +/mob/proc/can_interact_with_interface(var/src_object) + return STATUS_CLOSE // By default no mob can do anything with NanoUI + +/mob/dead/observer/can_interact_with_interface() + if(check_rights(R_ADMIN, 0)) + return STATUS_INTERACTIVE // Admins are more equal + return STATUS_UPDATE // Ghosts can view updates + +/mob/living/silicon/robot/can_interact_with_interface(var/src_object) + if(stat || !client) + return STATUS_CLOSE + if(lockcharge || stunned || weakened) + return STATUS_DISABLED + if (src_object in view(client.view, src)) // robots can see and interact with things they can see within their view range + return STATUS_INTERACTIVE // interactive (green visibility) + return STATUS_DISABLED // no updates, completely disabled (red visibility) + +/mob/living/silicon/robot/syndicate/can_interact_with_interface(var/src_object) + . = ..() + if(. != STATUS_INTERACTIVE) + return + + if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level + return STATUS_INTERACTIVE + if(istype(get_area(src), /area/syndicate_station) || istype(get_area(src), /area/traitor)) // If elsewhere, they can interact with everything on the syndicate shuttle and traitor station + return STATUS_INTERACTIVE + if(istype(src_object, /obj/machinery)) // And they can also interact with everything else + /*var/obj/machinery/Machine = src_object + if(Machine.emagged) // Uncomment so they can only interact with emagged machinery + return STATUS_INTERACTIVE*/ + return STATUS_INTERACTIVE + return STATUS_UPDATE + +/mob/living/silicon/ai/can_interact_with_interface(var/src_object) + if(!client || check_unable(1)) + return STATUS_CLOSE + // Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras) + // unless it's on the same level as the object it's interacting with. + var/turf/T = get_turf(src_object) + if(!T || !(z == T.z || (T.z in config.player_levels))) + return STATUS_CLOSE + + // If an object is in view then we can interact with it + if(src_object in view(client.view, src)) + return STATUS_INTERACTIVE + + // If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view + if(is_in_chassis()) + //stop AIs from leaving windows open and using then after they lose vision + //apc_override is needed here because AIs use their own APC when powerless + if(cameranet && !cameranet.checkTurfVis(get_turf(src_object))) + return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE + return STATUS_INTERACTIVE + + return STATUS_CLOSE + +/mob/living/proc/shared_living_nano_interaction(var/src_object) + if (src.stat != CONSCIOUS) + return STATUS_CLOSE // no updates, close the interface + else if (restrained() || lying || stat || stunned || weakened) + return STATUS_UPDATE // update only (orange visibility) + return STATUS_INTERACTIVE + +/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object) + if(!isturf(src_object.loc)) + if(src_object.loc == src) // Item in the inventory + return STATUS_INTERACTIVE + if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item + return STATUS_INTERACTIVE + + if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates + return STATUS_CLOSE + + var/dist = get_dist(src_object, src) + if (dist <= 1) + return STATUS_INTERACTIVE // interactive (green visibility) + else if (dist <= 2) + return STATUS_UPDATE // update only (orange visibility) + else if (dist <= 4) + return STATUS_DISABLED // no updates, completely disabled (red visibility) + return STATUS_CLOSE + +/mob/living/can_interact_with_interface(var/src_object, var/be_close = 1) + . = shared_living_nano_interaction(src_object) + if(. == STATUS_INTERACTIVE && be_close) + . = shared_living_nano_distance(src_object) + if(STATUS_INTERACTIVE) + return STATUS_UPDATE + +/mob/living/carbon/human/can_interact_with_interface(var/src_object, var/be_close = 1) + . = shared_living_nano_interaction(src_object) + if(. == STATUS_INTERACTIVE && be_close) + . = shared_living_nano_distance(src_object) + if(. == STATUS_UPDATE && (M_TK in mutations)) // If we have telekinesis and remain close enough, allow interaction. + return STATUS_INTERACTIVE /** * Set the ui to auto update (every master_controller tick) diff --git a/code/modules/security levels/security levels.dm b/code/modules/security levels/security levels.dm index b85d9589209..0fb411b2894 100644 --- a/code/modules/security levels/security levels.dm +++ b/code/modules/security levels/security levels.dm @@ -7,6 +7,8 @@ //5 = code delta //config.alert_desc_blue_downto +/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg')) +/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1) /proc/set_security_level(var/level) switch(level) @@ -27,8 +29,7 @@ if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level) switch(level) if(SEC_LEVEL_GREEN) - world << "Attention! Security level lowered to green." - world << "All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced." + security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.") security_level = SEC_LEVEL_GREEN for(var/obj/machinery/firealarm/FA in world) @@ -38,11 +39,9 @@ if(SEC_LEVEL_BLUE) if(security_level < SEC_LEVEL_BLUE) - world << "Attention! Security level elevated to blue." - world << "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted." + security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.") else - world << "Attention! Security level lowered to blue." - world << "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed." + security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.") security_level = SEC_LEVEL_BLUE for(var/obj/machinery/firealarm/FA in world) @@ -52,11 +51,9 @@ if(SEC_LEVEL_RED) if(security_level < SEC_LEVEL_RED) - world << "Attention! Code Red!" - world << "There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised. The station's secure armory has been unlocked and is ready for use." + security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") else - world << "Attention! Code Red!" - world << "The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised." + security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") security_level = SEC_LEVEL_RED var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world @@ -74,8 +71,7 @@ FA.overlays += image('icons/obj/monitors.dmi', "overlay_red") if(SEC_LEVEL_GAMMA) - world << "Attention! Gamma security level activated!" - world << "Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use." + security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!") security_level = SEC_LEVEL_GAMMA move_gamma_ship() @@ -102,8 +98,7 @@ FA.update_icon() if(SEC_LEVEL_EPSILON) - world << "Attention! Epsilon security level activated!" - world << "Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated." + security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!") security_level = SEC_LEVEL_EPSILON var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) @@ -116,8 +111,7 @@ FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon") if(SEC_LEVEL_DELTA) - world << "Attention! Delta security level reached!" - world << "The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill." + security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!") security_level = SEC_LEVEL_DELTA var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm index 29baa07c1b0..398bc9f9259 100644 --- a/code/modules/shuttles/shuttle_emergency.dm +++ b/code/modules/shuttles/shuttle_emergency.dm @@ -26,9 +26,9 @@ emergency_shuttle.departed = 1 if (emergency_shuttle.evac) - captain_announce("The Emergency Shuttle has left the station. Estimate [round(emergency_shuttle.estimate_arrival_time()/60,1)] minutes until the shuttle docks at Central Command.") + priority_announcement.Announce("The Emergency Shuttle has left the station. Estimate [round(emergency_shuttle.estimate_arrival_time()/60,1)] minutes until the shuttle docks at Central Command.") else - captain_announce("The Crew Transfer Shuttle has left the station. Estimate [round(emergency_shuttle.estimate_arrival_time()/60,1)] minutes until the shuttle docks at Central Command.") + priority_announcement.Announce("The Crew Transfer Shuttle has left the station. Estimate [round(emergency_shuttle.estimate_arrival_time()/60,1)] minutes until the shuttle docks at Central Command.") ..(origin, destination) diff --git a/code/modules/shuttles/shuttles_multi.dm b/code/modules/shuttles/shuttles_multi.dm index 3a73cafb58f..bac0384a4d3 100644 --- a/code/modules/shuttles/shuttles_multi.dm +++ b/code/modules/shuttles/shuttles_multi.dm @@ -33,14 +33,14 @@ if(cloaked || isnull(departure_message)) return - command_alert(departure_message,(announcer ? announcer : "Central Command")) + command_announcement.Announce(departure_message,(announcer ? announcer : "Central Command")) /datum/shuttle/multi_shuttle/proc/announce_arrival() if(cloaked || isnull(arrival_message)) return - command_alert(arrival_message,(announcer ? announcer : "Central Command")) + command_announcement.Announce(arrival_message,(announcer ? announcer : "Central Command")) /obj/machinery/computer/shuttle_control/multi icon_state = "syndishuttle" diff --git a/code/setup.dm b/code/setup.dm index 4906f0e6bdf..ad89e18dbbb 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -951,4 +951,10 @@ var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF") #define SUIT_SENSOR_OFF 0 #define SUIT_SENSOR_BINARY 1 #define SUIT_SENSOR_VITAL 2 -#define SUIT_SENSOR_TRACKING 3 \ No newline at end of file +#define SUIT_SENSOR_TRACKING 3 + +// NanoUI flags +#define STATUS_INTERACTIVE 2 // GREEN Visability +#define STATUS_UPDATE 1 // ORANGE Visability +#define STATUS_DISABLED 0 // RED Visability +#define STATUS_CLOSE -1 // Close the interface \ No newline at end of file diff --git a/config/example/config.txt b/config/example/config.txt index 1a53041a540..a26aa4575d6 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -246,6 +246,18 @@ GHOST_INTERACTION ## Default is "python" on Windows, "/usr/bin/env python2" on UNIX. #PYTHON_PATH pythonw +## Defines which Z-levels the station exists on. +STATION_LEVELS 1 + +## Defines which Z-levels are used for admin functionality, such as Central Command and the Syndicate Shuttle +ADMIN_LEVELS 2 + +## Defines which Z-levels which, for example, a Code Red announcement may affect +CONTACT_LEVELS 1;5 + +## Defines all Z-levels a character can typically reach +PLAYER_LEVELS 1;3;4;5;6 + ## Expected round length in minutes EXPECTED_ROUND_LENGTH 120 diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index a83f398a1b3f9e069c8293351a4ef7f15e143a71..d226cf4694948c20f38c4758e1ceb6517e77b8b5 100644 GIT binary patch delta 5866 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 diff --git a/nano/debug.html b/nano/debug.html index 969956bacb2..58b2be3df1a 100644 --- a/nano/debug.html +++ b/nano/debug.html @@ -16,7 +16,7 @@ - +