diff --git a/code/__DEFINES/~skyrat_defines/sound.dm b/code/__DEFINES/~skyrat_defines/sound.dm
new file mode 100644
index 00000000000..4408a95c832
--- /dev/null
+++ b/code/__DEFINES/~skyrat_defines/sound.dm
@@ -0,0 +1,18 @@
+#define ANNOUNCER_SHUTTLELEFT "announcer_shuttleleft"
+#define ANNOUNCER_CARP "announcer_carp"
+#define ANNOUNCER_VORTEXANOMALIES "announcer_vortexanomalies"
+#define ANNOUNCER_CAPTAIN "announcer_captain"
+#define ANNOUNCER_MASSIVEBSPACEANOMALIES "announcer_massivebspaceanomalies"
+#define ANNOUNCER_PYROANOMALIES "announcer_pyroanomalies"
+#define ANNOUNCER_FLUXANOMALIES "announcer_fluxanomalies"
+#define ANNOUNCER_GRAVANOMALIES "announcer_gravanomalies"
+#define ANNOUNCER_GRAVGENON "announcer_gravgenon"
+#define ANNOUNCER_GRAVGENOFF "announcer_gravgenoff"
+#define ANNOUNCER_GREYTIDE "announcer_greytide"
+#define ANNOUNCER_COMMSBLACKOUT "announcer_commsblackout"
+#define ANNOUNCER_ELECTRICALSTORM "announcer_electricalstorm"
+#define ANNOUNCER_BRANDINTELLIGENCE "announcer_brandintelligence"
+#define ANNOUNCER_RADIATIONPASSED "announcer_radiationpasssed"
+#define ANNOUNCER_BLUESPACEARTY "announcer_bluespacearty"
+#define ANNOUNCER_SPOOKY "announcer_spooky"
+#define ANNOUNCER_ERTYES "announcer_ertyes"
diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm
index 911792c8e84..7202ba3df3e 100644
--- a/code/__HELPERS/priority_announce.dm
+++ b/code/__HELPERS/priority_announce.dm
@@ -1,3 +1,4 @@
+/* - SKYRAT EDIT REMOVAL - MOVED TO MODULAR PRIORITY_ANNOUNCE.DM
/proc/priority_announce(text, title = "", sound, type , sender_override, has_important_message)
if(!text)
return
@@ -73,3 +74,4 @@
SEND_SOUND(M, sound('sound/misc/notice1.ogg'))
else
SEND_SOUND(M, sound('sound/misc/notice2.ogg'))
+*/
diff --git a/code/controllers/subsystem/communications.dm b/code/controllers/subsystem/communications.dm
index 3bab7faf704..916e60b1c5d 100644
--- a/code/controllers/subsystem/communications.dm
+++ b/code/controllers/subsystem/communications.dm
@@ -23,7 +23,7 @@ SUBSYSTEM_DEF(communications)
minor_announce(html_decode(input),"[user.name] Announces:")
silicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN_AI
else
- priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain", has_important_message = TRUE)
+ priority_announce(html_decode(user.treat_message(input)), null, ANNOUNCER_CAPTAIN, "Captain", has_important_message = TRUE) //SKYRAT EDIT CHANGE
nonsilicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN
user.log_talk(input, LOG_SAY, tag="priority announcement")
message_admins("[ADMIN_LOOKUPFLW(user)] has made a priority announcement.")
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index fc44224836f..5e3452ebea0 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -306,7 +306,7 @@ SUBSYSTEM_DEF(ticker)
SSdbcore.SetRoundStart()
to_chat(world, "Welcome to [station_name()], enjoy your stay!")
- SEND_SOUND(world, sound(SSstation.announcer.get_rand_welcome_sound()))
+ alert_sound_to_playing(sound(SSstation.announcer.get_rand_welcome_sound())) //SKYRAT EDIT CHANGE
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)
diff --git a/code/datums/announcers/default_announcer.dm b/code/datums/announcers/default_announcer.dm
index 9db822e02fe..c604ed2a704 100644
--- a/code/datums/announcers/default_announcer.dm
+++ b/code/datums/announcers/default_announcer.dm
@@ -1,3 +1,4 @@
+/*
/datum/centcom_announcer/default
welcome_sounds = list('sound/ai/default/welcome.ogg')
alert_sounds = list('sound/ai/default/attention.ogg')
@@ -18,3 +19,4 @@
ANNOUNCER_SHUTTLEDOCK = 'sound/ai/default/shuttledock.ogg',
ANNOUNCER_SHUTTLERECALLED = 'sound/ai/default/shuttlerecalled.ogg',
ANNOUNCER_SPANOMALIES = 'sound/ai/default/spanomalies.ogg')
+ */
diff --git a/code/datums/ert.dm b/code/datums/ert.dm
index f0f783aebf0..18b8f4ccc22 100644
--- a/code/datums/ert.dm
+++ b/code/datums/ert.dm
@@ -16,6 +16,8 @@
var/spawn_admin = FALSE
/// If TRUE, we try and pick one of the most experienced players who volunteered to fill the leader slot
var/leader_experience = TRUE
+ ///SKYRAT EDIT: Do we want to notify the players of this ERT?
+ var/notify_players = TRUE
/datum/ert/New()
if (!polldesc)
diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm
index 5a084aa23b5..d3b04f82f68 100644
--- a/code/datums/weather/weather_types/radiation_storm.dm
+++ b/code/datums/weather/weather_types/radiation_storm.dm
@@ -47,7 +47,7 @@
/datum/weather/rad_storm/end()
if(..())
return
- priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert")
+ priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert", ANNOUNCER_RADIATIONPASSED) //SKYRAT EDIT CHANGE
status_alarm(FALSE)
/datum/weather/rad_storm/proc/status_alarm(active) //Makes the status displays show the radiation warning for those who missed the announcement.
diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm
index 988711468fd..32207447593 100644
--- a/code/game/objects/effects/anomalies.dm
+++ b/code/game/objects/effects/anomalies.dm
@@ -234,7 +234,7 @@
var/turf/TO = get_turf(chosen) // the turf of origin we're travelling TO
playsound(TO, 'sound/effects/phasein.ogg', 100, TRUE)
- priority_announce("Massive bluespace translocation detected.", "Anomaly Alert")
+ priority_announce("Massive bluespace translocation detected.", "Anomaly Alert", ANNOUNCER_MASSIVEBSPACEANOMALIES) //SKYRAT EDIT CHANGE
var/list/flashers = list()
for(var/mob/living/carbon/C in viewers(TO, null))
diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm
index 0fd8d98e0d9..7ba629fda71 100644
--- a/code/modules/admin/verbs/one_click_antag.dm
+++ b/code/modules/admin/verbs/one_click_antag.dm
@@ -325,7 +325,8 @@
"open_armory" = list("desc" = "Open armory doors", "type" = "boolean", "value" = "[(ertemplate.opendoors ? "Yes" : "No")]"),
"leader_experience" = list("desc" = "Pick an experienced leader", "type" = "boolean", "value" = "[(ertemplate.leader_experience ? "Yes" : "No")]"),
"random_names" = list("desc" = "Randomize names", "type" = "boolean", "value" = "[(ertemplate.random_names ? "Yes" : "No")]"),
- "spawn_admin" = list("desc" = "Spawn yourself as briefing officer", "type" = "boolean", "value" = "[(ertemplate.spawn_admin ? "Yes" : "No")]")
+ "spawn_admin" = list("desc" = "Spawn yourself as briefing officer", "type" = "boolean", "value" = "[(ertemplate.spawn_admin ? "Yes" : "No")]"),
+ "notify_players" = list("desc" = "Notify players that you have sent an ERT", "type" = "boolean", "value" = "[(ertemplate.notify_players ? "Yes" : "No")]") //SKYRAT EDIT ADDITION
)
)
@@ -352,6 +353,7 @@
ertemplate.leader_experience = prefs["leader_experience"]["value"] == "Yes"
ertemplate.random_names = prefs["random_names"]["value"] == "Yes"
ertemplate.spawn_admin = prefs["spawn_admin"]["value"] == "Yes"
+ ertemplate.notify_players = prefs["notify_players"]["value"] == "Yes" //SKYRAT EDIT ADDITION
var/list/spawnpoints = GLOB.emergencyresponseteamspawn
var/index = 0
@@ -443,7 +445,10 @@
if (teamSpawned)
message_admins("[ertemplate.polldesc] has spawned with the mission: [ertemplate.mission]")
-
+ //SKYRAT EDIT ADDITION BEGIN
+ if(ertemplate.notify_players)
+ priority_announce("Central command has responded to your request for a CODE [uppertext(ertemplate.code)] Emergency Response Team and have confirmed one to be enroute.", "ERT Request", ANNOUNCER_ERTYES)
+ //SKYRAT EDIT END
//Open the Armory doors
if(ertemplate.opendoors)
for(var/obj/machinery/door/poddoor/ert/door in GLOB.airlocks)
diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
index 1b1d0f6cae7..e250066f8bb 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
@@ -462,9 +462,10 @@
safety = TRUE
update_appearance()
sound_to_playing_players('sound/machines/alarm.ogg')
+ sound_to_playing_players('modular_skyrat/modules/alerts/sound/ai/default/DeltaBOOM.ogg') //SKYRAT EDIT ADDITION
if(SSticker?.mode)
SSticker.roundend_check_paused = TRUE
- addtimer(CALLBACK(src, .proc/actually_explode), 100)
+ addtimer(CALLBACK(src, .proc/actually_explode), 10 SECONDS)
/obj/machinery/nuclearbomb/proc/actually_explode()
if(!core)
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index c59bb499404..442c28f3aa5 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -837,11 +837,12 @@
name = "Bluespace Artillery Parts"
desc = "The pride of Nanotrasen Naval Command. The legendary Bluespace Artillery Cannon is a devastating feat of human engineering and testament to wartime determination. Highly advanced research is required for proper construction. "
cost = CARGO_CRATE_VALUE * 30
- special = TRUE
+ special = FALSE //SKYRAT EDIT CHANGE
access_view = ACCESS_HEADS
contains = list(/obj/item/circuitboard/machine/bsa/front,
/obj/item/circuitboard/machine/bsa/middle,
/obj/item/circuitboard/machine/bsa/back,
+ /obj/item/circuitboard/machine/bsa/powercore, //SKYRAT EDIT ADDITION
/obj/item/circuitboard/computer/bsa_control
)
crate_name= "bluespace artillery parts crate"
diff --git a/code/modules/events/anomaly_bluespace.dm b/code/modules/events/anomaly_bluespace.dm
index 23a2a1968a8..80e7b1176ae 100644
--- a/code/modules/events/anomaly_bluespace.dm
+++ b/code/modules/events/anomaly_bluespace.dm
@@ -11,4 +11,4 @@
anomaly_path = /obj/effect/anomaly/bluespace
/datum/round_event/anomaly/anomaly_bluespace/announce(fake)
- priority_announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
+ priority_announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", ANNOUNCER_VORTEXANOMALIES)
diff --git a/code/modules/events/anomaly_flux.dm b/code/modules/events/anomaly_flux.dm
index 4737ad9bb41..2452719c992 100644
--- a/code/modules/events/anomaly_flux.dm
+++ b/code/modules/events/anomaly_flux.dm
@@ -12,4 +12,4 @@
anomaly_path = /obj/effect/anomaly/flux
/datum/round_event/anomaly/anomaly_flux/announce(fake)
- priority_announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
+ priority_announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", ANNOUNCER_FLUXANOMALIES) //SKYRAT EDIT CHANGE
diff --git a/code/modules/events/anomaly_grav.dm b/code/modules/events/anomaly_grav.dm
index c337b94b8a7..e56f6241a05 100644
--- a/code/modules/events/anomaly_grav.dm
+++ b/code/modules/events/anomaly_grav.dm
@@ -23,4 +23,4 @@
anomaly_path = /obj/effect/anomaly/grav/high
/datum/round_event/anomaly/anomaly_grav/announce(fake)
- priority_announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
+ priority_announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", ANNOUNCER_GRAVANOMALIES) //SKYRAT EDIT CHANGE
diff --git a/code/modules/events/anomaly_pyro.dm b/code/modules/events/anomaly_pyro.dm
index 29c6e15d282..d04a5a991c0 100644
--- a/code/modules/events/anomaly_pyro.dm
+++ b/code/modules/events/anomaly_pyro.dm
@@ -11,4 +11,4 @@
anomaly_path = /obj/effect/anomaly/pyro
/datum/round_event/anomaly/anomaly_pyro/announce(fake)
- priority_announce("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
+ priority_announce("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", ANNOUNCER_PYROANOMALIES) //SKYRAT EDIT CHANGE
diff --git a/code/modules/events/anomaly_vortex.dm b/code/modules/events/anomaly_vortex.dm
index feb32ff13cd..9d923949bca 100644
--- a/code/modules/events/anomaly_vortex.dm
+++ b/code/modules/events/anomaly_vortex.dm
@@ -12,4 +12,4 @@
anomaly_path = /obj/effect/anomaly/bhole
/datum/round_event/anomaly/anomaly_vortex/announce(fake)
- priority_announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
+ priority_announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert", ANNOUNCER_VORTEXANOMALIES)
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index 401872db253..dd6a6dd4dc7 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -30,7 +30,7 @@
source = initial(example.name)
else if(originMachine)
source = originMachine.name
- priority_announce("Rampant brand intelligence has been detected aboard [station_name()]. Please stand by. The origin is believed to be \a [source].", "Machine Learning Alert")
+ priority_announce("Rampant brand intelligence has been detected aboard [station_name()]. Please stand by. The origin is believed to be \a [source].", "Machine Learning Alert", ANNOUNCER_BRANDINTELLIGENCE) //SKYRAT EDIT CHANGE
/datum/round_event/brand_intelligence/start()
for(var/obj/machinery/vending/V in GLOB.machines)
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index a8cb9867be1..32e2e308091 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -24,7 +24,7 @@
startWhen = rand(40, 60)
/datum/round_event/carp_migration/announce(fake)
- priority_announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
+ priority_announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert", ANNOUNCER_CARP)
/datum/round_event/carp_migration/start()
diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm
index 3ad325f9005..8e9d291df71 100644
--- a/code/modules/events/communications_blackout.dm
+++ b/code/modules/events/communications_blackout.dm
@@ -18,7 +18,7 @@
to_chat(A, "
[alert]
")
if(prob(30) || fake) //most of the time, we don't want an announcement, so as to allow AIs to fake blackouts.
- priority_announce(alert)
+ priority_announce(alert, null, ANNOUNCER_COMMSBLACKOUT) //SKYRAT EDIT CHANGE
/datum/round_event/communications_blackout/start()
diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm
index 39b7039ed28..8fb58f21a17 100644
--- a/code/modules/events/electrical_storm.dm
+++ b/code/modules/events/electrical_storm.dm
@@ -12,7 +12,7 @@
announceWhen = 1
/datum/round_event/electrical_storm/announce(fake)
- priority_announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert")
+ priority_announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert", ANNOUNCER_ELECTRICALSTORM) //SKYRAT EDIT CHANGE
/datum/round_event/electrical_storm/start()
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index e4b38cf7828..7d218a0f5f2 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -372,6 +372,12 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
if(M.client)
shake_camera(M, 15, 1)
M.playsound_local(T, null, 100, 1, 0.5, S = alert_sound)
+ //SKYRAT EDIT ADDITON BEGIN
+ if(on)
+ priority_announce("GRAVITATIONAL SYSTEMS OPERATIONAL", "Gravity Generator", ANNOUNCER_GRAVGENON)
+ else
+ priority_announce("GRAVITATIONAL SYSTEMS FAILURE", "Gravity Generator", ANNOUNCER_GRAVGENOFF)
+ //SKYRAT EDIT END
/obj/machinery/gravity_generator/main/proc/gravity_in_level()
var/turf/T = get_turf(src)
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index 663a5b91833..1d92ed73b53 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -503,7 +503,7 @@
mode = SHUTTLE_ESCAPE
launch_status = ENDGAME_LAUNCHED
setTimer(SSshuttle.emergencyEscapeTime * engine_coeff)
- priority_announce("The Emergency Shuttle has left the station. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.", null, null, "Priority")
+ priority_announce("The Emergency Shuttle has left the station. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.", null, ANNOUNCER_SHUTTLELEFT, "Priority") //SKYRAT EDIT CHANGE - ANNOUNCER_SHUTTLELEFT
INVOKE_ASYNC(SSticker, /datum/controller/subsystem/ticker.proc/poll_hearts)
SSmapping.mapvote() //If no map vote has been run yet, start one.
diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm
index 96d7b4568f7..f75cd18c5d3 100644
--- a/code/modules/station_goals/bsa.dm
+++ b/code/modules/station_goals/bsa.dm
@@ -1,3 +1,4 @@
+/* SKYRAT EDIT REMOVAL - MOVED TO MODULAR BSA_OVERHAUL
// Crew has to build a bluespace cannon
// Cargo orders part for high price
// Requires high amount of power
@@ -8,7 +9,6 @@
/datum/station_goal/bluespace_cannon/get_report()
return {"Our military presence is inadequate in your sector.
We need you to construct BSA-[rand(1,99)] Artillery position aboard your station.
-
Base parts are available for shipping via cargo.
-Nanotrasen Naval Command"}
@@ -334,3 +334,4 @@
qdel(centerpiece.back)
qdel(centerpiece)
return cannon
+*/
diff --git a/modular_skyrat/modules/alerts/code/default_announcer.dm b/modular_skyrat/modules/alerts/code/default_announcer.dm
new file mode 100644
index 00000000000..3bd9ecafa3d
--- /dev/null
+++ b/modular_skyrat/modules/alerts/code/default_announcer.dm
@@ -0,0 +1,38 @@
+/datum/centcom_announcer/default
+ welcome_sounds = list('modular_skyrat/modules/alerts/sound/ai/default/welcome.ogg')
+ alert_sounds = list('modular_skyrat/modules/alerts/sound/alert2.ogg')
+ command_report_sounds = list('modular_skyrat/modules/alerts/sound/ai/default/commandreport.ogg')
+ event_sounds = list(ANNOUNCER_AIMALF = 'sound/ai/default/aimalf.ogg',
+ ANNOUNCER_ALIENS = list('modular_skyrat/modules/alerts/sound/ai/default/lifesigns1.ogg', 'modular_skyrat/modules/alerts/sound/ai/default/lifesigns1.ogg', 'modular_skyrat/modules/alerts/sound/ai/default/lifesigns1.ogg'),
+ ANNOUNCER_ANIMES = 'sound/ai/default/animes.ogg',
+ ANNOUNCER_INTERCEPT = 'modular_skyrat/modules/alerts/sound/alert2.ogg',
+ ANNOUNCER_IONSTORM = 'modular_skyrat/modules/alerts/sound/ai/default/ionstorm.ogg',
+ ANNOUNCER_METEORS = list('modular_skyrat/modules/alerts/sound/ai/default/meteors1.ogg', 'modular_skyrat/modules/alerts/sound/ai/default/meteors2.ogg'),
+ ANNOUNCER_OUTBREAK5 = list('modular_skyrat/modules/alerts/sound/ai/default/outbreak5_1.ogg', 'modular_skyrat/modules/alerts/sound/ai/default/outbreak5_2.ogg'),
+ ANNOUNCER_OUTBREAK7 = 'modular_skyrat/modules/alerts/sound/ai/default/outbreak7.ogg',
+ ANNOUNCER_POWEROFF = list('modular_skyrat/modules/alerts/sound/ai/default/poweroff1.ogg', 'modular_skyrat/modules/alerts/sound/ai/default/poweroff2.ogg'),
+ ANNOUNCER_POWERON = 'modular_skyrat/modules/alerts/sound/ai/default/poweron.ogg',
+ ANNOUNCER_RADIATION = list('modular_skyrat/modules/alerts/sound/ai/default/radiation1.ogg', 'modular_skyrat/modules/alerts/sound/ai/default/radiation2.ogg', 'modular_skyrat/modules/alerts/sound/ai/default/radiation3.ogg'),
+ ANNOUNCER_RADIATIONPASSED = 'modular_skyrat/modules/alerts/sound/ai/default/radpassed.ogg',
+ ANNOUNCER_SHUTTLECALLED = 'modular_skyrat/modules/alerts/sound/ai/default/crew_s_called.ogg',
+ ANNOUNCER_SHUTTLEDOCK = 'modular_skyrat/modules/alerts/sound/ai/default/crew_s_docked.ogg',
+ ANNOUNCER_SHUTTLERECALLED = 'modular_skyrat/modules/alerts/sound/ai/default/crew_s_recalled.ogg',
+ ANNOUNCER_SHUTTLELEFT = 'modular_skyrat/modules/alerts/sound/ai/default/crew_s_left.ogg',
+ ANNOUNCER_GRAVANOMALIES= 'modular_skyrat/modules/alerts/sound/ai/default/gravanomalies.ogg',
+ ANNOUNCER_SPANOMALIES = 'modular_skyrat/modules/alerts/sound/ai/default/wormholes.ogg',
+ ANNOUNCER_VORTEXANOMALIES = 'modular_skyrat/modules/alerts/sound/ai/default/vortex.ogg',
+ ANNOUNCER_BSPACEANOMALIES = 'modular_skyrat/modules/alerts/sound/ai/default/blusp_anomalies.ogg',
+ ANNOUNCER_MASSIVEBSPACEANOMALIES = 'modular_skyrat/modules/alerts/sound/ai/default/mas-blu-spa_anomalies.ogg',
+ ANNOUNCER_FLUXANOMALIES = 'modular_skyrat/modules/alerts/sound/ai/default/flux.ogg',
+ ANNOUNCER_PYROANOMALIES = 'modular_skyrat/modules/alerts/sound/ai/default/pyr_anomalies.ogg',
+ ANNOUNCER_CARP = 'modular_skyrat/modules/alerts/sound/ai/default/carps.ogg',
+ ANNOUNCER_BLUESPACEARTY = 'modular_skyrat/modules/alerts/sound/ai/default/artillery.ogg',
+ ANNOUNCER_CAPTAIN = 'modular_skyrat/modules/alerts/sound/ai/default/announce.ogg',
+ ANNOUNCER_GRAVGENOFF = 'modular_skyrat/modules/alerts/sound/ai/default/gravityoff.ogg',
+ ANNOUNCER_GRAVGENON = 'modular_skyrat/modules/alerts/sound/ai/default/gravityon.ogg',
+ ANNOUNCER_GREYTIDE = 'modular_skyrat/modules/alerts/sound/ai/default/greytide.ogg',
+ ANNOUNCER_COMMSBLACKOUT = 'modular_skyrat/modules/alerts/sound/ai/default/commsblackout.ogg',
+ ANNOUNCER_ELECTRICALSTORM = 'modular_skyrat/modules/alerts/sound/ai/default/estorm.ogg',
+ ANNOUNCER_BRANDINTELLIGENCE = 'modular_skyrat/modules/alerts/sound/ai/default/rampant_brand_int.ogg',
+ ANNOUNCER_SPOOKY = 'modular_skyrat/modules/alerts/sound/ai/default/admin_horror_music.ogg',
+ ANNOUNCER_ERTYES = 'modular_skyrat/modules/alerts/sound/ai/default/yesert.ogg')
diff --git a/modular_skyrat/modules/alerts/code/priority_announce.dm b/modular_skyrat/modules/alerts/code/priority_announce.dm
new file mode 100644
index 00000000000..96019d48b7a
--- /dev/null
+++ b/modular_skyrat/modules/alerts/code/priority_announce.dm
@@ -0,0 +1,84 @@
+///Sends an announcement to all players and formats it accordingly. Use this for big bad shit.
+/proc/priority_announce(text, title = "", sound, type , sender_override, has_important_message)
+ if(!text)
+ return
+
+ var/announcement
+
+ if(!sound)
+ sound = SSstation.announcer.get_rand_alert_sound()
+ else if(SSstation.announcer.event_sounds[sound])
+ var/list/picked = SSstation.announcer.event_sounds[sound]
+ sound = pick(picked)
+
+ if(type == "Priority")
+ announcement += "
Priority Announcement
"
+ if (title && length(title) > 0)
+ announcement += "
[html_encode(title)]
"
+ else if(type == "Captain")
+ announcement += "Captain Announces
"
+ GLOB.news_network.SubmitArticle(html_encode(text), "Captain's Announcement", "Station Announcements", null)
+
+ else
+ if(!sender_override)
+ announcement += "[command_name()] Update
"
+ else
+ announcement += "[sender_override]
"
+ if (title && length(title) > 0)
+ announcement += "
[html_encode(title)]
"
+
+ if(!sender_override)
+ if(title == "")
+ GLOB.news_network.SubmitArticle(text, "Central Command Update", "Station Announcements", null)
+ else
+ GLOB.news_network.SubmitArticle(title + "
" + text, "Central Command", "Station Announcements", null)
+
+ ///If the announcer overrides alert messages, use that message.
+ if(SSstation.announcer.custom_alert_message && !has_important_message)
+ announcement += SSstation.announcer.custom_alert_message
+ else
+ announcement += "
[html_encode(text)]
"
+ announcement += "
"
+
+ var/s = sound(sound)
+ alert_sound_to_playing(s)
+ for(var/mob/M in GLOB.player_list)
+ if(!isnewplayer(M) && M.can_hear())
+ to_chat(M, announcement)
+
+/proc/print_command_report(text = "", title = null, announce=TRUE)
+ if(!title)
+ title = "Classified [command_name()] Update"
+
+ if(announce)
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", SSstation.announcer.get_rand_report_sound(), has_important_message = TRUE)
+
+ var/datum/comm_message/M = new
+ M.title = title
+ M.content = text
+
+ SScommunications.send_message(M)
+
+///This proc sends an announcement to all currently playing mobs. Use alert to send a more ominious BEEP. Generally used for updating people on minor things, such as CME locaiton. Use priority_announce for large announcements.
+/proc/minor_announce(message, title = "Attention:", alert, html_encode = TRUE, sound)
+ if(!message)
+ return
+
+ if (html_encode)
+ title = html_encode(title)
+ message = html_encode(message)
+
+ for(var/mob/M in GLOB.player_list)
+ if(!isnewplayer(M) && M.can_hear())
+ to_chat(M, "[title]
[message]
")
+
+ if(sound)
+ if(SSstation.announcer.event_sounds[sound])
+ var/list/picked = SSstation.announcer.event_sounds[sound]
+ sound = pick(picked)
+ alert_sound_to_playing(sound)
+
+ if(alert)
+ alert_sound_to_playing(sound('modular_skyrat/modules/alerts/sound/alert1.ogg'))
+ else
+ alert_sound_to_playing(sound('sound/misc/notice2.ogg'))
diff --git a/modular_skyrat/modules/alerts/code/set_security_level.dm b/modular_skyrat/modules/alerts/code/set_security_level.dm
index 704f225f3b2..b6869663848 100644
--- a/modular_skyrat/modules/alerts/code/set_security_level.dm
+++ b/modular_skyrat/modules/alerts/code/set_security_level.dm
@@ -1,6 +1,10 @@
-GLOBAL_VAR_INIT(gamma_looping, FALSE) //This is so we know if the gamma sound effect is currently playing
+GLOBAL_VAR_INIT(gamma_timer_id, null)
+GLOBAL_VAR_INIT(delta_timer_id, null)
+GLOBAL_VAR_INIT(sec_level_cooldown, FALSE)
#define GAMMA_LOOP_LENGTH 1236 //2.06 minutes in deciseconds
+#define DELTA_LOOP_LENGTH 8 SECONDS
+#define SET_SEC_LEVEL_COOLDOWN 5 SECONDS
/proc/set_security_level(level)
level = isnum(level) ? level : seclevel2num(level)
@@ -9,41 +13,16 @@ GLOBAL_VAR_INIT(gamma_looping, FALSE) //This is so we know if the gamma sound ef
//Will not be announced if you try to set to the same level as it already is
if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_GAMMA && level != GLOB.security_level)
- switch(level)
- if(SEC_LEVEL_GREEN)
- minor_announce(CONFIG_GET(string/alert_green), "Attention! Alert level lowered to green:")
- if(SEC_LEVEL_BLUE)
- if(GLOB.security_level < SEC_LEVEL_BLUE)
- minor_announce(CONFIG_GET(string/alert_blue_upto), "Attention! Alert level elevated to blue:",1)
- else
- minor_announce(CONFIG_GET(string/alert_blue_downto), "Attention! Alert level lowered to blue:")
- if(SEC_LEVEL_VIOLET)
- if(GLOB.security_level < SEC_LEVEL_VIOLET)
- minor_announce(CONFIG_GET(string/alert_violet_upto), "Attention! Alert level set to violet:",1)
- else
- minor_announce(CONFIG_GET(string/alert_violet_downto), "Attention! Alert level set to violet:")
- if(SEC_LEVEL_ORANGE)
- if(GLOB.security_level < SEC_LEVEL_ORANGE)
- minor_announce(CONFIG_GET(string/alert_orange_upto), "Attention! Alert level set to orange:",1)
- else
- minor_announce(CONFIG_GET(string/alert_orange_downto), "Attention! Alert level set to orange:")
- if(SEC_LEVEL_AMBER)
- if(GLOB.security_level < SEC_LEVEL_AMBER)
- minor_announce(CONFIG_GET(string/alert_amber_upto), "Attention! Alert level set to amber:",1)
- else
- minor_announce(CONFIG_GET(string/alert_amber_downto), "Attention! Alert level set to amber:")
- if(SEC_LEVEL_RED)
- if(GLOB.security_level < SEC_LEVEL_RED)
- minor_announce(CONFIG_GET(string/alert_red_upto), "Attention! Code red!",1)
- else
- minor_announce(CONFIG_GET(string/alert_red_downto), "Attention! Code red!")
- if(SEC_LEVEL_DELTA)
- if(GLOB.security_level < SEC_LEVEL_DELTA)
- minor_announce(CONFIG_GET(string/alert_delta_upto), "Attention! Delta Alert level reached!",1)
- else
- minor_announce(CONFIG_GET(string/alert_delta_downto), "Attention! Delta Alert level reached!",1)
- if(SEC_LEVEL_GAMMA)
- minor_announce(CONFIG_GET(string/alert_gamma), "Attention! ZK-Class Reality Failure Scenario Detected, GAMMA Alert Level Reached!",1)
+ if(GLOB.sec_level_cooldown)
+ message_admins("Attempt made to change security level while in cooldown!")
+ return "COOLDOWN"
+ if(GLOB.delta_timer_id)
+ deltimer(GLOB.delta_timer_id)
+ GLOB.delta_timer_id = null
+ if(GLOB.gamma_timer_id)
+ deltimer(GLOB.gamma_timer_id)
+ GLOB.gamma_timer_id = null
+ announce_security_level(level) //IF YOU ARE ADDING A NEW SECURITY LEVEL, UPDATE THIS PROC
GLOB.security_level = level
for(var/obj/machinery/firealarm/FA in GLOB.machines)
if(is_station_level(FA.z))
@@ -61,10 +40,14 @@ GLOBAL_VAR_INIT(gamma_looping, FALSE) //This is so we know if the gamma sound ef
SSshuttle.emergency.modTimer(modTimer)
SSblackbox.record_feedback("tally", "security_level_changes", 1, get_security_level())
SSnightshift.check_nightshift()
- play_security_alert_sound(level)
+ GLOB.sec_level_cooldown = TRUE
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_sec_level_cooldown), SET_SEC_LEVEL_COOLDOWN)
else
return
+/proc/reset_sec_level_cooldown()
+ GLOB.sec_level_cooldown = FALSE
+
/proc/get_mod_timer(secLevel)
switch(secLevel)
if(SEC_LEVEL_GREEN)
@@ -141,40 +124,72 @@ GLOBAL_VAR_INIT(gamma_looping, FALSE) //This is so we know if the gamma sound ef
if("gamma")
return SEC_LEVEL_GAMMA
-/proc/play_security_alert_sound(level)
+/proc/announce_security_level(level)
switch(level)
+ if(SEC_LEVEL_GREEN)
+ minor_announce(CONFIG_GET(string/alert_green), "Attention! Alert level lowered to green:", sound = 'modular_skyrat/modules/alerts/sound/misc/downtoGREEN.ogg')
if(SEC_LEVEL_BLUE)
- alert_sound_to_playing('modular_skyrat/modules/alerts/sound/misc/voybluealert.ogg', volume = 50)
+ if(GLOB.security_level < SEC_LEVEL_BLUE)
+ minor_announce(CONFIG_GET(string/alert_blue_upto), "Attention! Alert level elevated to blue:", sound = 'modular_skyrat/modules/alerts/sound/misc/blue.ogg')
+ else
+ minor_announce(CONFIG_GET(string/alert_blue_downto), "Attention! Alert level lowered to blue:", sound = 'modular_skyrat/modules/alerts/sound/misc/downtoBLUE.ogg')
if(SEC_LEVEL_VIOLET)
- alert_sound_to_playing('modular_skyrat/modules/alerts/sound/misc/notice1.ogg', volume = 50)
+ if(GLOB.security_level < SEC_LEVEL_VIOLET)
+ minor_announce(CONFIG_GET(string/alert_violet_upto), "Attention! Alert level set to violet:", TRUE, sound = 'modular_skyrat/modules/alerts/sound/misc/voyalert.ogg')
+ else
+ minor_announce(CONFIG_GET(string/alert_violet_downto), "Attention! Alert level set to violet:", sound = 'modular_skyrat/modules/alerts/sound/misc/voyalert.ogg')
if(SEC_LEVEL_ORANGE)
- alert_sound_to_playing('modular_skyrat/modules/alerts/sound/misc/notice1.ogg', volume = 50)
+ if(GLOB.security_level < SEC_LEVEL_ORANGE)
+ minor_announce(CONFIG_GET(string/alert_orange_upto), "Attention! Alert level set to orange:", TRUE, sound = 'modular_skyrat/modules/alerts/sound/misc/voyalert.ogg')
+ else
+ minor_announce(CONFIG_GET(string/alert_orange_downto), "Attention! Alert level set to orange:", sound = 'modular_skyrat/modules/alerts/sound/misc/voyalert.ogg')
if(SEC_LEVEL_AMBER)
- alert_sound_to_playing('modular_skyrat/modules/alerts/sound/misc/notice1.ogg', volume = 50)
+ if(GLOB.security_level < SEC_LEVEL_AMBER)
+ minor_announce(CONFIG_GET(string/alert_amber_upto), "Attention! Alert level set to amber:", TRUE, sound = 'modular_skyrat/modules/alerts/sound/misc/voyalert.ogg')
+ else
+ minor_announce(CONFIG_GET(string/alert_amber_downto), "Attention! Alert level set to amber:", sound = 'modular_skyrat/modules/alerts/sound/misc/voyalert.ogg')
if(SEC_LEVEL_RED)
- alert_sound_to_playing('modular_skyrat/modules/alerts/sound/misc/redalert1.ogg', volume = 50)
+ if(GLOB.security_level < SEC_LEVEL_RED)
+ minor_announce(CONFIG_GET(string/alert_red_upto), "Attention! Code red!", TRUE, sound = 'modular_skyrat/modules/alerts/sound/misc/red.ogg')
+ else
+ minor_announce(CONFIG_GET(string/alert_red_downto), "Attention! Code red!", sound = 'modular_skyrat/modules/alerts/sound/misc/downtoRED.ogg')
if(SEC_LEVEL_DELTA)
- alert_sound_to_playing('modular_skyrat/modules/alerts/sound/misc/deltaklaxon.ogg')
+ if(GLOB.security_level < SEC_LEVEL_DELTA)
+ minor_announce(CONFIG_GET(string/alert_delta_upto), "Attention! Delta Alert level reached!", TRUE, sound = 'modular_skyrat/modules/alerts/sound/misc/delta.ogg')
+ else
+ minor_announce(CONFIG_GET(string/alert_delta_downto), "Attention! Delta Alert level reached!", TRUE, sound = 'modular_skyrat/modules/alerts/sound/misc/delta.ogg')
+ GLOB.security_level = level //Snowflake shit to make sue they actually loop.
+ delta_alarm()
if(SEC_LEVEL_GAMMA)
- if(!GLOB.gamma_looping)
- gamma_loop() //Gamma has a looping sound effect
+ minor_announce(CONFIG_GET(string/alert_gamma), "Attention! ZK-Class Reality Failure Scenario Detected, GAMMA Alert Level Reached!", TRUE, sound = 'modular_skyrat/modules/alerts/sound/misc/gamma_alert.ogg')
+ GLOB.security_level = level
+ gamma_loop()
-/proc/alert_sound_to_playing(soundin, volume = 100, vary = FALSE, frequency = 0, falloff = FALSE, channel = 0, pressure_affected = FALSE, sound/S)
+/proc/delta_alarm() //Delta alarm sounds every so often
+ if(GLOB.security_level == SEC_LEVEL_DELTA)
+ alert_sound_to_playing('modular_skyrat/modules/alerts/sound/alarm_delta.ogg')
+ GLOB.delta_timer_id = addtimer(CALLBACK(GLOBAL_PROC, .proc/delta_alarm), DELTA_LOOP_LENGTH, TIMER_UNIQUE | TIMER_STOPPABLE)
+
+/proc/gamma_loop() //Loops gamma sound
+ if(GLOB.security_level == SEC_LEVEL_GAMMA)
+ alert_sound_to_playing('modular_skyrat/modules/alerts/sound/misc/gamma_alert.ogg')
+ GLOB.gamma_timer_id = addtimer(CALLBACK(GLOBAL_PROC, .proc/gamma_loop), GAMMA_LOOP_LENGTH, TIMER_UNIQUE | TIMER_STOPPABLE)
+
+///This is quite franlky the most important proc relating to global sounds, it uses area definition to play sounds depending on your location, and respects the players announcement volume. Generally if you're sending an announcement you want to use priority_announce.
+/proc/alert_sound_to_playing(soundin, vary = FALSE, frequency = 0, falloff = FALSE, channel = 0, pressure_affected = FALSE, sound/S)
if(!S)
S = sound(get_sfx(soundin))
+ var/list/quiet_areas = typecacheof(typesof(/area/maintenance) + typesof(/area/space) + typesof(/area/commons/dorms))
for(var/m in GLOB.player_list)
if(ismob(m) && !isnewplayer(m))
var/mob/M = m
- if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS)
- M.playsound_local(M, null, volume, vary, frequency, falloff, channel, pressure_affected, S)
-
-//ALERT ALERT ALERT SHITCODE
-/proc/gamma_loop() //Loops gamma sound
- if(GLOB.security_level != SEC_LEVEL_GAMMA)
- GLOB.gamma_looping = FALSE
- return
- GLOB.gamma_looping = TRUE
- alert_sound_to_playing('modular_skyrat/modules/alerts/sound/misc/gamma_alert.ogg')
- addtimer(CALLBACK(.proc/gamma_loop), GAMMA_LOOP_LENGTH)
+ if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS && M.can_hear())
+ var/area/A = get_area(M)
+ if(is_type_in_typecache(A, quiet_areas)) //These areas don't hear it as loudly
+ M.playsound_local(get_turf(M), S, min(10, M.client.prefs.announcement_volume), FALSE)
+ else
+ M.playsound_local(get_turf(M), S, M.client.prefs.announcement_volume, FALSE)
#undef GAMMA_LOOP_LENGTH
+#undef SET_SEC_LEVEL_COOLDOWN
+#undef DELTA_LOOP_LENGTH
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/DeltaBOOM.ogg b/modular_skyrat/modules/alerts/sound/ai/default/DeltaBOOM.ogg
new file mode 100644
index 00000000000..8a6200bd8b5
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/DeltaBOOM.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/admin_horror_music.ogg b/modular_skyrat/modules/alerts/sound/ai/default/admin_horror_music.ogg
new file mode 100644
index 00000000000..b8a6139605c
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/admin_horror_music.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/aimalf.ogg b/modular_skyrat/modules/alerts/sound/ai/default/aimalf.ogg
new file mode 100644
index 00000000000..b7996916b47
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/aimalf.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/animes.ogg b/modular_skyrat/modules/alerts/sound/ai/default/animes.ogg
new file mode 100644
index 00000000000..a46a207edc4
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/animes.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/announce.ogg b/modular_skyrat/modules/alerts/sound/ai/default/announce.ogg
new file mode 100644
index 00000000000..c5b9251e91a
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/announce.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/artillery.ogg b/modular_skyrat/modules/alerts/sound/ai/default/artillery.ogg
new file mode 100644
index 00000000000..dc14ed60d6f
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/artillery.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/attention.ogg b/modular_skyrat/modules/alerts/sound/ai/default/attention.ogg
new file mode 100644
index 00000000000..912be4425eb
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/attention.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/blusp_anomalies.ogg b/modular_skyrat/modules/alerts/sound/ai/default/blusp_anomalies.ogg
new file mode 100644
index 00000000000..52ec5ddb115
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/blusp_anomalies.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/carps.ogg b/modular_skyrat/modules/alerts/sound/ai/default/carps.ogg
new file mode 100644
index 00000000000..9edbe1f2988
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/carps.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/commandreport.ogg b/modular_skyrat/modules/alerts/sound/ai/default/commandreport.ogg
new file mode 100644
index 00000000000..de4b75f75e2
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/commandreport.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/commsblackout.ogg b/modular_skyrat/modules/alerts/sound/ai/default/commsblackout.ogg
new file mode 100644
index 00000000000..b7fdbd952f3
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/commsblackout.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/crew_s_called.ogg b/modular_skyrat/modules/alerts/sound/ai/default/crew_s_called.ogg
new file mode 100644
index 00000000000..c73da2e66d3
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/crew_s_called.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/crew_s_docked.ogg b/modular_skyrat/modules/alerts/sound/ai/default/crew_s_docked.ogg
new file mode 100644
index 00000000000..bfd664340a8
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/crew_s_docked.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/crew_s_left.ogg b/modular_skyrat/modules/alerts/sound/ai/default/crew_s_left.ogg
new file mode 100644
index 00000000000..4c4168d478c
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/crew_s_left.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/crew_s_recalled.ogg b/modular_skyrat/modules/alerts/sound/ai/default/crew_s_recalled.ogg
new file mode 100644
index 00000000000..6838ee47ec3
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/crew_s_recalled.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/estorm.ogg b/modular_skyrat/modules/alerts/sound/ai/default/estorm.ogg
new file mode 100644
index 00000000000..7361ba1810c
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/estorm.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/flux.ogg b/modular_skyrat/modules/alerts/sound/ai/default/flux.ogg
new file mode 100644
index 00000000000..938526b9946
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/flux.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/gravanomalies.ogg b/modular_skyrat/modules/alerts/sound/ai/default/gravanomalies.ogg
new file mode 100644
index 00000000000..201f571e206
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/gravanomalies.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/gravityoff.ogg b/modular_skyrat/modules/alerts/sound/ai/default/gravityoff.ogg
new file mode 100644
index 00000000000..4b5f295b11f
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/gravityoff.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/gravityon.ogg b/modular_skyrat/modules/alerts/sound/ai/default/gravityon.ogg
new file mode 100644
index 00000000000..c3707962b5b
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/gravityon.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/greytide.ogg b/modular_skyrat/modules/alerts/sound/ai/default/greytide.ogg
new file mode 100644
index 00000000000..79918bd5216
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/greytide.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/intercept.ogg b/modular_skyrat/modules/alerts/sound/ai/default/intercept.ogg
new file mode 100644
index 00000000000..3569a07d401
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/intercept.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/ionstorm.ogg b/modular_skyrat/modules/alerts/sound/ai/default/ionstorm.ogg
new file mode 100644
index 00000000000..f3c8a1dc040
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/ionstorm.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/lifesigns1.ogg b/modular_skyrat/modules/alerts/sound/ai/default/lifesigns1.ogg
new file mode 100644
index 00000000000..000f3834559
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/lifesigns1.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/lifesigns2.ogg b/modular_skyrat/modules/alerts/sound/ai/default/lifesigns2.ogg
new file mode 100644
index 00000000000..6bdb9b29ae9
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/lifesigns2.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/lifesigns3.ogg b/modular_skyrat/modules/alerts/sound/ai/default/lifesigns3.ogg
new file mode 100644
index 00000000000..910471d6bf0
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/lifesigns3.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/mas-blu-spa_anomalies.ogg b/modular_skyrat/modules/alerts/sound/ai/default/mas-blu-spa_anomalies.ogg
new file mode 100644
index 00000000000..27072e54abc
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/mas-blu-spa_anomalies.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/meteors.ogg b/modular_skyrat/modules/alerts/sound/ai/default/meteors.ogg
new file mode 100644
index 00000000000..8f1c3aeacbb
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/meteors.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/meteors1.ogg b/modular_skyrat/modules/alerts/sound/ai/default/meteors1.ogg
new file mode 100644
index 00000000000..fea2d79cfa9
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/meteors1.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/meteors2.ogg b/modular_skyrat/modules/alerts/sound/ai/default/meteors2.ogg
new file mode 100644
index 00000000000..1179383a327
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/meteors2.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/noert.ogg b/modular_skyrat/modules/alerts/sound/ai/default/noert.ogg
new file mode 100644
index 00000000000..03d615e4017
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/noert.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/outbreak5_1.ogg b/modular_skyrat/modules/alerts/sound/ai/default/outbreak5_1.ogg
new file mode 100644
index 00000000000..569ff788ed0
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/outbreak5_1.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/outbreak5_2.ogg b/modular_skyrat/modules/alerts/sound/ai/default/outbreak5_2.ogg
new file mode 100644
index 00000000000..b8e66a17c05
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/outbreak5_2.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/outbreak7.ogg b/modular_skyrat/modules/alerts/sound/ai/default/outbreak7.ogg
new file mode 100644
index 00000000000..fae4a0ccf0f
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/outbreak7.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/poweroff1.ogg b/modular_skyrat/modules/alerts/sound/ai/default/poweroff1.ogg
new file mode 100644
index 00000000000..251065f3311
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/poweroff1.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/poweroff2.ogg b/modular_skyrat/modules/alerts/sound/ai/default/poweroff2.ogg
new file mode 100644
index 00000000000..8b52c9d8b51
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/poweroff2.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/poweron.ogg b/modular_skyrat/modules/alerts/sound/ai/default/poweron.ogg
new file mode 100644
index 00000000000..18f303d1e71
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/poweron.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/pyr_anomalies.ogg b/modular_skyrat/modules/alerts/sound/ai/default/pyr_anomalies.ogg
new file mode 100644
index 00000000000..f4786029c75
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/pyr_anomalies.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/radiation1.ogg b/modular_skyrat/modules/alerts/sound/ai/default/radiation1.ogg
new file mode 100644
index 00000000000..c789c8c5180
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/radiation1.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/radiation2.ogg b/modular_skyrat/modules/alerts/sound/ai/default/radiation2.ogg
new file mode 100644
index 00000000000..d3c4622105f
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/radiation2.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/radiation3.ogg b/modular_skyrat/modules/alerts/sound/ai/default/radiation3.ogg
new file mode 100644
index 00000000000..d3a21f3ab57
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/radiation3.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/radpassed.ogg b/modular_skyrat/modules/alerts/sound/ai/default/radpassed.ogg
new file mode 100644
index 00000000000..4079df7a2ee
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/radpassed.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/rampant_brand_int.ogg b/modular_skyrat/modules/alerts/sound/ai/default/rampant_brand_int.ogg
new file mode 100644
index 00000000000..db0e136d6b2
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/rampant_brand_int.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/shuttlerecalled.ogg b/modular_skyrat/modules/alerts/sound/ai/default/shuttlerecalled.ogg
new file mode 100644
index 00000000000..5f6db404b87
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/shuttlerecalled.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/vortex.ogg b/modular_skyrat/modules/alerts/sound/ai/default/vortex.ogg
new file mode 100644
index 00000000000..6f9554f5445
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/vortex.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/welcome.ogg b/modular_skyrat/modules/alerts/sound/ai/default/welcome.ogg
new file mode 100644
index 00000000000..5573dc04fef
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/welcome.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/wormholes.ogg b/modular_skyrat/modules/alerts/sound/ai/default/wormholes.ogg
new file mode 100644
index 00000000000..efeb92d498f
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/wormholes.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/ai/default/yesert.ogg b/modular_skyrat/modules/alerts/sound/ai/default/yesert.ogg
new file mode 100644
index 00000000000..1cd543509f1
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/ai/default/yesert.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/alarm_delta.ogg b/modular_skyrat/modules/alerts/sound/alarm_delta.ogg
new file mode 100644
index 00000000000..c93fd01417b
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/alarm_delta.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/alert1.ogg b/modular_skyrat/modules/alerts/sound/alert1.ogg
new file mode 100644
index 00000000000..f99508e5c1b
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/alert1.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/alert2.ogg b/modular_skyrat/modules/alerts/sound/alert2.ogg
new file mode 100644
index 00000000000..9dfc96a4f82
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/alert2.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/alert3.ogg b/modular_skyrat/modules/alerts/sound/alert3.ogg
new file mode 100644
index 00000000000..5d0ef5c3c12
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/alert3.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/misc/blue.ogg b/modular_skyrat/modules/alerts/sound/misc/blue.ogg
new file mode 100644
index 00000000000..a55d6d1bddd
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/misc/blue.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/misc/delta.ogg b/modular_skyrat/modules/alerts/sound/misc/delta.ogg
new file mode 100644
index 00000000000..1798ad084f8
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/misc/delta.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/misc/downtoBLUE.ogg b/modular_skyrat/modules/alerts/sound/misc/downtoBLUE.ogg
new file mode 100644
index 00000000000..a4798b36a63
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/misc/downtoBLUE.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/misc/downtoGREEN.ogg b/modular_skyrat/modules/alerts/sound/misc/downtoGREEN.ogg
new file mode 100644
index 00000000000..d08d880d010
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/misc/downtoGREEN.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/misc/downtoRED.ogg b/modular_skyrat/modules/alerts/sound/misc/downtoRED.ogg
new file mode 100644
index 00000000000..f2c781c54ae
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/misc/downtoRED.ogg differ
diff --git a/modular_skyrat/modules/alerts/sound/misc/red.ogg b/modular_skyrat/modules/alerts/sound/misc/red.ogg
new file mode 100644
index 00000000000..95defa75aa8
Binary files /dev/null and b/modular_skyrat/modules/alerts/sound/misc/red.ogg differ
diff --git a/modular_skyrat/modules/bsa_overhaul/code/bsa_cannon.dm b/modular_skyrat/modules/bsa_overhaul/code/bsa_cannon.dm
new file mode 100644
index 00000000000..8611fbcc947
--- /dev/null
+++ b/modular_skyrat/modules/bsa_overhaul/code/bsa_cannon.dm
@@ -0,0 +1,362 @@
+// Crew has to build a bluespace cannon
+// Cargo orders part for high price
+// Requires high amount of power
+// Requires high level stock parts
+
+#define SYSTEM_OFFLINE "SYSTEM OFFLINE"
+#define SYSTEM_READY "SYSTEM READY"
+#define SYSTEM_PREFIRE "SYSTEM PREFIRING"
+#define SYSTEM_FIRING "SYSTEM FIRING"
+#define SYSTEM_RELOADING "SYSTEM RELOADING"
+#define SYSTEM_INTERRUPTED "SYSTEM INTERRUPTED"
+
+#define SUPERWEAPON_RELOAD_TIME 30 SECONDS
+
+/datum/station_goal/bluespace_cannon
+ name = "Bluespace Artillery"
+
+/datum/station_goal/bluespace_cannon/get_report()
+ return {"Our military presence is inadequate in your sector.
+ We need you to construct BSA-[rand(1,99)] Artillery position aboard your station.
+
+ Base parts are available for shipping via cargo.
+ -Nanotrasen Naval Command"}
+
+/datum/station_goal/bluespace_cannon/check_completion()
+ if(..())
+ return TRUE
+ var/obj/machinery/bsa/full/B = locate()
+ if(B && !B.machine_stat)
+ return TRUE
+ return FALSE
+
+/obj/machinery/bsa
+ icon = 'icons/obj/machines/particle_accelerator.dmi'
+ density = TRUE
+ anchored = TRUE
+
+/obj/machinery/bsa/wrench_act(mob/living/user, obj/item/I)
+ ..()
+ default_unfasten_wrench(user, I, 10)
+ return TRUE
+
+/obj/machinery/bsa/back
+ name = "Bluespace Artillery Generator"
+ desc = "Generates cannon pulse. Needs to be linked with a fusor."
+ icon_state = "power_box"
+
+/obj/machinery/bsa/back/multitool_act(mob/living/user, obj/item/I)
+ if(!multitool_check_buffer(user, I)) //make sure it has a data buffer
+ return
+ var/obj/item/multitool/M = I
+ M.buffer = src
+ to_chat(user, "You store linkage information in [I]'s buffer.")
+ return TRUE
+
+/obj/machinery/bsa/front
+ name = "Bluespace Artillery Bore"
+ desc = "Do not stand in front of cannon during operation. Needs to be linked with a fusor."
+ icon_state = "emitter_center"
+
+/obj/machinery/bsa/front/multitool_act(mob/living/user, obj/item/I)
+ if(!multitool_check_buffer(user, I)) //make sure it has a data buffer
+ return
+ var/obj/item/multitool/M = I
+ M.buffer = src
+ to_chat(user, "You store linkage information in [I]'s buffer.")
+ return TRUE
+
+/obj/machinery/bsa/middle
+ name = "Bluespace Artillery Fusor"
+ desc = "Contents classified by Nanotrasen Naval Command. Needs to be linked with the other BSA parts using a multitool."
+ icon_state = "fuel_chamber"
+ var/obj/machinery/bsa/back/back
+ var/obj/machinery/bsa/front/front
+
+/obj/machinery/bsa/middle/multitool_act(mob/living/user, obj/item/I)
+ if(!multitool_check_buffer(user, I))
+ return
+ var/obj/item/multitool/M = I
+ if(M.buffer)
+ if(istype(M.buffer, /obj/machinery/bsa/back))
+ back = M.buffer
+ M.buffer = null
+ to_chat(user, "You link [src] with [back].")
+ else if(istype(M.buffer, /obj/machinery/bsa/front))
+ front = M.buffer
+ M.buffer = null
+ to_chat(user, "You link [src] with [front].")
+ else
+ to_chat(user, "[I]'s data buffer is empty!")
+ return TRUE
+
+/obj/machinery/bsa/middle/proc/check_completion()
+ if(!front || !back)
+ return "No linked parts detected!"
+ if(!front.anchored || !back.anchored || !anchored)
+ return "Linked parts unwrenched!"
+ if(front.y != y || back.y != y || !(front.x > x && back.x < x || front.x < x && back.x > x) || front.z != z || back.z != z)
+ return "Parts misaligned!"
+ if(!has_space())
+ return "Not enough free space!"
+
+/obj/machinery/bsa/middle/proc/has_space()
+ var/cannon_dir = get_cannon_direction()
+ var/x_min
+ var/x_max
+ switch(cannon_dir)
+ if(EAST)
+ x_min = x - 4 //replace with defines later
+ x_max = x + 6
+ if(WEST)
+ x_min = x + 4
+ x_max = x - 6
+
+ for(var/turf/T in block(locate(x_min,y-1,z),locate(x_max,y+1,z)))
+ if(T.density || isspaceturf(T))
+ return FALSE
+ return TRUE
+
+/obj/machinery/bsa/middle/proc/get_cannon_direction()
+ if(front.x > x && back.x < x)
+ return EAST
+ else if(front.x < x && back.x > x)
+ return WEST
+
+/obj/machinery/bsa/full
+ name = "Bluespace Artillery"
+ desc = "Long range bluespace artillery."
+ icon = 'icons/obj/lavaland/cannon.dmi'
+ icon_state = "orbital_cannon1"
+ var/static/mutable_appearance/top_layer
+ use_power = NO_POWER_USE
+ var/ex_power = 5
+ var/power_used_per_shot = 20000000 //enough to kil standard apc - todo : make this use wires instead and scale explosion power with it
+ var/ready
+ var/system_state = SYSTEM_OFFLINE
+ max_integrity = 2000
+ var/obj/machinery/computer/bsa_control/control_unit
+ pixel_y = -32
+ pixel_x = -192
+ bound_width = 352
+ bound_x = -192
+ appearance_flags = NONE //Removes default TILE_BOUND
+
+/obj/machinery/bsa/full/wrench_act(mob/living/user, obj/item/I)
+ return FALSE
+
+/obj/machinery/bsa/full/proc/get_front_turf()
+ switch(dir)
+ if(WEST)
+ return locate(x - 7,y,z)
+ if(EAST)
+ return locate(x + 7,y,z)
+ return get_turf(src)
+
+/obj/machinery/bsa/full/proc/get_back_turf()
+ switch(dir)
+ if(WEST)
+ return locate(x + 5,y,z)
+ if(EAST)
+ return locate(x - 5,y,z)
+ return get_turf(src)
+
+/obj/machinery/bsa/full/proc/get_target_turf()
+ switch(dir)
+ if(WEST)
+ return locate(1,y,z)
+ if(EAST)
+ return locate(world.maxx,y,z)
+ return get_turf(src)
+
+/obj/machinery/bsa/full/Initialize(mapload, cannon_direction = WEST)
+ . = ..()
+ top_layer = top_layer || mutable_appearance(icon, layer = ABOVE_MOB_LAYER)
+ switch(cannon_direction)
+ if(WEST)
+ setDir(WEST)
+ top_layer.icon_state = "top_west"
+ icon_state = "cannon_west"
+ if(EAST)
+ setDir(EAST)
+ pixel_x = -128
+ bound_x = -128
+ top_layer.icon_state = "top_east"
+ icon_state = "cannon_east"
+ add_overlay(top_layer)
+ reload()
+
+/obj/machinery/bsa/full/proc/pre_fire(mob/user, turf/bullseye)
+ if(system_state == SYSTEM_READY)
+ priority_announce("BLUESPACE TARGETING PARAMETERS SET, PREIGNITION STARTING... FIRING IN T-20 SECONDS!", "BLUESPACE ARTILLERY", ANNOUNCER_BLUESPACEARTY)
+ alert_sound_to_playing('modular_skyrat/modules/bsa_overhaul/sound/superlaser_prefire.ogg')
+ system_state = SYSTEM_PREFIRE
+ message_admins("[user] has started the fire cycle of [src]!")
+ set_light(5, 5, COLOR_BLUE_LIGHT)
+ addtimer(CALLBACK(src, .proc/fire, user, bullseye), 15 SECONDS)
+ START_PROCESSING(SSobj, src)
+ return system_state
+
+/obj/machinery/bsa/full/process()
+ if(system_state == SYSTEM_PREFIRE) //We drain this while either action is being performed.
+ if(isnull(control_unit.core))
+ system_state = SYSTEM_INTERRUPTED
+ STOP_PROCESSING(SSobj, src)
+ var/obj/structure/cable/attached = control_unit.core.attached
+ var/datum/powernet/PN = attached.powernet
+ if(PN)
+ // found a powernet, so drain up to max power from it
+ var/drained = min(power_used_per_shot, attached.newavail())
+ attached.add_delayedload(drained)
+ // if tried to drain more than available on powernet
+ // now look for APCs and drain their cells
+ if(drained < power_used_per_shot)
+ for(var/obj/machinery/power/terminal/T in PN.nodes)
+ if(istype(T.master, /obj/machinery/power/apc))
+ var/obj/machinery/power/apc/A = T.master
+ if(A.operating && A.cell)
+ A.cell.charge = max(0, A.cell.charge - 50)
+ if(A.charging == 2) // If the cell was full
+ A.charging = 1 // It's no longer full
+ if(drained >= power_used_per_shot)
+ break
+ else
+ system_state = SYSTEM_INTERRUPTED
+ STOP_PROCESSING(SSobj, src)
+ else
+ STOP_PROCESSING(SSobj, src)
+
+/obj/machinery/bsa/full/proc/fire(mob/user, turf/bullseye)
+ if(!system_state == SYSTEM_PREFIRE || !control_unit.core || machine_stat)
+ minor_announce("BLUESPACE ARTILLERY FIRE FAILURE!", "BLUESPACE ARTILLERY", TRUE)
+ system_state = SYSTEM_READY
+ return
+ system_state = SYSTEM_FIRING
+ reload()
+ use_power(power_used_per_shot)
+ var/turf/point = get_front_turf()
+ var/turf/target = get_target_turf()
+ var/atom/movable/blocker
+ for(var/T in getline(get_step(point, dir), target))
+ var/turf/tile = T
+ if(SEND_SIGNAL(tile, COMSIG_ATOM_BSA_BEAM) & COMSIG_ATOM_BLOCKS_BSA_BEAM)
+ blocker = tile
+ else
+ for(var/AM in tile)
+ var/atom/movable/stuff = AM
+ if(SEND_SIGNAL(stuff, COMSIG_ATOM_BSA_BEAM) & COMSIG_ATOM_BLOCKS_BSA_BEAM)
+ blocker = stuff
+ break
+ if(blocker)
+ target = tile
+ break
+ else
+ SSexplosions.highturf += tile //also fucks everything else on the turf
+ point.Beam(target, icon_state = "bsa_beam", time = 5 SECONDS, maxdistance = world.maxx) //ZZZAP
+ new /obj/effect/temp_visual/bsa_splash(point, dir)
+
+ if(!blocker)
+ message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike targeting [ADMIN_VERBOSEJMP(bullseye)].")
+ log_game("[key_name(user)] has launched an artillery strike targeting [AREACOORD(bullseye)].")
+ minor_announce("BLUESPACE ARTILLERY FIRE SUCCESSFUL! DIRECT HIT!", "BLUESPACE ARTILLERY", TRUE)
+ explosion(bullseye, ex_power, ex_power*2, ex_power*4)
+ alert_sound_to_playing('modular_skyrat/modules/bsa_overhaul/sound/superlaser_firing.ogg')
+ else
+ message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike targeting [ADMIN_VERBOSEJMP(bullseye)] but it was blocked by [blocker] at [ADMIN_VERBOSEJMP(target)].")
+ log_game("[key_name(user)] has launched an artillery strike targeting [AREACOORD(bullseye)] but it was blocked by [blocker] at [AREACOORD(target)].")
+ minor_announce("BLUESPACE ARTILLERY FIRE FAILURE!", "BLUESPACE ARTILLERY", TRUE)
+
+/obj/machinery/bsa/full/proc/reload()
+ system_state = SYSTEM_RELOADING
+ set_light(0)
+ STOP_PROCESSING(SSobj, src)
+ addtimer(CALLBACK(src, .proc/ready_cannon), SUPERWEAPON_RELOAD_TIME)
+
+/obj/machinery/bsa/full/proc/ready_cannon()
+ system_state = SYSTEM_READY
+ STOP_PROCESSING(SSobj, src)
+
+/obj/machinery/bsa/full/Destroy()
+ control_unit.cannon = null
+ control_unit = null
+ . = ..()
+
+/obj/structure/filler
+ name = "big machinery part"
+ density = TRUE
+ anchored = TRUE
+ invisibility = INVISIBILITY_ABSTRACT
+ var/obj/machinery/parent
+
+/obj/structure/filler/ex_act()
+ return
+
+/obj/structure/filler/Destroy()
+ parent = null
+ . = ..()
+
+/obj/machinery/bsa_powercore
+ name = "artillery powercore"
+ desc = "A core that transfers power from the local power net and transfers it to nearby artillery pieces."
+ icon = 'modular_skyrat/modules/bsa_overhaul/icons/bsa_parts.dmi'
+ icon_state = "powercore_off"
+ density = TRUE
+ ///The attached power cable that the power core will SUCC energy from.
+ var/obj/machinery/computer/bsa_control/control_unit
+ var/obj/structure/cable/attached
+
+/obj/machinery/bsa_powercore/multitool_act(mob/living/user, obj/item/I)
+ if(!multitool_check_buffer(user, I)) //make sure it has a data buffer
+ return
+ var/obj/item/multitool/M = I
+ M.buffer = src
+ to_chat(user, "You store linkage information in [I]'s buffer.")
+ return TRUE
+
+/obj/machinery/bsa_powercore/wrench_act(mob/living/user, obj/item/I)
+ ..()
+ default_unfasten_wrench(user, I, 10)
+ if(anchored)
+ var/turf/T = loc
+ if(isturf(T) && !T.intact)
+ attached = locate() in T
+ if(!attached)
+ set_light(0)
+ to_chat(user, "[src] must be placed over an exposed, powered cable node!")
+ else
+ set_light(5)
+ to_chat(user, "You attach [src] to the cable below.")
+ else
+ attached = null
+ update_appearance()
+ return TRUE
+
+/obj/machinery/bsa_powercore/Destroy()
+ control_unit.core = null
+ control_unit = null
+ attached = null
+ . = ..()
+
+/obj/machinery/bsa_powercore/update_icon(updates)
+ . = ..()
+ if(attached)
+ icon_state = "powercore_on"
+ else
+ icon_state = "powercore_off"
+
+/obj/item/circuitboard/machine/bsa/powercore
+ name = "Bluespace Artillery Powercore (Machine Board)"
+ icon_state = "command"
+ build_path = /obj/machinery/bsa_powercore
+ req_components = list(
+ /obj/item/stock_parts/capacitor/quadratic = 5,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ /obj/item/stack/cable_coil = 2)
+
+#undef SYSTEM_OFFLINE
+#undef SYSTEM_READY
+#undef SYSTEM_PREFIRE
+#undef SYSTEM_FIRING
+#undef SYSTEM_RELOADING
+#undef SYSTEM_INTERRUPTED
+#undef SUPERWEAPON_RELOAD_TIME
diff --git a/modular_skyrat/modules/bsa_overhaul/code/bsa_computer.dm b/modular_skyrat/modules/bsa_overhaul/code/bsa_computer.dm
new file mode 100644
index 00000000000..9894834a4da
--- /dev/null
+++ b/modular_skyrat/modules/bsa_overhaul/code/bsa_computer.dm
@@ -0,0 +1,139 @@
+//CONTROL COMPUTER
+
+/obj/machinery/computer/bsa_control
+ name = "bluespace artillery control"
+ use_power = NO_POWER_USE
+ circuit = /obj/item/circuitboard/computer/bsa_control
+ icon = 'icons/obj/machines/particle_accelerator.dmi'
+ icon_state = "control_boxp"
+ var/obj/machinery/bsa_powercore/core //The moveable power core link
+ var/obj/machinery/bsa/full/cannon
+ var/notice
+ var/target
+ var/area_aim = FALSE //should also show areas for targeting
+
+/obj/machinery/computer/bsa_control/multitool_act(mob/living/user, obj/item/I)
+ if(!multitool_check_buffer(user, I))
+ return
+ var/obj/item/multitool/M = I
+ if(M.buffer)
+ if(istype(M.buffer, /obj/machinery/bsa_powercore))
+ if(!cannon)
+ to_chat(user, "There is no cannon linked to this control unit!")
+ return FALSE
+ if(core)
+ to_chat(user, "There is already a core linked to this control unit!")
+ return FALSE
+ core = M.buffer
+ core.control_unit = src
+ M.buffer = null
+ to_chat(user, "You link [src] with [core].")
+ else
+ to_chat(user, "[I]'s data buffer is empty!")
+ return TRUE
+
+/obj/machinery/computer/bsa_control/ui_state(mob/user)
+ return GLOB.physical_state
+
+/obj/machinery/computer/bsa_control/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "BluespaceArtillery", name)
+ ui.open()
+
+/obj/machinery/computer/bsa_control/ui_data()
+ var/list/data = list()
+ data["ready"] = cannon ? cannon.ready : FALSE
+ data["connected"] = cannon
+ data["notice"] = notice
+ data["unlocked"] = GLOB.bsa_unlock
+ if(target)
+ data["target"] = get_target_name()
+ return data
+
+/obj/machinery/computer/bsa_control/ui_act(action, params)
+ . = ..()
+ if(.)
+ return
+
+ switch(action)
+ if("build")
+ cannon = deploy()
+ . = TRUE
+ if("fire")
+ fire(usr)
+ . = TRUE
+ if("recalibrate")
+ calibrate(usr)
+ . = TRUE
+ update_appearance()
+
+/obj/machinery/computer/bsa_control/proc/calibrate(mob/user)
+ if(!GLOB.bsa_unlock)
+ return
+ var/list/gps_locators = list()
+ for(var/datum/component/gps/G in GLOB.GPS_list) //nulls on the list somehow
+ if(G.tracking)
+ gps_locators[G.gpstag] = G
+
+ var/list/options = gps_locators
+ if(area_aim)
+ options += GLOB.teleportlocs
+ var/V = input(user,"Select target", "Select target",null) in options|null
+ target = options[V]
+
+/obj/machinery/computer/bsa_control/proc/get_target_name()
+ if(istype(target, /area))
+ return get_area_name(target, TRUE)
+ else if(istype(target, /datum/component/gps))
+ var/datum/component/gps/G = target
+ return G.gpstag
+
+/obj/machinery/computer/bsa_control/proc/get_impact_turf()
+ if(istype(target, /area))
+ return pick(get_area_turfs(target))
+ else if(istype(target, /datum/component/gps))
+ var/datum/component/gps/G = target
+ return get_turf(G.parent)
+
+/obj/machinery/computer/bsa_control/proc/fire(mob/user)
+ if(!core)
+ notice = "Core not detected!"
+ return
+ if((cannon.machine_stat & BROKEN))
+ notice = "Cannon integrity failure!"
+ return
+ if((cannon.machine_stat & NOPOWER))
+ notice = "Cannon unpowered!"
+ return
+ notice = cannon.pre_fire(user, get_impact_turf())
+
+/obj/machinery/computer/bsa_control/proc/deploy(force=FALSE)
+ var/obj/machinery/bsa/full/prebuilt = locate() in range(7) //In case of adminspawn
+ if(prebuilt)
+ prebuilt.control_unit = src
+ return prebuilt
+
+ var/obj/machinery/bsa/middle/centerpiece = locate() in range(7)
+ if(!centerpiece)
+ notice = "No BSA parts detected nearby."
+ return null
+ notice = centerpiece.check_completion()
+ if(notice)
+ return null
+ //Totally nanite construction system not an immersion breaking spawning
+ var/datum/effect_system/smoke_spread/s = new
+ s.set_up(4,get_turf(centerpiece))
+ s.start()
+ var/obj/machinery/bsa/full/cannon = new(get_turf(centerpiece),centerpiece.get_cannon_direction())
+ cannon.control_unit = src
+ qdel(centerpiece.front)
+ qdel(centerpiece.back)
+ qdel(centerpiece)
+ return cannon
+
+/obj/machinery/computer/bsa_control/Destroy()
+ cannon.control_unit = null
+ cannon = null
+ core = null
+ . = ..()
diff --git a/modular_skyrat/modules/bsa_overhaul/icons/bsa_parts.dmi b/modular_skyrat/modules/bsa_overhaul/icons/bsa_parts.dmi
new file mode 100644
index 00000000000..ce9ab9c6f59
Binary files /dev/null and b/modular_skyrat/modules/bsa_overhaul/icons/bsa_parts.dmi differ
diff --git a/modular_skyrat/modules/bsa_overhaul/sound/superlaser_firing.ogg b/modular_skyrat/modules/bsa_overhaul/sound/superlaser_firing.ogg
new file mode 100644
index 00000000000..edf22909786
Binary files /dev/null and b/modular_skyrat/modules/bsa_overhaul/sound/superlaser_firing.ogg differ
diff --git a/modular_skyrat/modules/bsa_overhaul/sound/superlaser_prefire.ogg b/modular_skyrat/modules/bsa_overhaul/sound/superlaser_prefire.ogg
new file mode 100644
index 00000000000..8a6f19213b5
Binary files /dev/null and b/modular_skyrat/modules/bsa_overhaul/sound/superlaser_prefire.ogg differ
diff --git a/modular_skyrat/modules/cme/code/cme.dm b/modular_skyrat/modules/cme/code/cme.dm
index c353b33fa0a..a890ed31be5 100644
--- a/modular_skyrat/modules/cme/code/cme.dm
+++ b/modular_skyrat/modules/cme/code/cme.dm
@@ -148,10 +148,7 @@ Armageddon is truly going to fuck the station, use it sparingly.
intensity = pick(CME_MINIMAL, CME_MODERATE, CME_EXTREME)
var/area/loc_area_name = get_area(spawnpoint)
minor_announce("WARNING! [uppertext(intensity)] PULSE EXPECTED IN: [loc_area_name.name]", "Solar Flare Log:")
- for(var/i in GLOB.mob_list)
- var/mob/M = i
- if(M.client && M.z == spawnpoint.z)
- SEND_SOUND(M, sound('modular_skyrat/modules/cme/sound/cme_warning.ogg'))
+ alert_sound_to_playing(sound('modular_skyrat/modules/cme/sound/cme_warning.ogg'))
switch(intensity)
if(CME_MINIMAL)
var/obj/effect/cme/spawnedcme = new(spawnpoint)
diff --git a/modular_skyrat/modules/customization/modules/client/preferences.dm b/modular_skyrat/modules/customization/modules/client/preferences.dm
index 9aad0216db0..24d6f955246 100644
--- a/modular_skyrat/modules/customization/modules/client/preferences.dm
+++ b/modular_skyrat/modules/customization/modules/client/preferences.dm
@@ -219,6 +219,8 @@ GLOBAL_LIST_INIT(food, list(
var/show_body_size = FALSE
///The arousal state of the previewed character, can be toggled by the user
var/arousal_preview = AROUSAL_NONE
+ ///The current volume setting for announcements
+ var/announcement_volume = 60
/datum/preferences/New(client/C)
parent = C
@@ -1086,6 +1088,7 @@ GLOBAL_LIST_INIT(food, list(
dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"]
"
dat += "Play End of Round Sounds: [(toggles & SOUND_ENDOFROUND) ? "Enabled":"Disabled"]
"
dat += "Play Combat Mode Sounds: [(toggles & SOUND_COMBATMODE) ? "Enabled":"Disabled"]
"
+ dat += "Announcement Sound Volume: [announcement_volume]
"
dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"]
"
dat += "
"
@@ -2638,6 +2641,11 @@ GLOBAL_LIST_INIT(food, list(
if("combat_mode_sound")
toggles ^= SOUND_COMBATMODE
+ if("announcement_volume_level")
+ var/new_annoumcenent_volume = clamp(input(user, "Please enter the new announcement volume(1-100)", "New volume setting", 0) as num|null, 1, 100)
+ if(new_annoumcenent_volume)
+ announcement_volume = new_annoumcenent_volume
+
if("ghost_ears")
chat_toggles ^= CHAT_GHOSTEARS
diff --git a/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm b/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm
index 3f257c1cc4d..a4b550f3bb1 100644
--- a/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm
+++ b/modular_skyrat/modules/customization/modules/client/preferences_savefile.dm
@@ -170,13 +170,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
READ_FILE(S["see_rc_emotes"] , see_rc_emotes)
READ_FILE(S["broadcast_login_logout"] , broadcast_login_logout)
+ READ_FILE(S["announcement_volume"], announcement_volume)
+
READ_FILE(S["tgui_fancy"], tgui_fancy)
READ_FILE(S["tgui_lock"], tgui_lock)
READ_FILE(S["buttons_locked"], buttons_locked)
READ_FILE(S["windowflash"], windowflashing)
READ_FILE(S["be_special"] , be_special)
-
READ_FILE(S["default_slot"], default_slot)
READ_FILE(S["chat_toggles"], chat_toggles)
READ_FILE(S["skyrat_toggles"], skyrat_toggles)
@@ -271,6 +272,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color))
key_bindings = sanitize_keybindings(key_bindings)
favorite_outfits = SANITIZE_LIST(favorite_outfits)
+ announcement_volume = sanitize_integer(announcement_volume, 1, 100, initial(announcement_volume))
if(needs_update >= 0) //save the updated version
var/old_default_slot = default_slot
@@ -350,6 +352,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["key_bindings"], key_bindings)
WRITE_FILE(S["hearted_until"], (hearted_until > world.realtime ? hearted_until : null))
WRITE_FILE(S["favorite_outfits"], favorite_outfits)
+ WRITE_FILE(S["announcement_volume"], announcement_volume)
return TRUE
/datum/preferences/proc/load_character(slot)
diff --git a/tgstation.dme b/tgstation.dme
index 6f14bde0835..7d078e6fd75 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -170,6 +170,7 @@
#include "code\__DEFINES\~skyrat_defines\say.dm"
#include "code\__DEFINES\~skyrat_defines\security_alerts.dm"
#include "code\__DEFINES\~skyrat_defines\signals.dm"
+#include "code\__DEFINES\~skyrat_defines\sound.dm"
#include "code\__DEFINES\~skyrat_defines\traits.dm"
#include "code\__HELPERS\_lists.dm"
#include "code\__HELPERS\_logging.dm"
@@ -3593,7 +3594,9 @@
#include "modular_skyrat\modules\aesthetics\washing_machine\code\washing_machine.dm"
#include "modular_skyrat\modules\aesthetics\windows\code\windows.dm"
#include "modular_skyrat\modules\alerts\code\config.dm"
+#include "modular_skyrat\modules\alerts\code\default_announcer.dm"
#include "modular_skyrat\modules\alerts\code\firealarm.dm"
+#include "modular_skyrat\modules\alerts\code\priority_announce.dm"
#include "modular_skyrat\modules\alerts\code\set_security_level.dm"
#include "modular_skyrat\modules\altborgs\code\game\objects\items\robot_items.dm"
#include "modular_skyrat\modules\altborgs\code\game\objects\items\robot_upgrade.dm"
@@ -3653,6 +3656,8 @@
#include "modular_skyrat\modules\bluespace_locker\code\controllers\subsystem\bluespace_locker.dm"
#include "modular_skyrat\modules\bluespace_locker\code\game\area\Space_Station_13_areas.dm"
#include "modular_skyrat\modules\bluespace_locker\code\game\objects\structures\crates_lockers\bluespace_locker.dm"
+#include "modular_skyrat\modules\bsa_overhaul\code\bsa_cannon.dm"
+#include "modular_skyrat\modules\bsa_overhaul\code\bsa_computer.dm"
#include "modular_skyrat\modules\bulletrebalance\sniper.dm"
#include "modular_skyrat\modules\cargo\code\bloat.dm"
#include "modular_skyrat\modules\cargo\code\goodies.dm"