From e70905985ef1a2ed6fdf4b8beeeb140d1d5a36fa Mon Sep 17 00:00:00 2001 From: Changelogs Date: Wed, 28 Jun 2023 01:47:31 +0000 Subject: [PATCH 01/39] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-3584.yml | 6 ------ html/changelogs/AutoChangeLog-pr-3592.yml | 5 ----- html/changelogs/AutoChangeLog-pr-3600.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3620.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3720.yml | 4 ---- html/changelogs/archive/2023-06.yml | 17 +++++++++++++++++ 6 files changed, 17 insertions(+), 23 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-3584.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3592.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3600.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3620.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3720.yml diff --git a/html/changelogs/AutoChangeLog-pr-3584.yml b/html/changelogs/AutoChangeLog-pr-3584.yml deleted file mode 100644 index 95544a0eccfa..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3584.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "ihatethisengine" -delete-after: True -changes: - - balance: "explosive barricade upgrade provides better protection against explosions (25% to 50%)" - - balance: "explosive barricade upgrade provides strong protection against brute-based projectiles (50%)" - - balance: "explosive barricade upgrade provides strong protection against fire (50%)" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-3592.yml b/html/changelogs/AutoChangeLog-pr-3592.yml deleted file mode 100644 index dd8c5e6fb198..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3592.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "ihatethisengine" -delete-after: True -changes: - - balance: "larva surge is limited by marines/xenos ratio" - - bugfix: "xenos no longer get free larva from abandoned facehuggers during hijack" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-3600.yml b/html/changelogs/AutoChangeLog-pr-3600.yml deleted file mode 100644 index 9eef18f635f4..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3600.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "TheGamerdk" -delete-after: True -changes: - - balance: "Cluster OBs will now no longer hit turfs that have gotten OB protection after the initial OB was fired." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-3620.yml b/html/changelogs/AutoChangeLog-pr-3620.yml deleted file mode 100644 index 749713ef74a3..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3620.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Morrow, Thwomper" -delete-after: True -changes: - - rscadd: "Added three new uniforms and a snow jacket for the CL." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-3720.yml b/html/changelogs/AutoChangeLog-pr-3720.yml deleted file mode 100644 index 0d932c15ed35..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3720.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Drathek" -delete-after: True -changes: - - admin: "Mentors can now eavesdrop on mentor messages, and the responder to a mhelp doesn't get double logging from eavesdropping." \ No newline at end of file diff --git a/html/changelogs/archive/2023-06.yml b/html/changelogs/archive/2023-06.yml index 5593a1a1cc41..71aeb035f4b8 100644 --- a/html/changelogs/archive/2023-06.yml +++ b/html/changelogs/archive/2023-06.yml @@ -366,3 +366,20 @@ - bugfix: The game will no longer falsely claim there is no CO realforest2001: - rscadd: Changed min and max Predator ages from 20 - 10000 to 175 - 3000 +2023-06-28: + Drathek: + - admin: Mentors can now eavesdrop on mentor messages, and the responder to a mhelp + doesn't get double logging from eavesdropping. + Morrow, Thwomper: + - rscadd: Added three new uniforms and a snow jacket for the CL. + TheGamerdk: + - balance: Cluster OBs will now no longer hit turfs that have gotten OB protection + after the initial OB was fired. + ihatethisengine: + - balance: larva surge is limited by marines/xenos ratio + - bugfix: xenos no longer get free larva from abandoned facehuggers during hijack + - balance: explosive barricade upgrade provides better protection against explosions + (25% to 50%) + - balance: explosive barricade upgrade provides strong protection against brute-based + projectiles (50%) + - balance: explosive barricade upgrade provides strong protection against fire (50%) From 662abf15d69a402c3e2c760eca6e4d1fb4c7e94c Mon Sep 17 00:00:00 2001 From: blackdragonTOW <31581761+blackdragonTOW@users.noreply.github.com> Date: Tue, 27 Jun 2023 22:20:16 -0700 Subject: [PATCH 02/39] Almayer Maintenence Light Adjustments (#3731) # About the pull request Half a dozen rooms in Maint did not have any light fixtures at all (including rooms that were meant to be work spaces and storage. Added 1 small light to each of these rooms. Additionally, added one small light near important gameplay objects (1x near the ladder in upper port aft, and 1x near a door in upper starboard mid). The dark atmosphere of the corridors should remain 99.99% untouched. # Explain why it's good for the game Places like work spaces and food storage should have lights of some kind. Rooms, broadly speaking should have a light as well. This adds the bare minimum to closed off rooms as well as adds lights to two significant gameplay objects on the map (a ladder and a door) # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: maptweak: Added a small light to unlit rooms. /:cl: --- maps/map_files/USS_Almayer/USS_Almayer.dmm | 37 +++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index b58f522be0af..7043cc4cccee 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -993,6 +993,9 @@ /obj/structure/closet, /obj/item/clothing/suit/armor/riot/marine/vintage_riot, /obj/item/clothing/head/helmet/riot/vintage_riot, +/obj/structure/machinery/light/small{ + dir = 1 + }, /turf/open/floor/almayer{ icon_state = "plate" }, @@ -6497,6 +6500,9 @@ pixel_x = 8; pixel_y = -32 }, +/obj/structure/machinery/light/small{ + dir = 4 + }, /turf/open/floor/almayer{ icon_state = "plate" }, @@ -28329,6 +28335,9 @@ "cBd" = ( /obj/structure/surface/rack, /obj/item/reagent_container/food/snacks/wrapped/chunk, +/obj/structure/machinery/light/small{ + dir = 4 + }, /turf/open/floor/almayer{ icon_state = "cargo" }, @@ -33616,6 +33625,9 @@ dir = 8 }, /obj/effect/decal/cleanable/blood, +/obj/structure/machinery/light/small{ + dir = 4 + }, /turf/open/floor/almayer{ icon_state = "plate" }, @@ -38094,6 +38106,12 @@ icon_state = "plate" }, /area/almayer/hull/lower_hull/l_f_p) +"gXh" = ( +/obj/structure/machinery/light/small{ + dir = 8 + }, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/hull/upper_hull/u_m_s) "gXl" = ( /obj/structure/closet/secure_closet/personal/cabinet{ req_access_txt = "5" @@ -68843,6 +68861,14 @@ icon_state = "dark_sterile" }, /area/almayer/engineering/laundry) +"vqO" = ( +/obj/structure/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/almayer{ + icon_state = "plate" + }, +/area/almayer/hull/upper_hull/u_a_p) "vqW" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -71972,6 +71998,9 @@ desc = "A small coin, bearing the falling falcons insignia."; name = "falling falcons challenge coin" }, +/obj/structure/machinery/light/small{ + dir = 8 + }, /turf/open/floor/almayer{ icon_state = "plate" }, @@ -109119,7 +109148,7 @@ awE vGk xCX vGk -csz +hoX qVM csz qVM @@ -109931,7 +109960,7 @@ awE csz iid csz -csz +hoX qVM noV csz @@ -115357,7 +115386,7 @@ aag lYA aao aap -aap +gXh aao aap aap @@ -122923,7 +122952,7 @@ vuv vuv cxo cxo -cxo +vqO sXK tbD qMu From d9d8e2761778e0f33d6bc230a93ceab46a27e8c3 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 06:29:33 +0100 Subject: [PATCH 03/39] Automatic changelog for PR #3731 [ci skip] --- html/changelogs/AutoChangeLog-pr-3731.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3731.yml diff --git a/html/changelogs/AutoChangeLog-pr-3731.yml b/html/changelogs/AutoChangeLog-pr-3731.yml new file mode 100644 index 000000000000..21fd76664d2b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3731.yml @@ -0,0 +1,4 @@ +author: "blackdragonTOW" +delete-after: True +changes: + - maptweak: "Added a small light to unlit rooms." \ No newline at end of file From 108751ce0346c28b9bbf1ed6dcd841f3e8242a70 Mon Sep 17 00:00:00 2001 From: fira Date: Wed, 28 Jun 2023 06:20:29 +0100 Subject: [PATCH 04/39] Fix Infinite Recursion in Hugger Custom Rebound (#3730) # About the pull request ``` hugger egg trigger -> /obj/effect/alien/egg/proc/release_hugger -> /obj/item/clothing/mask/facehugger/proc/leap_at_nearest_target -> throw_atom -> collide against crusher in the way <<------------------------- -> launch_impact | -> hugger custom mob_launch_collision | -> step away | -> launch_impact didn't have time to reset throw yet | -> collides with something as throw again -------------------------- ``` # Testing Photographs and Procedure Untested # Changelog :cl: fix: Fixed a MC crash related to NPC huggers rebounding logic. /:cl: --- code/modules/mob/living/carbon/xenomorph/Facehuggers.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm b/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm index 212688c8c98f..8b3b1d54f26d 100644 --- a/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm +++ b/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm @@ -209,6 +209,11 @@ if(stat == UNCONSCIOUS) return + // Force reset throw now because [/atom/movable/proc/launch_impact] only does that later on + // If we DON'T, step()'s move below can collide, rebound, trigger this proc again, into infinite recursion + throwing = FALSE + rebounding = FALSE + if(leaping && can_hug(L, hivenumber)) attach(L) else if(L.density) From fedf2473306c21a7ef8fb7c356263b71dfbdf0e4 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 06:48:00 +0100 Subject: [PATCH 05/39] Automatic changelog for PR #3730 [ci skip] --- html/changelogs/AutoChangeLog-pr-3730.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3730.yml diff --git a/html/changelogs/AutoChangeLog-pr-3730.yml b/html/changelogs/AutoChangeLog-pr-3730.yml new file mode 100644 index 000000000000..9ae18e6bc788 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3730.yml @@ -0,0 +1,4 @@ +author: "fira" +delete-after: True +changes: + - bugfix: "Fixed a MC crash related to NPC huggers rebounding logic." \ No newline at end of file From b710769cc3b68bfb8835e13e14eb323ab51971af Mon Sep 17 00:00:00 2001 From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com> Date: Wed, 28 Jun 2023 07:27:21 +0200 Subject: [PATCH 06/39] Removes 2second queen building cooldown when building away from hive while boosted (#3718) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # About the pull request Currently, when the Queen has boosted building at the start of the game, she gets a 2 second cooldown AFTER construction is complete if she’s building far away from the hive. This removes that cooldown # Explain why it's good for the game This cooldown was introduced when queen boosted building was added 2 years ago. It has never worked, and started working recently due to a refactor. It obviously hasn’t been needed else someone wouldve fixed it. Currently, unboosted building has a 2 second cooldown from when you START building, this cooldown is only triggered AFTER the wall is built. This makes it very hard for Queen to build chokes, especially on lower pops. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: balance: Queen boosted building no longer has 2 second cooldown when far from hive /:cl: --- .../xenomorph/abilities/queen/queen_powers.dm | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm index 20bd029f5c94..944192530b0d 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm @@ -472,22 +472,6 @@ user_xeno.hive.banished_ckeys.Remove(banished_name) return ..() -/datum/action/xeno_action/activable/secrete_resin/remote/queen/use_ability(atom/A) - . = ..() - if(!.) - return - - if(!boosted) - return - var/mob/living/carbon/xenomorph/X = owner - var/datum/hive_status/HS = X.hive - if(!HS || !HS.hive_location) - return - // 5 screen radius - if(get_dist(A, HS.hive_location) > 35) - // Apply the normal cooldown if not building near the hive - apply_cooldown_override(initial(xeno_cooldown)) - /datum/action/xeno_action/onclick/eye name = "Enter Eye Form" action_icon_state = "queen_eye" From d2db229ec3bd4f76fcc264d408a6830a0c783b2e Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 07:02:30 +0100 Subject: [PATCH 07/39] Automatic changelog for PR #3718 [ci skip] --- html/changelogs/AutoChangeLog-pr-3718.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3718.yml diff --git a/html/changelogs/AutoChangeLog-pr-3718.yml b/html/changelogs/AutoChangeLog-pr-3718.yml new file mode 100644 index 000000000000..41f5322a2493 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3718.yml @@ -0,0 +1,4 @@ +author: "TheGamerdk" +delete-after: True +changes: + - balance: "Queen boosted building no longer has 2 second cooldown when far from hive" \ No newline at end of file From 8b7d442ac994afe19d30e8f5e5e70ec741373582 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Tue, 27 Jun 2023 22:28:59 -0700 Subject: [PATCH 08/39] Fix Deterred Crashsite Offset (#3717) # About the pull request This PR fixes an oversight where a deterred crashsite does not get positioned the same as a non-deterred one. # Explain why it's good for the game Fixes #3593 or atleast should much better mitigate it making it so a deterred crashsite positions the same as a non-deterred. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: Drathek fix: Fixed the crashsite offset for a hijack shuttle that gets deterred by the MGAD System /:cl: --- code/modules/shuttle/dropship_hijack.dm | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/code/modules/shuttle/dropship_hijack.dm b/code/modules/shuttle/dropship_hijack.dm index e664d0165c78..35009ad42485 100644 --- a/code/modules/shuttle/dropship_hijack.dm +++ b/code/modules/shuttle/dropship_hijack.dm @@ -1,3 +1,5 @@ +#define HIJACK_CRASH_SITE_OFFSET_X -5 +#define HIJACK_CRASH_SITE_OFFSET_Y -11 /datum/dropship_hijack var/obj/docking_port/mobile/shuttle @@ -90,9 +92,10 @@ var/obj/docking_port/stationary/marine_dropship/crash_site/target_site = new() crash_site = target_site - crash_site.x = target.x - 5 - crash_site.y = target.y - 11 - crash_site.z = target.z + var/turf/offset_target = locate(target.x + HIJACK_CRASH_SITE_OFFSET_X, target.y + HIJACK_CRASH_SITE_OFFSET_Y, target.z) + if(!offset_target) + offset_target = target // Welp the offsetting failed so... + target_site.forceMove(offset_target) target_site.name = "[shuttle] crash site" target_site.id = "crash_site_[shuttle.id]" @@ -116,7 +119,10 @@ remaining_crash_sites -= target_ship_section var/new_target_ship_section = pick(remaining_crash_sites) var/turf/target = get_crashsite_turf(new_target_ship_section) - crash_site.Move(target) + var/turf/offset_target = locate(target.x + HIJACK_CRASH_SITE_OFFSET_X, target.y + HIJACK_CRASH_SITE_OFFSET_Y, target.z) + if(!offset_target) + offset_target = target // Welp the offsetting failed so... + crash_site.forceMove(offset_target) marine_announcement("A hostile aircraft on course for the [target_ship_section] has been successfully deterred.", "IX-50 MGAD System") target_ship_section = new_target_ship_section // TODO mobs not alerted @@ -218,3 +224,6 @@ else CRASH("Crash site [ship_section] unknown.") return pick(turfs) + +#undef HIJACK_CRASH_SITE_OFFSET_X +#undef HIJACK_CRASH_SITE_OFFSET_Y From e5de7e89d16e0cd3370b009b0b935bc1202e2f4c Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 07:18:12 +0100 Subject: [PATCH 09/39] Automatic changelog for PR #3717 [ci skip] --- html/changelogs/AutoChangeLog-pr-3717.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3717.yml diff --git a/html/changelogs/AutoChangeLog-pr-3717.yml b/html/changelogs/AutoChangeLog-pr-3717.yml new file mode 100644 index 000000000000..6d6327ea63a7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3717.yml @@ -0,0 +1,4 @@ +author: "Drathek" +delete-after: True +changes: + - bugfix: "Fixed the crashsite offset for a hijack shuttle that gets deterred by the MGAD System" \ No newline at end of file From 10fcbded479dfe9e09f388116499d98f5a0bffe2 Mon Sep 17 00:00:00 2001 From: morrowwolf Date: Wed, 28 Jun 2023 02:43:51 -0400 Subject: [PATCH 10/39] Removes toxin mags on shivas (#3736) # About the pull request This PR removes toxin mags that were left on shivas. # Explain why it's good for the game This gear should no longer be attainable. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: Morrow del: Removed toxin mags on shivas /:cl: --- maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm | 5 ----- 1 file changed, 5 deletions(-) diff --git a/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm b/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm index 2ca8c7083cfa..a431aa368702 100644 --- a/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm +++ b/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm @@ -8762,8 +8762,6 @@ "cSn" = ( /obj/structure/closet/secure_closet/guncabinet, /obj/item/weapon/gun/rifle/m41aMK1, -/obj/item/ammo_magazine/rifle/m41aMK1/toxin, -/obj/item/ammo_magazine/rifle/m41aMK1/toxin, /obj/item/ammo_magazine/rifle/m41aMK1, /obj/item/ammo_magazine/rifle/m41aMK1, /obj/item/ammo_magazine/rifle/m41aMK1, @@ -19747,7 +19745,6 @@ pixel_x = -10; pixel_y = 13 }, -/obj/item/ammo_magazine/rifle/toxin, /turf/open/asphalt/cement, /area/shiva/interior/warehouse) "oYw" = ( @@ -21979,7 +21976,6 @@ /area/shiva/interior/colony/research_hab) "ril" = ( /obj/structure/closet/secure_closet/freezer/fridge, -/obj/item/ammo_magazine/rifle/m41aMK1/toxin, /turf/open/floor/shiva{ icon_state = "multi_tiles" }, @@ -24859,7 +24855,6 @@ }, /area/shiva/interior/colony/medseceng) "ukJ" = ( -/obj/item/ammo_magazine/rifle/m41aMK1/toxin, /turf/open/floor/shiva, /area/shiva/interior/colony/research_hab) "ukU" = ( From 169fcc302433957c05178a4e4315f3d0b8c4b96a Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 07:56:49 +0100 Subject: [PATCH 11/39] Automatic changelog for PR #3736 [ci skip] --- html/changelogs/AutoChangeLog-pr-3736.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3736.yml diff --git a/html/changelogs/AutoChangeLog-pr-3736.yml b/html/changelogs/AutoChangeLog-pr-3736.yml new file mode 100644 index 000000000000..c1eba0beabfd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3736.yml @@ -0,0 +1,4 @@ +author: "Morrow" +delete-after: True +changes: + - rscdel: "Removed toxin mags on shivas" \ No newline at end of file From 5d1c11e4a7c113e196c34d9d32fd3a2c7aef6cd8 Mon Sep 17 00:00:00 2001 From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com> Date: Wed, 28 Jun 2023 09:20:29 +0200 Subject: [PATCH 12/39] Fixes communications intel objective being instantly completed (#3723) # About the pull request tcomms_startup sets on = TRUE and is called on Initialize(), silly. This means it just checks when you toggle the state of the tower (usually to on) Doesn't check if you inputted the frequencies I guess but eh # Explain why it's good for the game Don't give marines free intel they didn't earn # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: fix: Communications intel objective now actually works /:cl: --- code/game/machinery/telecomms/presets.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index ce5e9a743bc5..a25293aebbd3 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -60,7 +60,7 @@ return TRUE return FALSE -/obj/structure/machinery/telecomms/relay/preset/tower/tcomms_startup() +/obj/structure/machinery/telecomms/relay/preset/tower/update_state() . = ..() if(on) playsound(src, 'sound/machines/tcomms_on.ogg', vol = 80, vary = FALSE, sound_range = 16, falloff = 0.5) From 3a181b0a1a63c4baa50baef5973aec042f9a68b6 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 08:29:14 +0100 Subject: [PATCH 13/39] Automatic changelog for PR #3723 [ci skip] --- html/changelogs/AutoChangeLog-pr-3723.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3723.yml diff --git a/html/changelogs/AutoChangeLog-pr-3723.yml b/html/changelogs/AutoChangeLog-pr-3723.yml new file mode 100644 index 000000000000..987b7eeec708 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3723.yml @@ -0,0 +1,4 @@ +author: "TheGamerdk" +delete-after: True +changes: + - bugfix: "Communications intel objective now actually works" \ No newline at end of file From 613e967a79830fc87e4ee7b36b96124e2b349375 Mon Sep 17 00:00:00 2001 From: morrowwolf Date: Wed, 28 Jun 2023 03:52:28 -0400 Subject: [PATCH 14/39] Xenos no longer can pull dead xenos (#3666) # About the pull request This PR makes it so xenos can no longer pull dead xenos (or other non-human typepathed dead mobs). The exception is dead larva. When https://github.com/cmss13-devs/cmss13/pull/3644 is merged I'll likely add xeno corpses so as to minimize clutter/wall blocking. # Explain why it's good for the game Recovering corpses for marines is an important part of multiple gameplay loops now. We shouldn't really be seeing stacks of xeno corpses in hives. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: Morrow balance: Xenos no longer can pull dead xenos /:cl: --- code/modules/mob/living/carbon/xenomorph/attack_alien.dm | 3 +++ code/modules/mob/living/carbon/xenomorph/castes/Larva.dm | 2 ++ 2 files changed, 5 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm index 9eb8601bb6dc..246e2d2809db 100644 --- a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm +++ b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm @@ -287,6 +287,9 @@ SPAN_DANGER("You nudge your head against [src]."), null, 5, CHAT_TYPE_XENO_FLUFF) /mob/living/proc/is_xeno_grabbable() + if(stat == DEAD) + return FALSE + return TRUE /mob/living/carbon/human/is_xeno_grabbable() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Larva.dm b/code/modules/mob/living/carbon/xenomorph/castes/Larva.dm index 04b7e04c2da5..4cf0ff113615 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Larva.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Larva.dm @@ -170,3 +170,5 @@ /mob/living/carbon/xenomorph/larva/emote(act, m_type, message, intentional, force_silence) playsound(loc, "alien_roar_larva", 15) +/mob/living/carbon/xenomorph/larva/is_xeno_grabbable() + return TRUE From 71f0ab820728426612b8ce6e0aab33077116bf43 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 09:05:03 +0100 Subject: [PATCH 15/39] Automatic changelog for PR #3666 [ci skip] --- html/changelogs/AutoChangeLog-pr-3666.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3666.yml diff --git a/html/changelogs/AutoChangeLog-pr-3666.yml b/html/changelogs/AutoChangeLog-pr-3666.yml new file mode 100644 index 000000000000..d7d8860c237e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3666.yml @@ -0,0 +1,4 @@ +author: "Morrow" +delete-after: True +changes: + - balance: "Xenos no longer can pull dead xenos" \ No newline at end of file From 151f92e06de7b02eaf8328b6bcfe7f10a1f869e5 Mon Sep 17 00:00:00 2001 From: spartanbobby <71467726+spartanbobby@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:23:47 +0100 Subject: [PATCH 16/39] LV522: Moves breaching charge again, buffs sec armoury as optional loot area for FORECON, adds missing warning stripes (#3742) # About the pull request In my last PR I moved the breaching charge because I thought it's prior location was too "free" for FORECON the location I moved it was too far away off the beaten path for FORECON making it entirely useless this PR moves it back onto the path while still being something they have to trek for it's also been made unacidable due to the location it's been moved to (The APC north of fitness) This PR also buffs up the security armoury very slightly, adding 2 more L42As and a box of 16 L42A magazines for FORECON to use if they can figure out how to actually get inside (Blowing up the fueltanks to the west of security) other than that I added some warning stripes to some stuff to make it look more pretty and messed up some closed walls outside of the maps bounds that no one can see anyway along with putting a maintjack next to a locked door for some enviro storytelling # Explain why it's good for the game FORECON is meant to gun for the dropship and in my last PR I kinda messed that up the optional sec stuff is there to provide a helping hand to FORECON if they're really in a bad spot # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: SpartanBobby maptweak: Minor decal changes to LV522 maptweak: Buffed sec armory on LV522 maptweak: LV522 Breaching charge moved to the PROP APC made UNACIDABLE /:cl: --- .../LV522_Chances_Claim.dmm | 366 ++++++++++++------ 1 file changed, 242 insertions(+), 124 deletions(-) diff --git a/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm b/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm index 01df2b7e136e..34eecc574c9c 100644 --- a/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm +++ b/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm @@ -998,8 +998,8 @@ /obj/structure/closet/crate/weapon, /obj/item/weapon/gun/rifle/l42a, /obj/item/weapon/gun/rifle/l42a, -/obj/item/ammo_magazine/rifle/l42a, -/obj/item/ammo_magazine/rifle/l42a, +/obj/item/weapon/gun/rifle/l42a, +/obj/item/weapon/gun/rifle/l42a, /turf/open/floor/prison, /area/lv522/indoors/a_block/security) "aIp" = ( @@ -4661,12 +4661,11 @@ /turf/open/floor/corsat, /area/lv522/atmos/east_reactor/west) "cKF" = ( -/obj/structure/cargo_container/kelland/left, /obj/item/explosive/plastic/breaching_charge{ - layer = 5 + unacidable = 1 }, /turf/open/auto_turf/shale/layer0, -/area/lv522/outdoors/colony_streets/east_central_street) +/area/lv522/outdoors/n_rockies) "cKG" = ( /turf/closed/wall/strata_ice/dirty, /area/lv522/outdoors/nw_rockies) @@ -9745,6 +9744,21 @@ icon_state = "plate" }, /area/lv522/atmos/east_reactor/east) +"eWF" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/storage/firstaid/adv{ + layer = 3.1; + pixel_x = 3; + pixel_y = -2 + }, +/obj/structure/surface/rack, +/obj/item/storage/firstaid/adv{ + pixel_y = 14 + }, +/turf/open/floor/prison{ + icon_state = "darkredfull2" + }, +/area/lv522/indoors/a_block/security) "eWK" = ( /obj/structure/pipes/standard/manifold/hidden/green{ dir = 4 @@ -10683,6 +10697,12 @@ /obj/item/prop/colony/used_flare, /turf/open/floor/prison, /area/lv522/indoors/a_block/dorms) +"fuw" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "W" + }, +/turf/open/auto_turf/shale/layer0, +/area/lv522/outdoors/colony_streets/north_west_street) "fuQ" = ( /obj/structure/pipes/standard/manifold/hidden/green{ dir = 1 @@ -13641,6 +13661,7 @@ "gLV" = ( /obj/structure/prop/server_equipment/yutani_server/broken{ density = 0; + layer = 3.5; pixel_y = 16 }, /obj/effect/decal/cleanable/dirt, @@ -13746,10 +13767,9 @@ /area/lv522/atmos/east_reactor) "gOC" = ( /obj/structure/pipes/vents/pump, -/obj/structure/surface/rack, -/obj/item/weapon/shield/riot, -/obj/item/weapon/classic_baton, /obj/effect/decal/cleanable/dirt, +/obj/structure/surface/table/almayer, +/obj/item/ammo_box/magazine/shotgun/beanbag/empty, /turf/open/floor/prison{ icon_state = "darkredfull2" }, @@ -19773,10 +19793,10 @@ }, /area/lv522/indoors/c_block/cargo) "jmd" = ( -/obj/item/weapon/shield/riot, -/obj/item/weapon/classic_baton, -/obj/structure/surface/rack, /obj/effect/decal/cleanable/dirt, +/obj/structure/surface/rack, +/obj/item/weapon/gun/revolver/cmb, +/obj/item/ammo_magazine/revolver/cmb, /turf/open/floor/prison{ icon_state = "darkredfull2" }, @@ -20728,13 +20748,13 @@ /turf/open/auto_turf/shale/layer1, /area/lv522/outdoors/colony_streets/north_west_street) "jGj" = ( -/obj/structure/surface/rack, -/obj/item/weapon/gun/revolver/cmb, -/obj/item/ammo_magazine/revolver/cmb, -/turf/open/floor/prison{ - icon_state = "darkredfull2" +/obj/effect/decal/cleanable/dirt, +/obj/item/maintenance_jack, +/turf/open/floor/strata{ + dir = 4; + icon_state = "white_cyan1" }, -/area/lv522/indoors/a_block/security) +/area/lv522/indoors/a_block/corpo) "jGm" = ( /obj/structure/barricade/handrail{ dir = 4 @@ -21364,6 +21384,10 @@ }, /turf/closed/wall/mineral/bone_resin, /area/lv522/oob) +"jUg" = ( +/obj/item/ammo_box/magazine/l42a/ap/empty, +/turf/open/floor/prison, +/area/lv522/indoors/a_block/security) "jUk" = ( /turf/open/floor/prison{ dir = 10; @@ -22373,6 +22397,13 @@ /obj/structure/platform_decoration{ dir = 4 }, +/obj/effect/decal/warning_stripes{ + icon_state = "S" + }, +/obj/effect/decal/warning_stripes{ + icon_state = "E"; + pixel_x = 1 + }, /turf/open/floor/prison{ icon_state = "floor_plate" }, @@ -25126,6 +25157,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/prison, /area/lv522/indoors/a_block/dorms) +"lsG" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "E"; + pixel_x = 1 + }, +/turf/open/auto_turf/shale/layer0, +/area/lv522/outdoors/colony_streets/north_west_street) "lsR" = ( /obj/structure/fence{ layer = 2.9 @@ -26235,6 +26273,13 @@ icon_state = "floor_marked" }, /area/lv522/indoors/lone_buildings/outdoor_bot) +"lUh" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "N"; + pixel_y = 1 + }, +/turf/open/auto_turf/shale/layer1, +/area/lv522/outdoors/colony_streets/north_west_street) "lUi" = ( /obj/structure/bed/chair/comfy{ dir = 1 @@ -27097,6 +27142,12 @@ /obj/structure/platform_decoration{ dir = 8 }, +/obj/effect/decal/warning_stripes{ + icon_state = "S" + }, +/obj/effect/decal/warning_stripes{ + icon_state = "W" + }, /turf/open/floor/prison{ icon_state = "floor_plate" }, @@ -27108,6 +27159,13 @@ icon_state = "darkpurplefull2" }, /area/lv522/indoors/a_block/dorms) +"mnU" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/ammo_magazine/rifle/l42a/extended{ + current_rounds = 0 + }, +/turf/open/floor/prison, +/area/lv522/indoors/a_block/security/glass) "mnX" = ( /obj/item/weapon/gun/rifle/m41a{ current_mag = null @@ -28488,6 +28546,13 @@ /area/lv522/outdoors/colony_streets/south_east_street) "mUG" = ( /obj/structure/platform_decoration, +/obj/effect/decal/warning_stripes{ + icon_state = "N"; + pixel_y = 1 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "W" + }, /turf/open/floor/prison{ icon_state = "floor_plate" }, @@ -28507,6 +28572,10 @@ /area/lv522/indoors/a_block/kitchen) "mVi" = ( /obj/structure/platform, +/obj/effect/decal/warning_stripes{ + icon_state = "N"; + pixel_y = 1 + }, /turf/open/floor/prison{ icon_state = "floor_plate" }, @@ -29045,6 +29114,9 @@ /obj/structure/platform{ dir = 4 }, +/obj/effect/decal/warning_stripes{ + icon_state = "W" + }, /turf/open/floor/prison{ icon_state = "floor_plate" }, @@ -30273,21 +30345,14 @@ /turf/open/asphalt/cement, /area/lv522/outdoors/colony_streets/north_street) "nKo" = ( -/obj/structure/surface/table/almayer, -/obj/structure/machinery/door_control/brbutton/alt{ - id = "Secure_Master_Armoury"; - name = "remote door-control" - }, -/obj/item/limb/hand/l_hand{ - dir = 1; - pixel_x = 9; - pixel_y = 3 +/obj/structure/pipes/standard/simple/hidden/green{ + dir = 4 }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/prison{ - icon_state = "darkredfull2" +/obj/item/weapon/gun/rifle/l42a{ + current_mag = null }, -/area/lv522/indoors/a_block/security) +/turf/open/floor/plating/plating_catwalk/prison, +/area/lv522/indoors/a_block/security/glass) "nKK" = ( /obj/structure/platform{ dir = 8 @@ -30376,6 +30441,7 @@ "nMt" = ( /obj/structure/surface/table/almayer, /obj/effect/decal/cleanable/dirt, +/obj/item/ammo_box/magazine/l42a, /turf/open/floor/prison{ icon_state = "darkredfull2" }, @@ -34987,6 +35053,14 @@ /obj/structure/platform_decoration{ dir = 1 }, +/obj/effect/decal/warning_stripes{ + icon_state = "N"; + pixel_y = 1 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "E"; + pixel_x = 1 + }, /turf/open/floor/prison{ icon_state = "floor_plate" }, @@ -36438,6 +36512,13 @@ }, /turf/open/floor/plating, /area/lv522/outdoors/colony_streets/central_streets) +"qma" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "NW-out"; + pixel_y = 1 + }, +/turf/open/auto_turf/shale/layer1, +/area/lv522/outdoors/colony_streets/north_west_street) "qml" = ( /obj/structure/pipes/standard/simple/hidden/green{ dir = 4 @@ -36686,9 +36767,17 @@ /turf/open/floor/plating/plating_catwalk/prison, /area/lv522/indoors/a_block/bridges/op_centre) "qqD" = ( -/obj/item/ammo_box/magazine/shotgun/buckshot/empty, /obj/structure/surface/table/almayer, /obj/effect/decal/cleanable/dirt, +/obj/structure/machinery/door_control/brbutton/alt{ + id = "Sec-Armoury-Lockdown"; + name = "remote door-control" + }, +/obj/item/limb/hand/l_hand{ + dir = 1; + pixel_x = 9; + pixel_y = 3 + }, /turf/open/floor/prison{ icon_state = "darkredfull2" }, @@ -36816,6 +36905,10 @@ /obj/structure/platform{ dir = 8 }, +/obj/effect/decal/warning_stripes{ + icon_state = "E"; + pixel_x = 1 + }, /turf/open/floor/prison{ icon_state = "floor_plate" }, @@ -37353,6 +37446,14 @@ icon_state = "blue_plate" }, /area/lv522/indoors/a_block/hallway) +"qDl" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "NE-out"; + pixel_x = 1; + pixel_y = 1 + }, +/turf/open/auto_turf/shale/layer0, +/area/lv522/outdoors/colony_streets/north_west_street) "qDr" = ( /obj/item/ammo_magazine/rifle/heap{ current_rounds = 0 @@ -39297,6 +39398,12 @@ icon_state = "floor_plate" }, /area/lv522/indoors/a_block/hallway) +"rmX" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "S" + }, +/turf/open/auto_turf/shale/layer0, +/area/lv522/outdoors/colony_streets/north_west_street) "rng" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/machinery/camera/autoname{ @@ -39624,12 +39731,8 @@ /turf/open/floor/prison, /area/lv522/indoors/a_block/dorms) "ruj" = ( -/obj/structure/machinery/door_control{ - id = "UD6"; - name = "Cargo Shutter Control" - }, /turf/closed/shuttle/dropship2/tornado/typhoon{ - icon_state = "53" + icon_state = "59" }, /area/lv522/landing_zone_forecon/UD6_Typhoon) "rus" = ( @@ -40104,18 +40207,12 @@ }, /area/lv522/landing_zone_forecon/UD6_Typhoon) "rDu" = ( -/obj/structure/closet/crate/ammo, -/obj/item/ammo_magazine/m56d, -/obj/item/ammo_magazine/m56d, -/obj/item/device/m56d_gun, -/obj/structure/barricade/handrail{ - dir = 4 - }, -/obj/structure/barricade/handrail{ - dir = 8 +/obj/structure/machinery/door_control{ + id = "UD6"; + name = "Cargo Shutter Control" }, -/turf/open/shuttle/dropship{ - icon_state = "rasputin15" +/turf/closed/shuttle/dropship2/tornado/typhoon{ + icon_state = "53" }, /area/lv522/landing_zone_forecon/UD6_Typhoon) "rDz" = ( @@ -41363,6 +41460,9 @@ /obj/structure/machinery/light{ dir = 8 }, +/obj/effect/decal/warning_stripes{ + icon_state = "W" + }, /turf/open/auto_turf/shale/layer0, /area/lv522/outdoors/colony_streets/north_west_street) "seA" = ( @@ -44799,6 +44899,9 @@ /obj/structure/platform{ dir = 1 }, +/obj/effect/decal/warning_stripes{ + icon_state = "S" + }, /turf/open/floor/prison{ icon_state = "floor_plate" }, @@ -47329,6 +47432,13 @@ "uAa" = ( /turf/open/floor/prison, /area/lv522/outdoors/colony_streets/north_street) +"uAb" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "SE-out"; + pixel_x = 1 + }, +/turf/open/auto_turf/shale/layer0, +/area/lv522/outdoors/colony_streets/north_west_street) "uAd" = ( /turf/open/floor/corsat{ dir = 1; @@ -47394,7 +47504,7 @@ /turf/open/floor/prison, /area/lv522/indoors/a_block/security) "uDs" = ( -/obj/item/clothing/head/beret/sec/hos, +/obj/item/clothing/head/CMB, /obj/effect/decal/cleanable/blood, /turf/open/floor/plating/plating_catwalk/prison, /area/lv522/indoors/a_block/security) @@ -47602,6 +47712,12 @@ icon_state = "blue_plate" }, /area/lv522/indoors/a_block/hallway) +"uGd" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "SW-out" + }, +/turf/open/auto_turf/shale/layer0, +/area/lv522/outdoors/colony_streets/north_west_street) "uGl" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/prison{ @@ -54463,7 +54579,7 @@ }, /area/lv522/indoors/b_block/hydro) "xwO" = ( -/obj/structure/cargo_container/watatsumi/leftmid, +/obj/structure/cargo_container/seegson/left, /turf/open/floor/prison, /area/lv522/outdoors/colony_streets/north_west_street) "xwZ" = ( @@ -54514,7 +54630,7 @@ /turf/open/floor/plating, /area/lv522/indoors/c_block/mining) "xxJ" = ( -/obj/structure/cargo_container/watatsumi/rightmid, +/obj/structure/cargo_container/seegson/mid, /obj/effect/decal/warning_stripes{ icon_state = "E"; pixel_x = 1 @@ -54530,7 +54646,7 @@ /turf/open/floor/prison, /area/lv522/indoors/a_block/admin) "xxV" = ( -/obj/structure/cargo_container/watatsumi/right, +/obj/structure/cargo_container/seegson/right, /turf/open/asphalt/cement{ icon_state = "cement1" }, @@ -55007,13 +55123,16 @@ /turf/open/floor/plating, /area/lv522/indoors/lone_buildings/engineering) "xKc" = ( -/obj/structure/largecrate/supply/supplies/mre, /obj/structure/barricade/handrail{ - dir = 4 + dir = 8 }, /obj/structure/barricade/handrail{ - dir = 8 + dir = 4 }, +/obj/structure/closet/crate/ammo, +/obj/item/ammo_magazine/m56d, +/obj/item/ammo_magazine/m56d, +/obj/item/device/m56d_gun, /turf/open/shuttle/dropship{ icon_state = "rasputin15" }, @@ -55994,9 +56113,8 @@ }, /area/lv522/outdoors/colony_streets/north_west_street) "ydD" = ( -/obj/item/weapon/shield/riot, -/obj/item/weapon/classic_baton, -/obj/structure/surface/rack, +/obj/structure/surface/table/almayer, +/obj/item/ammo_box/magazine/shotgun/buckshot/empty, /turf/open/floor/prison{ icon_state = "darkredfull2" }, @@ -64934,11 +65052,11 @@ slO hJZ hJZ hJZ -hJZ -hJZ -hJZ -hJZ -hJZ +uAb +lsG +lsG +lsG +qDl clY vjG kCJ @@ -65161,11 +65279,11 @@ slO hJZ clY hJZ -hJZ +rmX xkO xkO xkO -clY +lUh clY clY oTd @@ -65388,11 +65506,11 @@ slO hJZ clY clY -hJZ +rmX xkO sKj xkO -clY +lUh clY clY srQ @@ -65615,11 +65733,11 @@ eUt hJZ hJZ clY -hJZ +rmX xkO xWx xkO -clY +lUh clY clY oNQ @@ -65842,11 +65960,11 @@ eUt clY hJZ hJZ -hJZ +uGd sek -hJZ +fuw sek -clY +qma clY hJZ oNQ @@ -68540,7 +68658,7 @@ cpy cpy fgf cpy -yim +cKF hzA ihy yim @@ -75861,8 +75979,8 @@ kRb kBk iJu uDs -uDb -nKo +jUg +uVj sjy ogK oud @@ -76085,10 +76203,10 @@ wdi sjy sjy jmd -jmd +eWF oLW mbF -jGj +jft xbj sjy mNR @@ -77214,7 +77332,7 @@ sjy sjy sjy lhK -azl +nKo mqH ybt sjy @@ -77442,7 +77560,7 @@ sjy sjy lhK azl -mqH +mnU xhu sjy vHU @@ -78108,7 +78226,7 @@ iPZ uSv jyx uQF -jyx +jGj wwy jPw qgr @@ -79450,7 +79568,7 @@ saC saC saC saC -cpy +saC saC ien ien @@ -79675,9 +79793,9 @@ saC saC saC saC -cpy -cpy -cpy +saC +saC +saC saC saC ien @@ -79901,11 +80019,11 @@ saC saC saC saC -cpy -cpy -cpy -cpy -cpy +saC +saC +saC +saC +saC saC ien rxI @@ -80127,11 +80245,11 @@ saC saC saC saC -cpy -cpy -cpy -cpy -cpy +saC +saC +saC +saC +saC saC ien ien @@ -80355,10 +80473,10 @@ saC saC saC saC -cpy -cpy saC -cpy +saC +saC +saC saC saC ien @@ -80585,7 +80703,7 @@ saC saC saC saC -cpy +saC saC ien ien @@ -85353,7 +85471,7 @@ saC saC saC saC -cpy +saC saC saC saC @@ -85579,9 +85697,9 @@ saC saC saC saC -cpy -cpy -cpy +saC +saC +saC saC saC saC @@ -85806,11 +85924,11 @@ saC saC saC saC -cpy -cpy -cpy -cpy -cpy +saC +saC +saC +saC +saC saC saC bUN @@ -86034,11 +86152,11 @@ saC saC saC saC -cpy -cpy -cpy -cpy -cpy +saC +saC +saC +saC +saC ien cGd rtI @@ -86262,10 +86380,10 @@ saC saC saC saC -cpy -cpy -cpy -cpy +saC +saC +saC +saC ien rhh rtX @@ -86489,9 +86607,9 @@ saC saC saC saC -cpy -cpy -cpy +saC +saC +saC ien ien ien @@ -86717,9 +86835,9 @@ saC saC saC saC -cpy -cpy -cpy +saC +saC +saC ien qSH qSH @@ -86945,8 +87063,8 @@ saC saC saC saC -cpy -cpy +saC +saC ien qSH qSH @@ -94500,7 +94618,7 @@ tTD tTD tSm rnB -cKF +oXZ uKR rnB rnB From 5c5c6e59da54c3abfe8a7a1a9a92e6a8b7a8021e Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:31:45 +0100 Subject: [PATCH 17/39] Automatic changelog for PR #3742 [ci skip] --- html/changelogs/AutoChangeLog-pr-3742.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3742.yml diff --git a/html/changelogs/AutoChangeLog-pr-3742.yml b/html/changelogs/AutoChangeLog-pr-3742.yml new file mode 100644 index 000000000000..7319ac52f8d9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3742.yml @@ -0,0 +1,6 @@ +author: "SpartanBobby" +delete-after: True +changes: + - maptweak: "Minor decal changes to LV522" + - maptweak: "Buffed sec armory on LV522" + - maptweak: "LV522 Breaching charge moved to the PROP APC made UNACIDABLE" \ No newline at end of file From da8bda726843be28ffecff2d4907e335f9173c29 Mon Sep 17 00:00:00 2001 From: Katskan Date: Wed, 28 Jun 2023 10:02:31 -0400 Subject: [PATCH 18/39] Removes unintended extra storage G8 from jackets (#3743) # About the pull request Removes the G8 pouch storage for survivor jackets on some maps that was unintended. # Explain why it's good for the game Cuts some exploits/circumnavigation of storage balance that were unintended on snow maps. # Changelog :cl: balance: Removed G8A storage from various snow suits and parkas /:cl: --- code/modules/clothing/suits/labcoat.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index c621f112d7fc..278ffb666bfd 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -221,7 +221,6 @@ /obj/item/explosive/grenade, /obj/item/device/binoculars, /obj/item/attachable/bayonet, - /obj/item/storage/backpack/general_belt, /obj/item/storage/large_holster/machete, /obj/item/weapon/baseballbat, /obj/item/weapon/baseballbat/metal, @@ -289,7 +288,6 @@ /obj/item/explosive/grenade, /obj/item/device/binoculars, /obj/item/attachable/bayonet, - /obj/item/storage/backpack/general_belt, /obj/item/storage/large_holster/machete, /obj/item/weapon/baseballbat, /obj/item/weapon/baseballbat/metal, From 86a1e10eb53e8e318e4a8597e2d472677bc38636 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Wed, 28 Jun 2023 15:15:30 +0100 Subject: [PATCH 19/39] Automatic changelog for PR #3743 [ci skip] --- html/changelogs/AutoChangeLog-pr-3743.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3743.yml diff --git a/html/changelogs/AutoChangeLog-pr-3743.yml b/html/changelogs/AutoChangeLog-pr-3743.yml new file mode 100644 index 000000000000..084e74fc2c2e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3743.yml @@ -0,0 +1,4 @@ +author: "Katskan" +delete-after: True +changes: + - balance: "Removed G8A storage from various snow suits and parkas" \ No newline at end of file From 9dd2c0d0a1c21e3c9bddbad1321c63fd886f61cf Mon Sep 17 00:00:00 2001 From: forest2001 <41653574+realforest2001@users.noreply.github.com> Date: Wed, 28 Jun 2023 15:36:11 +0100 Subject: [PATCH 20/39] Project ARES - Resurrection (#3298) # About the pull request Overhauls ARES and makes it actually feel like a part of the ship and not a square box. Adds individual processors for different ARES systems that interact with oneanother to produce the same effects as we normally have. Bioscans require the bioscan processor to be functional, however will not broadcast if the interface processor is not functioning. The interface processor handles ARES communications (excluding Apollo) and is chiefly responsible for logging things to the ARES Console. This console can be used to review logs of all ARES' messages/announcements, Bioscans, the Apollo Link logs etc. # Explain why it's good for the game Adds a little immersion and use for ARES. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: add: Added an admin button for an ARES bioscan. Slightly refactored how Bioscans trigger for marines, relying on an ARES processor. add: Added individual proccessors for ARES systems. These are WIP and will eventually have damage and repair interactions. add: Added an ARES interaction console in the AI Core room, which holds logs for most ARES functions. add: Added the ability for ARES console to call ERT or Distress. add: Added motion triggers in ARES core and shipside comms that send alerts over Apollo. add: Added a 1to1 conversation feature between ARES and users of the interface console. add: Added preset open versions of blended poddoors. add: Added a console for directing Working Joes. This is largely WIP for future PR(s). add: Added subtypes of air pipes that don't explode on hijack, used these in ARES core. maptweak: Remodelled ARES Core onto a fake-z, and added the new processors. fix: door_control buttons now respect being indestructable when processing explosions. maptweak: Fixed the M39s overflowing in brig armory due to use of landmarks. /:cl: --------- Co-authored-by: harryob --- code/__DEFINES/ARES.dm | 54 + code/__DEFINES/__game.dm | 1 + code/__DEFINES/access.dm | 8 + code/__DEFINES/admin.dm | 2 + code/__DEFINES/camera.dm | 1 + code/__DEFINES/language.dm | 2 +- code/__DEFINES/misc.dm | 2 + code/__DEFINES/mode.dm | 1 + code/_globalvars/bitfields.dm | 1 + code/datums/emergency_calls/emergency_call.dm | 8 +- code/datums/paygrades/paygrade.dm | 7 + code/defines/procs/announcement.dm | 30 +- code/game/area/almayer.dm | 14 +- code/game/bioscans.dm | 13 +- code/game/jobs/access.dm | 7 +- code/game/machinery/ARES/ARES.dm | 236 + code/game/machinery/ARES/ARES_procs.dm | 815 +++ code/game/machinery/ARES/ARES_records.dm | 99 + .../game/machinery/ARES/ARES_step_triggers.dm | 197 + code/game/machinery/camera/presets.dm | 4 + .../machinery/computer/almayer_control.dm | 4 +- .../game/machinery/computer/camera_console.dm | 4 + .../game/machinery/computer/communications.dm | 3 + code/game/machinery/door_control.dm | 5 + code/game/machinery/doors/poddoor.dm | 5 +- code/game/machinery/doors/railing.dm | 6 +- code/game/objects/items/devices/cictablet.dm | 2 + code/game/objects/structures/misc.dm | 2 +- code/game/objects/structures/pipes/pipes.dm | 5 +- .../structures/pipes/standard/manifolds.dm | 8 + .../structures/pipes/standard/simple.dm | 4 + .../pipes/standard/standard_misc.dm | 4 + .../structures/pipes/vents/pump_scrubber.dm | 8 + code/game/objects/structures/signs.dm | 2 +- .../structures/stool_bed_chair_nest/chairs.dm | 5 + code/game/supplyshuttle.dm | 7 + code/game/turfs/floor_types.dm | 4 +- code/modules/admin/admin_verbs.dm | 11 + code/modules/admin/tabs/admin_tab.dm | 4 + code/modules/admin/tabs/event_tab.dm | 75 +- code/modules/admin/topic/topic.dm | 43 +- code/modules/cm_marines/anti_air.dm | 3 + code/modules/cm_marines/overwatch.dm | 3 + code/modules/cm_marines/smartgun_mount.dm | 17 +- code/modules/defenses/defenses.dm | 4 + code/modules/defenses/handheld.dm | 7 +- code/modules/gear_presets/uscm_ship.dm | 1 + code/modules/mob/language/languages.dm | 4 +- .../mob/living/carbon/xenomorph/Abilities.dm | 3 + .../xenomorph/abilities/general_powers.dm | 6 + .../xenomorph/abilities/queen/queen_powers.dm | 3 + .../mob/living/carbon/xenomorph/death.dm | 4 +- .../carbon/xenomorph/resin_constructions.dm | 3 + .../modules/mob/living/silicon/decoy/decoy.dm | 3 + .../security_levels/security_levels.dm | 12 +- .../shuttle/computers/dropship_computer.dm | 2 +- code/modules/shuttle/dropship_hijack.dm | 5 +- code/modules/shuttles/marine_ferry.dm | 4 +- code/modules/shuttles/shuttle_console.dm | 2 +- colonialmarines.dme | 5 + icons/obj/objects.dmi | Bin 159890 -> 164447 bytes icons/obj/structures/machinery/ares.dmi | Bin 0 -> 3840 bytes maps/map_files/USS_Almayer/USS_Almayer.dmm | 5719 +++++++++++------ .../packages/tgui/interfaces/AresInterface.js | 1493 +++++ tgui/packages/tgui/interfaces/WorkingJoe.js | 648 ++ 65 files changed, 7588 insertions(+), 2076 deletions(-) create mode 100644 code/__DEFINES/ARES.dm create mode 100644 code/game/machinery/ARES/ARES.dm create mode 100644 code/game/machinery/ARES/ARES_procs.dm create mode 100644 code/game/machinery/ARES/ARES_records.dm create mode 100644 code/game/machinery/ARES/ARES_step_triggers.dm create mode 100644 icons/obj/structures/machinery/ares.dmi create mode 100644 tgui/packages/tgui/interfaces/AresInterface.js create mode 100644 tgui/packages/tgui/interfaces/WorkingJoe.js diff --git a/code/__DEFINES/ARES.dm b/code/__DEFINES/ARES.dm new file mode 100644 index 000000000000..05a42738c499 --- /dev/null +++ b/code/__DEFINES/ARES.dm @@ -0,0 +1,54 @@ +/// Generic access for 1:1 conversations with ARES and unrestricted commands. +#define ARES_ACCESS_BASIC 0 +/// Secure Access, can read ARES Announcements and Bioscans. +#define ARES_ACCESS_COMMAND 1 +#define ARES_ACCESS_JOE 2 +/// CL, can read Apollo Log and also Delete Announcements. +#define ARES_ACCESS_CORPORATE 3 +/// Senior Command, can Delete Bioscans. +#define ARES_ACCESS_SENIOR 4 +/// Synth, CE & Commanding Officer, can read the access log. +#define ARES_ACCESS_CE 5 +#define ARES_ACCESS_SYNTH 6 +#define ARES_ACCESS_CO 7 +/// High Command, can read the deletion log. +#define ARES_ACCESS_HIGH 8 +#define ARES_ACCESS_WY_COMMAND 9 +/// Debugging. Allows me to view everything without using a high command rank. Unlikely to stay in a full merge. +#define ARES_ACCESS_DEBUG 10 + +#define ARES_RECORD_ANNOUNCE "Announcement Record" +#define ARES_RECORD_ANTIAIR "AntiAir Control Log" +#define ARES_RECORD_ASRS "Requisition Record" +#define ARES_RECORD_BIOSCAN "Bioscan Record" +#define ARES_RECORD_BOMB "Orbital Bombardment Record" +#define ARES_RECORD_DELETED "Deleted Record" +#define ARES_RECORD_SECURITY "Security Update" +#define ARES_RECORD_MAINTENANCE "Maintenance Ticket" +#define ARES_RECORD_ACCESS "Access Ticket" + +/// Not by ARES logged through marine_announcement() +#define ARES_LOG_NONE 0 +/// Logged with all announcements +#define ARES_LOG_MAIN 1 +/// Logged in the security updates +#define ARES_LOG_SECURITY 2 + +/// Access levels specifically for Working Joe management console +#define APOLLO_ACCESS_REQUEST 0 +#define APOLLO_ACCESS_REPORTER 1 +#define APOLLO_ACCESS_TEMP 2 +#define APOLLO_ACCESS_AUTHED 3 +#define APOLLO_ACCESS_JOE 4 +#define APOLLO_ACCESS_DEBUG 5 + +/// Ticket statuses, both for Access and Maintenance +#define TICKET_PENDING "pending" +#define TICKET_ASSIGNED "assigned" +#define TICKET_REJECTED "rejected" +#define TICKET_CANCELLED "cancelled" +#define TICKET_COMPLETED "complete" + +/// Cooldowns +#define COOLDOWN_ARES_SENSOR 60 SECONDS +#define COOLDOWN_ARES_ACCESS_CONTROL 20 SECONDS diff --git a/code/__DEFINES/__game.dm b/code/__DEFINES/__game.dm index 100a45ff6a94..3116d7f19555 100644 --- a/code/__DEFINES/__game.dm +++ b/code/__DEFINES/__game.dm @@ -106,6 +106,7 @@ block( \ #define SOUND_REBOOT (1<<5) #define SOUND_ADMIN_MEME (1<<6) #define SOUND_ADMIN_ATMOSPHERIC (1<<7) +#define SOUND_ARES_MESSAGE (1<<8) //toggles_chat #define CHAT_OOC (1<<0) diff --git a/code/__DEFINES/access.dm b/code/__DEFINES/access.dm index 8b9fe898c72c..a40675e0560e 100644 --- a/code/__DEFINES/access.dm +++ b/code/__DEFINES/access.dm @@ -43,6 +43,14 @@ most of them are tied into map-placed objects. This should be reworked in the fu #define ACCESS_MARINE_SYNTH 36 +// AI Core Accesses +/// Used in temporary passes +#define ACCESS_MARINE_AI_TEMP 90 +/// Used as dedicated access to ARES Core. +#define ACCESS_MARINE_AI 91 +/// Used to access Maintenance Protocols on ARES Interface. +#define ACCESS_ARES_DEBUG 92 + //Surface access levels #define ACCESS_CIVILIAN_PUBLIC 100 #define ACCESS_CIVILIAN_LOGISTICS 101 diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 95b98646c616..9702d51004ad 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -48,6 +48,8 @@ var/global/list/note_categories = list("Admin", "Merit", "Commanding Officer", " #define CC_MARK(user) "(MARK)" #define CC_REPLY(user) "(RPLY)" #define OBSERVER_JMP(observer, atom) atom ? "(JMP)" : "" +#define ARES_MARK(user) "(MARK)" +#define ARES_REPLY(user, ref) "(RPLY)" /atom/proc/Admin_Coordinates_Readable(area_name, admin_jump_ref) var/turf/T = get_turf(src) diff --git a/code/__DEFINES/camera.dm b/code/__DEFINES/camera.dm index 58b1b8acbd84..9d797b964d61 100644 --- a/code/__DEFINES/camera.dm +++ b/code/__DEFINES/camera.dm @@ -6,6 +6,7 @@ #define CAMERA_NET_ALAMO "Alamo" #define CAMERA_NET_NORMANDY "Normandy" #define CAMERA_NET_COLONY "Colony" +#define CAMERA_NET_ARES "ARES" #define CAMERA_NET_MILITARY "Military" #define CAMERA_NET_OVERWATCH "Overwatch" diff --git a/code/__DEFINES/language.dm b/code/__DEFINES/language.dm index 8cac90defb26..557f8e6a3f68 100644 --- a/code/__DEFINES/language.dm +++ b/code/__DEFINES/language.dm @@ -12,7 +12,7 @@ #define LANGUAGE_XENOMORPH "Xenomorph" #define LANGUAGE_HIVEMIND "Hivemind" -#define LANGUAGE_APOLLO "Apollo Link" +#define LANGUAGE_APOLLO "APOLLO Link" #define LANGUAGE_TELEPATH "Telepath Implant" diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index b2936248c3ba..bed2ceeced7d 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -44,6 +44,8 @@ #define AREA_ALLOW_XENO_JOIN (1<<2) /// Flags the area as a containment area #define AREA_CONTAINMENT (1<<3) +/// Flags the area as permanently unweedable. Still requires is_resin_allowed = FALSE +#define AREA_UNWEEDABLE (1<<4) /// Default number of ticks for do_after #define DA_DEFAULT_NUM_TICKS 5 diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm index 1f3c4ad22bf1..ab58df78abcc 100644 --- a/code/__DEFINES/mode.dm +++ b/code/__DEFINES/mode.dm @@ -14,6 +14,7 @@ #define EVACUATION_STATUS_IN_PROGRESS 2 #define EVACUATION_STATUS_COMPLETE 3 +#define NUCLEAR_TIME_LOCK 90 MINUTES #define NUKE_EXPLOSION_INACTIVE 0 #define NUKE_EXPLOSION_ACTIVE 1 #define NUKE_EXPLOSION_IN_PROGRESS 2 diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 7d16e437087b..121d1e305e43 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -328,6 +328,7 @@ DEFINE_BITFIELD(flags_area, list( "AREA_NOTUNNEL" = AREA_NOTUNNEL, "AREA_ALLOW_XENO_JOIN" = AREA_ALLOW_XENO_JOIN, "AREA_CONTAINMENT" = AREA_CONTAINMENT, + "ARES_UNWEEDABLE" = AREA_UNWEEDABLE, )) DEFINE_BITFIELD(disabilities, list( diff --git a/code/datums/emergency_calls/emergency_call.dm b/code/datums/emergency_calls/emergency_call.dm index c4b1000bb07b..2a305dcc4342 100644 --- a/code/datums/emergency_calls/emergency_call.dm +++ b/code/datums/emergency_calls/emergency_call.dm @@ -191,7 +191,7 @@ message_admins("Distress beacon: '[name]' activated [src.hostility? "[SPAN_WARNING("(THEY ARE HOSTILE)")]":"(they are friendly)"]. Looking for candidates.") if(announce) - marine_announcement("A distress beacon has been launched from the [MAIN_SHIP_NAME].", "Priority Alert", 'sound/AI/distressbeacon.ogg') + marine_announcement("A distress beacon has been launched from the [MAIN_SHIP_NAME].", "Priority Alert", 'sound/AI/distressbeacon.ogg', logging = ARES_LOG_SECURITY) addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/emergency_call, spawn_candidates), announce, override_spawn_loc, announce_dispatch_message), 30 SECONDS) @@ -207,7 +207,7 @@ candidates = list() if(announce) - marine_announcement("The distress signal has not received a response, the launch tubes are now recalibrating.", "Distress Beacon") + marine_announcement("The distress signal has not received a response, the launch tubes are now recalibrating.", "Distress Beacon", logging = ARES_LOG_SECURITY) return //We've got enough! @@ -236,8 +236,8 @@ if(I.current) to_chat(I.current, SPAN_WARNING("You didn't get selected to join the distress team. Better luck next time!")) - if(announce_dispatch_message) - marine_announcement(dispatch_message, "Distress Beacon", 'sound/AI/distressreceived.ogg') //Announcement that the Distress Beacon has been answered, does not hint towards the chosen ERT + if(announce) + marine_announcement(dispatch_message, "Distress Beacon", 'sound/AI/distressreceived.ogg', logging = ARES_LOG_SECURITY) //Announcement that the Distress Beacon has been answered, does not hint towards the chosen ERT message_admins("Distress beacon: [src.name] finalized, setting up candidates.") diff --git a/code/datums/paygrades/paygrade.dm b/code/datums/paygrades/paygrade.dm index b15071c882b7..bb0a3aa84bfa 100644 --- a/code/datums/paygrades/paygrade.dm +++ b/code/datums/paygrades/paygrade.dm @@ -25,6 +25,7 @@ GLOBAL_LIST_INIT_TYPED(paygrades, /datum/paygrade, setup_paygrades()) .[pg_id] = new PG GLOBAL_LIST_INIT(highcom_paygrades, list( + "PvI", "NO7", "MO7", "NO8", @@ -52,3 +53,9 @@ GLOBAL_LIST_INIT(co_paygrades, list( "MO5", "MO4" )) + +GLOBAL_LIST_INIT(wy_paygrades, list( + "WYC8", + "WYC9", + "WYC10" +)) diff --git a/code/defines/procs/announcement.dm b/code/defines/procs/announcement.dm index 5ee8c573d0e3..323fb526d527 100644 --- a/code/defines/procs/announcement.dm +++ b/code/defines/procs/announcement.dm @@ -30,7 +30,7 @@ //general marine announcement -/proc/marine_announcement(message, title = COMMAND_ANNOUNCE, sound_to_play = sound('sound/misc/notice2.ogg'), faction_to_display = FACTION_MARINE, add_PMCs = TRUE, signature) +/proc/marine_announcement(message, title = COMMAND_ANNOUNCE, sound_to_play = sound('sound/misc/notice2.ogg'), faction_to_display = FACTION_MARINE, add_PMCs = TRUE, signature, logging = ARES_LOG_MAIN) var/list/targets = GLOB.human_mob_list + GLOB.dead_mob_list if(faction_to_display == FACTION_MARINE) for(var/mob/M in targets) @@ -45,6 +45,14 @@ if((H.faction != faction_to_display && !add_PMCs) || (H.faction != faction_to_display && add_PMCs && !(H.faction in FACTION_LIST_WY)) && !(faction_to_display in H.faction_group)) //faction checks targets.Remove(H) + var/datum/ares_link/link = GLOB.ares_link + if(link.interface && !(link.interface.inoperable())) + switch(logging) + if(ARES_LOG_MAIN) + link.log_ares_announcement(title, message) + if(ARES_LOG_SECURITY) + link.log_ares_security(title, message) + else if(faction_to_display == "Everyone (-Yautja)") for(var/mob/M in targets) if(isobserver(M)) //observers see everything @@ -82,7 +90,7 @@ announcement_helper(message, title, targets, sound_to_play) //AI announcement that uses talking into comms -/proc/ai_announcement(message, sound_to_play = sound('sound/misc/interference.ogg')) +/proc/ai_announcement(message, sound_to_play = sound('sound/misc/interference.ogg'), logging = ARES_LOG_MAIN) for(var/mob/M in (GLOB.human_mob_list + GLOB.dead_mob_list)) if(isobserver(M) || ishuman(M) && is_mainship_level(M.z)) playsound_client(M.client, sound_to_play, M, vol = 45) @@ -90,6 +98,14 @@ for(var/mob/living/silicon/decoy/ship_ai/AI in ai_mob_list) INVOKE_ASYNC(AI, TYPE_PROC_REF(/mob/living/silicon/decoy/ship_ai, say), message) + var/datum/ares_link/link = GLOB.ares_link + if(link.interface && !(link.interface.inoperable())) + switch(logging) + if(ARES_LOG_MAIN) + link.log_ares_announcement("[MAIN_AI_SYSTEM] Comms Update", message) + if(ARES_LOG_SECURITY) + link.log_ares_security("[MAIN_AI_SYSTEM] Security Update", message) + /proc/ai_silent_announcement(message, channel_prefix, bypass_cooldown = FALSE) if(!message) return @@ -119,10 +135,14 @@ if(!isnull(signature)) message += "

Signed by,
[signature]
" + var/datum/ares_link/link = GLOB.ares_link + if(link.interface && !(link.interface.inoperable())) + link.log_ares_announcement(title, message) announcement_helper(message, title, targets, sound_to_play) + //Subtype of AI shipside announcement for "All Hands On Deck" alerts (COs and SEAs joining the game) -/proc/all_hands_on_deck(message, title = MAIN_AI_SYSTEM, sound_to_play = sound('sound/misc/sound_misc_boatswain.ogg'), signature) +/proc/all_hands_on_deck(message, title = MAIN_AI_SYSTEM, sound_to_play = sound('sound/misc/sound_misc_boatswain.ogg')) var/list/targets = GLOB.human_mob_list + GLOB.dead_mob_list for(var/mob/T in targets) if(isobserver(T)) @@ -130,6 +150,10 @@ if(!ishuman(T) || isyautja(T) || !is_mainship_level(T.z)) targets.Remove(T) + var/datum/ares_link/link = GLOB.ares_link + if(link.interface && !(link.interface.inoperable())) + link.log_ares_announcement("[title] Shipwide Update", message) + announcement_helper(message, title, targets, sound_to_play) //the announcement proc that handles announcing for each mob in targets list diff --git a/code/game/area/almayer.dm b/code/game/area/almayer.dm index a23f84323301..d19cbd3a6dec 100644 --- a/code/game/area/almayer.dm +++ b/code/game/area/almayer.dm @@ -77,17 +77,20 @@ fake_zlevel = 1 // upperdeck soundscape_playlist = SCAPE_PL_ARES soundscape_interval = 120 - flags_area = AREA_NOTUNNEL + flags_area = AREA_NOTUNNEL|AREA_UNWEEDABLE + can_build_special = FALSE + is_resin_allowed = FALSE + resin_construction_allowed = FALSE /area/almayer/command/securestorage name = "\improper Secure Storage" icon_state = "corporatespace" - fake_zlevel = 1 // upperdeck + fake_zlevel = 2 // lowerdeck /area/almayer/command/computerlab name = "\improper Computer Lab" icon_state = "ceroom" - fake_zlevel = 1 // upperdeck + fake_zlevel = 2 // lowerdeck /area/almayer/command/telecomms name = "\improper Telecommunications" @@ -181,6 +184,11 @@ icon_state = "astronavigation" fake_zlevel = 2 // lowerdeck +/area/almayer/shipboard/panic + name = "\improper Hangar Panic Room" + icon_state = "brig" + fake_zlevel = 2 // lowerdeck + /area/almayer/shipboard/starboard_missiles name = "\improper Missile Tubes Starboard" icon_state = "starboardmissile" diff --git a/code/game/bioscans.dm b/code/game/bioscans.dm index 474786e1ffae..55422ad3b878 100644 --- a/code/game/bioscans.dm +++ b/code/game/bioscans.dm @@ -107,7 +107,12 @@ GLOBAL_DATUM_INIT(bioscan_data, /datum/bioscan_data, new) /// This will do something after Project ARES. /datum/bioscan_data/proc/can_ares_bioscan() - return TRUE + var/datum/ares_link/link = GLOB.ares_link + if(!istype(link)) + return FALSE + if(link.p_bioscan && !link.p_bioscan.inoperable()) + return TRUE + return FALSE /// The announcement to all Humans. Slightly off for the planet and elsewhere, accurate for the ship. /datum/bioscan_data/proc/ares_bioscan(forced = FALSE, variance = 2) @@ -120,7 +125,11 @@ GLOBAL_DATUM_INIT(bioscan_data, /datum/bioscan_data, new) var/name = "[MAIN_AI_SYSTEM] Bioscan Status" var/input = "Bioscan complete.\n\nSensors indicate [xenos_on_ship_uncontained ? "[xenos_on_ship_uncontained]" : "no"] unknown lifeform signature[!xenos_on_ship_uncontained || xenos_on_ship_uncontained > 1 ? "s":""] present on the ship[xenos_on_ship_uncontained && xenos_ship_location ? ", including one in [xenos_ship_location]," : ""] and [fake_xenos_on_planet ? "approximately [fake_xenos_on_planet]" : "no"] signature[!fake_xenos_on_planet || fake_xenos_on_planet > 1 ? "s":""] located elsewhere[fake_xenos_on_planet && xenos_planet_location ? ", including one in [xenos_planet_location]":""]." - marine_announcement(input, name, 'sound/AI/bioscan.ogg') + + var/datum/ares_link/link = GLOB.ares_link + link.log_ares_bioscan(name, input) + if(forced || (link.p_interface && !link.p_interface.inoperable())) + marine_announcement(input, name, 'sound/AI/bioscan.ogg', logging = ARES_LOG_NONE) /// The announcement to all Xenos. Slightly off for the human ship, accurate otherwise. /datum/bioscan_data/proc/qm_bioscan(variance = 2) diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index c4a3070dea2d..55eee2e521bf 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -102,7 +102,11 @@ ///Includes restricted accesses /proc/get_all_marine_access() - return list(ACCESS_MARINE_CO) + get_main_marine_access() + return list( + ACCESS_MARINE_CO, + ACCESS_MARINE_AI, + ACCESS_MARINE_AI_TEMP, + ) + get_main_marine_access() ///All Almayer accesses other than the highly restricted ones, such as CO's office. /proc/get_main_marine_access() @@ -256,6 +260,7 @@ if(ACCESS_MARINE_SEA) return "SEA's Office" if(ACCESS_MARINE_KITCHEN) return "Kitchen" if(ACCESS_MARINE_SYNTH) return "Synthetic Storage" + if(ACCESS_MARINE_AI) return "AI Core" /proc/get_weyland_access_desc(A) switch(A) diff --git a/code/game/machinery/ARES/ARES.dm b/code/game/machinery/ARES/ARES.dm new file mode 100644 index 000000000000..f8a7351d123e --- /dev/null +++ b/code/game/machinery/ARES/ARES.dm @@ -0,0 +1,236 @@ +/obj/structure/machinery/ares + name = "ARES Machinery" + density = TRUE + anchored = TRUE + use_power = USE_POWER_IDLE + idle_power_usage = 600 + icon = 'icons/obj/structures/machinery/ares.dmi' + unslashable = TRUE + unacidable = TRUE + + var/link_id = MAIN_SHIP_DEFAULT_NAME + var/datum/ares_link/link + +/obj/structure/machinery/ares/ex_act(severity) + return + +/obj/structure/machinery/ares/Initialize(mapload, ...) + link_systems(override = FALSE) + . = ..() + +/obj/structure/machinery/ares/Destroy() + delink() + return ..() + +/obj/structure/machinery/ares/update_icon() + ..() + icon_state = initial(icon_state) + // Broken + if(stat & BROKEN) + icon_state += "_broken" + + // Powered + else if(stat & NOPOWER) + icon_state = initial(icon_state) + icon_state += "_off" + +/// Handles linking and de-linking the ARES systems. +/obj/structure/machinery/ares/proc/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + if(!new_link) + log_debug("Error: link_systems called without a link datum") + if(link && !override) + return FALSE + if(new_link.link_id == link_id) + link = new_link + log_debug("[name] linked to Ares Link [link_id]") + new_link.linked_systems += src + return TRUE + +/obj/structure/machinery/ares/proc/delink() + log_debug("[name] delinked from Ares Link [link.link_id]") + link.linked_systems -= src + link = null + +/obj/structure/machinery/ares/processor + name = "ARES Processor" + desc = "An external processor for ARES, used to process vast amounts of information." + icon_state = "processor" + +/obj/structure/machinery/ares/processor/apollo + name = "ARES Processor (APOLLO)" + desc = "The external component of ARES' APOLLO processor. Primarily responsible for coordinating Working Joes and Maintenance Drones. It definitely wasn't stolen from Seegson." + icon_state = "apollo_processor" + +/obj/structure/machinery/ares/processor/apollo/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + ..() + new_link.p_apollo = src + +/obj/structure/machinery/ares/processor/apollo/delink() + if(link && link.p_apollo == src) + link.p_apollo = null + ..() + +/obj/structure/machinery/ares/processor/interface + name = "ARES Processor (Interface)" + desc = "An external processor for ARES; this one handles core processes for interfacing with the crew, including radio transmissions and broadcasts." + icon_state = "int_processor" + +/obj/structure/machinery/ares/processor/interface/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + ..() + new_link.p_interface = src + +/obj/structure/machinery/ares/processor/interface/delink() + if(link && link.p_interface == src) + link.p_interface = null + ..() + +/obj/structure/machinery/ares/processor/bioscan + name = "ARES Processor (Bioscan)" + desc = "The external component of ARES' Bioscan systems. Without this, the USS Almayer would be incapable of running bioscans!" + icon_state = "bio_processor" + +/obj/structure/machinery/ares/processor/bioscan/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + ..() + new_link.p_bioscan = src + +/obj/structure/machinery/ares/processor/bioscan/delink() + if(link && link.p_bioscan == src) + link.p_bioscan = null + ..() + +/// Central Core +/obj/structure/machinery/ares/cpu + name = "ARES CPU" + desc = "This is ARES' central processor. Made of a casing designed to withstand nuclear blasts, the CPU also contains ARES' blackbox recorder." + icon_state = "CPU" + +/// Memory Substrate, +/obj/structure/machinery/ares/substrate + name = "ARES Substrate" + desc = "The memory substrate of ARES, containing complex protocols and information. Limited capabilities can operate on substrate alone, without the main ARES Unit operational." + icon_state = "substrate" + +// #################### ARES Interface Console ##################### +/obj/structure/machinery/computer/ares_console + name = "ARES Interface" + desc = "A console built to interface with ARES, allowing for 1:1 communication." + icon = 'icons/obj/structures/machinery/ares.dmi' + icon_state = "console" + exproof = TRUE + + var/current_menu = "login" + var/last_menu = "" + + var/authentication = ARES_ACCESS_BASIC + + /// The last person to login. + var/last_login + /// The person pretending to be last_login + var/sudo_holder + /// A record of who logged in and when. + var/list/access_list = list() + + /// The ID used to link all devices. + var/link_id = MAIN_SHIP_DEFAULT_NAME + var/datum/ares_link/link + + /// The current deleted chat log of 1:1 conversations being read. + var/list/deleted_1to1 = list() + + /// Holds all (/datum/ares_record/announcement)s and (/datum/ares_record/security/security_alert)s + var/list/records_announcement = list() + /// Holds all (/datum/ares_record/bioscan)s + var/list/records_bioscan = list() + /// Holds all (/datum/ares_record/bombardment)s + var/list/records_bombardment = list() + /// Holds all (/datum/ares_record/deletion)s + var/list/records_deletion = list() + /// Holds all (/datum/ares_record/talk_log)s + var/list/records_talking = list() + /// Holds all (/datum/ares_record/requisition_log)s + var/list/records_asrs = list() + /// Holds all (/datum/ares_record/security)s and (/datum/ares_record/antiair)s + var/list/records_security = list() + /// Is nuke request usable or not? (Nuke request is not currently coded to work.) + var/nuke_available = FALSE + + + COOLDOWN_DECLARE(ares_distress_cooldown) + COOLDOWN_DECLARE(ares_nuclear_cooldown) + +/obj/structure/machinery/computer/ares_console/proc/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + if(link && !override) + return FALSE + if(new_link.link_id == link_id) + new_link.interface = src + link = new_link + log_debug("[name] linked to Ares Link [link_id]") + new_link.linked_systems += src + return TRUE + +/obj/structure/machinery/computer/ares_console/Initialize(mapload, ...) + link_systems(override = FALSE) + . = ..() + +/obj/structure/machinery/computer/ares_console/proc/delink() + if(link && link.interface == src) + link.interface = null + link.linked_systems -= src + link = null + +/obj/structure/machinery/computer/ares_console/Destroy() + delink() + return ..() + +// #################### Working Joe Ticket Console ##################### +/obj/structure/machinery/computer/working_joe + name = "APOLLO Maintenance Controller" + desc = "A console built to facilitate Working Joes and their operation, allowing for simple allocation of resources." + icon = 'icons/obj/structures/machinery/ares.dmi' + icon_state = "console" + exproof = TRUE + + /// The ID used to link all devices. + var/link_id = MAIN_SHIP_DEFAULT_NAME + var/datum/ares_link/link + var/obj/structure/machinery/ares/processor/interface/processor + + var/current_menu = "login" + var/last_menu = "" + + var/authentication = ARES_ACCESS_BASIC + /// The last person to login. + var/last_login + /// A record of who logged in and when. + var/list/login_list = list() + + + /// If this is used to create AI Core access tickets + var/ticket_console = FALSE + var/obj/item/card/id/authenticator_id + var/ticket_authenticated = FALSE + var/obj/item/card/id/target_id + +/obj/structure/machinery/computer/working_joe/proc/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + if(link && !override) + return FALSE + if(new_link.link_id == link_id) + new_link.ticket_computers += src + link = new_link + log_debug("[name] linked to Ares Link [link_id]") + new_link.linked_systems += src + return TRUE + +/obj/structure/machinery/computer/working_joe/Initialize(mapload, ...) + link_systems(override = FALSE) + . = ..() + +/obj/structure/machinery/computer/working_joe/proc/delink() + if(link) + link.ticket_computers -= src + link.linked_systems -= src + link = null + +/obj/structure/machinery/computer/working_joe/Destroy() + delink() + return ..() diff --git a/code/game/machinery/ARES/ARES_procs.dm b/code/game/machinery/ARES/ARES_procs.dm new file mode 100644 index 000000000000..79c49818595c --- /dev/null +++ b/code/game/machinery/ARES/ARES_procs.dm @@ -0,0 +1,815 @@ +GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) + +/datum/ares_link + var/link_id = MAIN_SHIP_DEFAULT_NAME + /// All motion triggers for the link + var/list/linked_alerts = list() + /// All machinery for the link + var/list/linked_systems = list() + var/obj/structure/machinery/ares/processor/interface/p_interface + var/obj/structure/machinery/ares/processor/apollo/p_apollo + var/obj/structure/machinery/ares/processor/bioscan/p_bioscan + var/obj/structure/machinery/computer/ares_console/interface + var/list/obj/structure/machinery/computer/working_joe/ticket_computers = list() + + /// The chat log of the apollo link. Timestamped. + var/list/apollo_log = list() + + /// Working Joe stuff + var/list/tickets_maintenance = list() + var/list/tickets_access = list() + +/datum/ares_link/Destroy() + for(var/obj/structure/machinery/ares/link in linked_systems) + link.delink() + for(var/obj/structure/machinery/computer/ares_console/interface in linked_systems) + interface.delink() + for(var/obj/effect/step_trigger/ares_alert/alert in linked_alerts) + alert.delink() + ..() + + +// ------ ARES Logging Procs ------ // +/proc/log_ares_apollo(speaker, message) + if(!speaker) + speaker = "Unknown" + var/datum/ares_link/link = GLOB.ares_link + if(!link.p_apollo || link.p_apollo.inoperable()) + return + if(!link.p_interface || link.p_interface.inoperable()) + return + link.apollo_log.Add("[worldtime2text()]: [speaker], '[message]'") + +/datum/ares_link/proc/log_ares_bioscan(title, input) + if(!p_bioscan || p_bioscan.inoperable() || !interface) + return FALSE + interface.records_bioscan.Add(new /datum/ares_record/bioscan(title, input)) + +/datum/ares_link/proc/log_ares_bombardment(mob/living/user, ob_name, coordinates) + interface.records_bombardment.Add(new /datum/ares_record/bombardment(ob_name, "Bombardment fired at [coordinates].", user)) + +/datum/ares_link/proc/log_ares_announcement(title, message) + interface.records_announcement.Add(new /datum/ares_record/announcement(title, message)) + +/datum/ares_link/proc/log_ares_antiair(mob/living/user, details) + interface.records_security.Add(new /datum/ares_record/antiair(details, user)) + +/datum/ares_link/proc/log_ares_requisition(source, details, mob/living/user) + interface.records_asrs.Add(new /datum/ares_record/requisition_log(source, details, user)) + +/datum/ares_link/proc/log_ares_security(title, details) + interface.records_security.Add(new /datum/ares_record/security(title, details)) +// ------ End ARES Logging Procs ------ // + +// ------ ARES Interface Procs ------ // +/obj/structure/machinery/computer/proc/get_ares_access(obj/item/card/id/card) + if(ACCESS_ARES_DEBUG in card.access) + return ARES_ACCESS_DEBUG + switch(card.assignment) + if(JOB_WORKING_JOE) + return ARES_ACCESS_JOE + if(JOB_CHIEF_ENGINEER) + return ARES_ACCESS_CE + if(JOB_SYNTH) + return ARES_ACCESS_SYNTH + if(card.paygrade in GLOB.wy_paygrades) + return ARES_ACCESS_WY_COMMAND + if(card.paygrade in GLOB.highcom_paygrades) + return ARES_ACCESS_HIGH + if(card.paygrade in GLOB.co_paygrades) + return ARES_ACCESS_CO + if(ACCESS_MARINE_SENIOR in card.access) + return ARES_ACCESS_SENIOR + if(ACCESS_WY_CORPORATE in card.access) + return ARES_ACCESS_CORPORATE + if(ACCESS_MARINE_COMMAND in card.access) + return ARES_ACCESS_COMMAND + else + return ARES_ACCESS_BASIC + +/obj/structure/machinery/computer/proc/ares_auth_to_text(access_level) + switch(access_level) + if(ARES_ACCESS_BASIC)//0 + return "Authorized" + if(ARES_ACCESS_COMMAND)//1 + return "[MAIN_SHIP_NAME] Command" + if(ARES_ACCESS_JOE)//2 + return "Working Joe" + if(ARES_ACCESS_CORPORATE)//3 + return "Weyland-Yutani" + if(ARES_ACCESS_SENIOR)//4 + return "[MAIN_SHIP_NAME] Senior Command" + if(ARES_ACCESS_CE)//5 + return "Chief Engineer" + if(ARES_ACCESS_SYNTH)//6 + return "USCM Synthetic" + if(ARES_ACCESS_CO)//7 + return "[MAIN_SHIP_NAME] Commanding Officer" + if(ARES_ACCESS_HIGH)//8 + return "USCM High Command" + if(ARES_ACCESS_WY_COMMAND)//9 + return "Weyland-Yutani Directorate" + if(ARES_ACCESS_DEBUG)//10 + return "AI Service Technician" + + +/obj/structure/machinery/computer/ares_console/proc/message_ares(text, mob/Sender, ref) + var/msg = SPAN_STAFF_IC("ARES: [key_name(Sender, 1)] [ARES_MARK(Sender)] [ADMIN_PP(Sender)] [ADMIN_VV(Sender)] [ADMIN_SM(Sender)] [ADMIN_JMP_USER(Sender)] [ARES_REPLY(Sender, ref)]: [text]") + var/datum/ares_record/talk_log/conversation = locate(ref) + conversation.conversation += "[last_login] at [worldtime2text()], '[text]'" + for(var/client/admin in GLOB.admins) + if((R_ADMIN|R_MOD) & admin.admin_holder.rights) + to_chat(admin, msg) + if(admin.prefs.toggles_sound & SOUND_ARES_MESSAGE) + playsound_client(admin, 'sound/machines/chime.ogg', vol = 25) + log_say("[key_name(Sender)] sent '[text]' to ARES 1:1.") + +/obj/structure/machinery/computer/ares_console/proc/response_from_ares(text, ref) + var/datum/ares_record/talk_log/conversation = locate(ref) + conversation.conversation += "[MAIN_AI_SYSTEM] at [worldtime2text()], '[text]'" +// ------ End ARES Interface Procs ------ // + +// ------ ARES Interface UI ------ // + +/obj/structure/machinery/computer/ares_console/attack_hand(mob/user as mob) + if(..() || !allowed(usr) || inoperable()) + return FALSE + + tgui_interact(user) + return TRUE + +/obj/structure/machinery/computer/ares_console/tgui_interact(mob/user, datum/tgui/ui, datum/ui_state/state) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AresInterface", name) + ui.open() + +/obj/structure/machinery/computer/ares_console/ui_data(mob/user) + var/list/data = list() + + data["current_menu"] = current_menu + data["last_page"] = last_menu + + data["logged_in"] = last_login + data["sudo"] = sudo_holder ? TRUE : FALSE + + data["access_text"] = "[sudo_holder ? "(SUDO)," : ""] access level [authentication], [ares_auth_to_text(authentication)]." + data["access_level"] = authentication + + data["alert_level"] = security_level + data["evac_status"] = EvacuationAuthority.evac_status + data["worldtime"] = world.time + + data["access_log"] = list() + data["access_log"] += access_list + data["apollo_log"] = list() + data["apollo_log"] += link.apollo_log + + data["deleted_conversation"] = list() + data["deleted_conversation"] += deleted_1to1 + + data["distresstime"] = ares_distress_cooldown + data["distresstimelock"] = DISTRESS_TIME_LOCK + data["mission_failed"] = SSticker.mode.is_in_endgame + data["nuketimelock"] = NUCLEAR_TIME_LOCK + data["nuke_available"] = nuke_available + + var/list/logged_announcements = list() + for(var/datum/ares_record/announcement/broadcast as anything in records_announcement) + var/list/current_broadcast = list() + current_broadcast["time"] = broadcast.time + current_broadcast["title"] = broadcast.title + current_broadcast["details"] = broadcast.details + current_broadcast["ref"] = "\ref[broadcast]" + logged_announcements += list(current_broadcast) + data["records_announcement"] = logged_announcements + + var/list/logged_alerts = list() + for(var/datum/ares_record/security/security_alert as anything in records_announcement) + if(!istype(security_alert)) + continue + var/list/current_alert = list() + current_alert["time"] = security_alert.time + current_alert["title"] = security_alert.title + current_alert["details"] = security_alert.details + current_alert["ref"] = "\ref[security_alert]" + logged_alerts += list(current_alert) + data["records_security"] = logged_alerts + + var/list/logged_bioscans = list() + for(var/datum/ares_record/bioscan/scan as anything in records_bioscan) + var/list/current_scan = list() + current_scan["time"] = scan.time + current_scan["title"] = scan.title + current_scan["details"] = scan.details + current_scan["ref"] = "\ref[scan]" + logged_bioscans += list(current_scan) + data["records_bioscan"] = logged_bioscans + + var/list/logged_bombs = list() + for(var/datum/ares_record/bombardment/bomb as anything in records_bombardment) + var/list/current_bomb = list() + current_bomb["time"] = bomb.time + current_bomb["title"] = bomb.title + current_bomb["details"] = bomb.details + current_bomb["user"] = bomb.user + current_bomb["ref"] = "\ref[bomb]" + logged_bombs += list(current_bomb) + data["records_bombardment"] = logged_bombs + + var/list/logged_deletes = list() + for(var/datum/ares_record/deletion/deleted as anything in records_deletion) + if(!istype(deleted)) + continue + var/list/current_delete = list() + current_delete["time"] = deleted.time + current_delete["title"] = deleted.title + current_delete["details"] = deleted.details + current_delete["user"] = deleted.user + current_delete["ref"] = "\ref[deleted]" + logged_deletes += list(current_delete) + data["records_deletion"] = logged_deletes + + var/list/logged_discussions = list() + for(var/datum/ares_record/deleted_talk/deleted_convo as anything in records_deletion) + if(!istype(deleted_convo)) + continue + var/list/deleted_disc = list() + deleted_disc["time"] = deleted_convo.time + deleted_disc["title"] = deleted_convo.title + deleted_disc["ref"] = "\ref[deleted_convo]" + logged_discussions += list(deleted_disc) + data["deleted_discussions"] = logged_discussions + + var/list/logged_adjustments = list() + for(var/datum/ares_record/antiair/aa_adjustment as anything in records_security) + if(!istype(aa_adjustment)) + continue + var/list/current_adjustment = list() + current_adjustment["time"] = aa_adjustment.time + current_adjustment["details"] = aa_adjustment.details + current_adjustment["user"] = aa_adjustment.user + current_adjustment["ref"] = "\ref[aa_adjustment]" + logged_adjustments += list(current_adjustment) + data["aa_adjustments"] = logged_adjustments + + var/list/logged_orders = list() + for(var/datum/ares_record/requisition_log/req_order as anything in records_asrs) + if(!istype(req_order)) + continue + var/list/current_order = list() + current_order["time"] = req_order.time + current_order["details"] = req_order.details + current_order["title"] = req_order.title + current_order["user"] = req_order.user + current_order["ref"] = "\ref[req_order]" + logged_orders += list(current_order) + data["records_requisition"] = logged_orders + + var/list/logged_convos = list() + var/list/active_convo = list() + var/active_ref + for(var/datum/ares_record/talk_log/log as anything in records_talking) + if(!istype(log)) + continue + if(log.user == last_login) + active_convo = log.conversation + active_ref = "\ref[log]" + + var/list/current_convo = list() + current_convo["user"] = log.user + current_convo["ref"] = "\ref[log]" + current_convo["conversation"] = log.conversation + logged_convos += list(current_convo) + + data["active_convo"] = active_convo + data["active_ref"] = active_ref + data["conversations"] = logged_convos + + return data + +/obj/structure/machinery/computer/ares_console/ui_static_data(mob/user) + var/list/data = list() + + data["link_id"] = link_id + + return data + +/obj/structure/machinery/computer/ares_console/ui_status(mob/user, datum/ui_state/state) + . = ..() + if(!allowed(user)) + return UI_UPDATE + if(inoperable()) + return UI_DISABLED + +/obj/structure/machinery/computer/ares_console/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + playsound(src, "keyboard_alt", 15, 1) + + switch (action) + if("go_back") + if(!last_menu) + return to_chat(usr, SPAN_WARNING("Error, no previous page detected.")) + var/temp_holder = current_menu + current_menu = last_menu + last_menu = temp_holder + + if("login") + var/mob/living/carbon/human/operator = usr + var/obj/item/card/id/idcard = operator.get_active_hand() + if(istype(idcard)) + authentication = get_ares_access(idcard) + last_login = idcard.registered_name + else if(operator.wear_id) + idcard = operator.wear_id + if(istype(idcard)) + authentication = get_ares_access(idcard) + last_login = idcard.registered_name + else + to_chat(usr, SPAN_WARNING("You require an ID card to access this terminal!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(authentication) + access_list += "[last_login] at [worldtime2text()], Access Level [authentication] - [ares_auth_to_text(authentication)]." + current_menu = "main" + + if("sudo") + var/new_user = tgui_input_text(usr, "Enter Sudo Username", "Sudo User", encode = FALSE) + if(new_user) + if(new_user == sudo_holder) + last_login = sudo_holder + sudo_holder = null + return FALSE + if(new_user == last_login) + to_chat(usr, SPAN_WARNING("Already remote logged in as this user.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + sudo_holder = last_login + last_login = new_user + access_list += "[last_login] at [worldtime2text()], Sudo Access." + return TRUE + if("sudo_logout") + access_list += "[last_login] at [worldtime2text()], Sudo Logout." + last_login = sudo_holder + sudo_holder = null + return + // -- Page Changers -- // + if("logout") + last_menu = current_menu + current_menu = "login" + if(sudo_holder) + access_list += "[last_login] at [worldtime2text()], Sudo Logout." + last_login = sudo_holder + sudo_holder = null + access_list += "[last_login] logged out at [worldtime2text()]." + + if("home") + last_menu = current_menu + current_menu = "main" + if("page_1to1") + last_menu = current_menu + current_menu = "talking" + if("page_announcements") + last_menu = current_menu + current_menu = "announcements" + if("page_bioscans") + last_menu = current_menu + current_menu = "bioscans" + if("page_bombardments") + last_menu = current_menu + current_menu = "bombardments" + if("page_apollo") + last_menu = current_menu + current_menu = "apollo" + if("page_access") + last_menu = current_menu + current_menu = "access_log" + if("page_security") + last_menu = current_menu + current_menu = "security" + if("page_requisitions") + last_menu = current_menu + current_menu = "requisitions" + if("page_antiair") + last_menu = current_menu + current_menu = "antiair" + if("page_emergency") + last_menu = current_menu + current_menu = "emergency" + if("page_deleted") + last_menu = current_menu + current_menu = "delete_log" + if("page_deleted_1to1") + last_menu = current_menu + current_menu = "deleted_talks" + + // -- Delete Button -- // + if("delete_record") + var/datum/ares_record/record = locate(params["record"]) + if(record.record_name == ARES_RECORD_DELETED) + return FALSE + var/datum/ares_record/deletion/new_delete = new + var/new_details = "Error" + var/new_title = "Error" + switch(record.record_name) + if(ARES_RECORD_ANNOUNCE) + new_title = "[record.title] at [record.time]" + new_details = record.details + records_announcement -= record + if(ARES_RECORD_BIOSCAN) + new_title = "[record.title] at [record.time]" + new_details = record.details + records_bioscan -= record + if(ARES_RECORD_BOMB) + new_title = "[record.title] at [record.time]" + new_details = "[record.details] Launched by [record.user]." + records_bombardment -= record + + new_delete.details = new_details + new_delete.user = last_login + new_delete.title = new_title + + records_deletion += new_delete + + // -- 1:1 Conversation -- // + if("new_conversation") + var/datum/ares_record/talk_log/convo = new(last_login) + convo.conversation += "[MAIN_AI_SYSTEM] at [worldtime2text()], 'New 1:1 link initiated. Greetings, [last_login].'" + records_talking += convo + + if("clear_conversation") + var/datum/ares_record/talk_log/conversation = locate(params["active_convo"]) + if(!istype(conversation)) + return FALSE + var/datum/ares_record/deleted_talk/deleted = new + deleted.title = conversation.title + deleted.conversation = conversation.conversation + deleted.user = conversation.user + records_deletion += deleted + records_talking -= conversation + + if("message_ares") + var/message = tgui_input_text(usr, "What do you wish to say to ARES?", "ARES Message", encode = FALSE) + if(message) + message_ares(message, usr, params["active_convo"]) + + if("read_record") + var/datum/ares_record/deleted_talk/conversation = locate(params["record"]) + deleted_1to1 = conversation.conversation + last_menu = current_menu + current_menu = "read_deleted" + + // -- Emergency Buttons -- // + if("evacuation_start") + if(security_level < SEC_LEVEL_RED) + to_chat(usr, SPAN_WARNING("The ship must be under red alert in order to enact evacuation procedures.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + if(EvacuationAuthority.flags_scuttle & FLAGS_EVACUATION_DENY) + to_chat(usr, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + if(!EvacuationAuthority.initiate_evacuation()) + to_chat(usr, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + log_game("[key_name(usr)] has called for an emergency evacuation via ARES.") + message_admins("[key_name_admin(usr)] has called for an emergency evacuation via ARES.") + var/datum/ares_link/link = GLOB.ares_link + link.log_ares_security("Initiate Evacuation", "[last_login] has called for an emergency evacuation via ARES.") + . = TRUE + + if("distress") + if(!SSticker.mode) + return FALSE //Not a game mode? + if(world.time < DISTRESS_TIME_LOCK) + to_chat(usr, SPAN_WARNING("You have been here for less than six minutes... what could you possibly have done!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(!COOLDOWN_FINISHED(src, ares_distress_cooldown)) + to_chat(usr, SPAN_WARNING("The distress launcher is cooling down!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(security_level == SEC_LEVEL_DELTA) + to_chat(usr, SPAN_WARNING("The ship is already undergoing self destruct procedures!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + else if(security_level < SEC_LEVEL_RED) + to_chat(usr, SPAN_WARNING("The ship must be under red alert to launch a distress beacon!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + for(var/client/admin in GLOB.admins) + if((R_ADMIN|R_MOD) & admin.admin_holder.rights) + playsound_client(admin,'sound/effects/sos-morse-code.ogg',10) + message_admins("[key_name(usr)] has requested a Distress Beacon (via ARES)! [CC_MARK(usr)] (SEND) (DENY) [ADMIN_JMP_USER(usr)] [CC_REPLY(usr)]") + to_chat(usr, SPAN_NOTICE("A distress beacon request has been sent to USCM High Command.")) + COOLDOWN_START(src, ares_distress_cooldown, COOLDOWN_COMM_REQUEST) + return TRUE + + if("nuclearbomb") + if(!SSticker.mode) + return FALSE //Not a game mode? + if(world.time < NUCLEAR_TIME_LOCK) + to_chat(usr, SPAN_WARNING("It is too soon to request Nuclear Ordnance!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(!COOLDOWN_FINISHED(src, ares_nuclear_cooldown)) + to_chat(usr, SPAN_WARNING("The ordnance request frequency is garbled, wait for reset!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(security_level == SEC_LEVEL_DELTA || SSticker.mode.is_in_endgame) + to_chat(usr, SPAN_WARNING("The mission has failed catastrophically, what do you want a nuke for!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + for(var/client/admin in GLOB.admins) + if((R_ADMIN|R_MOD) & admin.admin_holder.rights) + playsound_client(admin,'sound/effects/sos-morse-code.ogg',10) + message_admins("[key_name(usr)] has requested use of Nuclear Ordnance (via ARES)! [CC_MARK(usr)] (APPROVE) (DENY) [ADMIN_JMP_USER(usr)] [CC_REPLY(usr)]") + to_chat(usr, SPAN_NOTICE("A nuclear ordnance request has been sent to USCM High Command.")) + COOLDOWN_START(src, ares_nuclear_cooldown, COOLDOWN_COMM_DESTRUCT) + return TRUE +// ------ End ARES Interface UI ------ // + + +/obj/structure/machinery/computer/working_joe/get_ares_access(obj/item/card/id/card) + if(ACCESS_ARES_DEBUG in card.access) + return APOLLO_ACCESS_DEBUG + switch(card.assignment) + if(JOB_WORKING_JOE) + return APOLLO_ACCESS_JOE + if(JOB_CHIEF_ENGINEER, JOB_SYNTH, JOB_CO) + return APOLLO_ACCESS_AUTHED + if(ACCESS_MARINE_AI in card.access) + return APOLLO_ACCESS_AUTHED + if(ACCESS_MARINE_AI_TEMP in card.access) + return APOLLO_ACCESS_TEMP + if((ACCESS_MARINE_COMMAND in card.access ) || (ACCESS_MARINE_ENGINEERING in card.access) || (ACCESS_WY_CORPORATE in card.access)) + return APOLLO_ACCESS_REPORTER + else + return APOLLO_ACCESS_REQUEST + +/obj/structure/machinery/computer/working_joe/ares_auth_to_text(access_level) + switch(access_level) + if(APOLLO_ACCESS_REQUEST)//0 + return "Unauthorized Personnel" + if(APOLLO_ACCESS_REPORTER)//1 + return "Validated Incident Reporter" + if(APOLLO_ACCESS_TEMP)//2 + return "Authorized Visitor" + if(APOLLO_ACCESS_AUTHED)//3 + return "Certified Personnel" + if(APOLLO_ACCESS_JOE)//4 + return "Working Joe" + if(APOLLO_ACCESS_DEBUG)//5 + return "AI Service Technician" + +// ------ Maintenance Controller UI ------ // +/obj/structure/machinery/computer/working_joe/verb/eject_id() + set category = "Object" + set name = "Eject ID Card" + set src in oview(1) + + if(!usr || usr.stat || usr.lying) return + + if(authenticator_id) + authenticator_id.loc = get_turf(src) + if(!usr.get_active_hand() && istype(usr,/mob/living/carbon/human)) + usr.put_in_hands(authenticator_id) + if(operable()) // Powered. Console can response. + visible_message("[SPAN_BOLD("[src]")] states, \"AUTH LOGOUT: Session end confirmed.\"") + else + to_chat(usr, "You remove [authenticator_id] from [src].") + ticket_authenticated = FALSE // No card - no access + authenticator_id = null + + else if(target_id) + target_id.loc = get_turf(src) + if(!usr.get_active_hand() && istype(usr,/mob/living/carbon/human)) + usr.put_in_hands(target_id) + else + to_chat(usr, "You remove [target_id] from [src].") + target_id = null + + else + to_chat(usr, "There is nothing to remove from the console.") + return + +/obj/structure/machinery/computer/working_joe/attackby(obj/object, mob/user) + if(istype(object, /obj/item/card/id)) + if(!operable()) + to_chat(user, SPAN_NOTICE("You try to insert [object] but [src] remains silent.")) + return + var/obj/item/card/id/idcard = object + if((ACCESS_MARINE_AI in idcard.access) || (ACCESS_ARES_DEBUG in idcard.access)) + if(!authenticator_id) + if(user.drop_held_item()) + object.forceMove(src) + authenticator_id = object + authenticate(authenticator_id) + else if(!target_id) + if(user.drop_held_item()) + object.forceMove(src) + target_id = object + else + to_chat(user, "Both slots are full already. Remove a card first.") + return + else + if(!target_id) + if(user.drop_held_item()) + object.forceMove(src) + target_id = object + else + to_chat(user, "Both slots are full already. Remove a card first.") + return + else + ..() + +/obj/structure/machinery/computer/working_joe/proc/authenticate(obj/item/card/id/id_card) + if(!id_card) + visible_message("[SPAN_BOLD("[src]")] states, \"AUTH ERROR: Authenticator card is missing!\"") + return FALSE + + if((ACCESS_MARINE_AI in id_card.access) || (ACCESS_ARES_DEBUG in id_card.access)) + ticket_authenticated = TRUE + visible_message("[SPAN_BOLD("[src]")] states, \"AUTH LOGIN: Welcome, [id_card.registered_name]. Access granted.\"") + return TRUE + + visible_message("[SPAN_BOLD("[src]")] states, \"AUTH ERROR: Access denied.\"") + return FALSE + + + + +/obj/structure/machinery/computer/working_joe/attack_hand(mob/user as mob) + if(..() || !allowed(usr) || inoperable()) + return FALSE + + tgui_interact(user) + return TRUE + +/obj/structure/machinery/computer/working_joe/tgui_interact(mob/user, datum/tgui/ui, datum/ui_state/state) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "WorkingJoe", name) + ui.open() + +/obj/structure/machinery/computer/working_joe/ui_data(mob/user) + var/list/data = list() + + data["ticket_console"] = ticket_console + data["current_menu"] = current_menu + data["last_page"] = last_menu + + data["logged_in"] = last_login + + data["access_text"] = "access level [authentication], [ares_auth_to_text(authentication)]." + data["access_level"] = authentication + + data["alert_level"] = security_level + data["worldtime"] = world.time + + data["access_log"] = list() + data["access_log"] += login_list + + data["apollo_log"] = list() + data["apollo_log"] += link.apollo_log + + data["authenticated"] = ticket_authenticated + + + var/list/logged_maintenance = list() + for(var/datum/ares_ticket/maintenance/maint_ticket as anything in link.tickets_maintenance) + if(!istype(maint_ticket)) + continue + var/list/current_maint = list() + current_maint["time"] = maint_ticket.ticket_time + current_maint["title"] = maint_ticket.ticket_name + current_maint["details"] = maint_ticket.ticket_details + current_maint["status"] = maint_ticket.ticket_status + current_maint["submitter"] = maint_ticket.ticket_submitter + current_maint["assignee"] = maint_ticket.ticket_assignee + current_maint["ref"] = "\ref[maint_ticket]" + logged_maintenance += list(current_maint) + data["maintenance_tickets"] = logged_maintenance + + var/list/logged_access = list() + for(var/datum/ares_ticket/access_ticket/access_ticket as anything in link.tickets_access) + var/list/current_ticket = list() + current_ticket["time"] = access_ticket.ticket_time + current_ticket["title"] = access_ticket.ticket_name + current_ticket["details"] = access_ticket.ticket_details + current_ticket["status"] = access_ticket.ticket_status + current_ticket["submitter"] = access_ticket.ticket_submitter + current_ticket["assignee"] = access_ticket.ticket_assignee + current_ticket["ref"] = "\ref[access_ticket]" + logged_access += list(current_ticket) + data["access_tickets"] = logged_access + + + return data + +/obj/structure/machinery/computer/working_joe/ui_static_data(mob/user) + var/list/data = list() + + data["link_id"] = link_id + + return data + +/obj/structure/machinery/computer/working_joe/ui_status(mob/user, datum/ui_state/state) + . = ..() + if(!allowed(user)) + return UI_UPDATE + if(inoperable()) + return UI_DISABLED + +/obj/structure/machinery/computer/working_joe/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + var/playsound = TRUE + var/mob/living/carbon/human/operator = usr + + switch (action) + if("go_back") + if(!last_menu) + return to_chat(usr, SPAN_WARNING("Error, no previous page detected.")) + var/temp_holder = current_menu + current_menu = last_menu + last_menu = temp_holder + + if("login") + + var/obj/item/card/id/idcard = operator.get_active_hand() + if(istype(idcard)) + authentication = get_ares_access(idcard) + last_login = idcard.registered_name + else if(operator.wear_id) + idcard = operator.wear_id + if(istype(idcard)) + authentication = get_ares_access(idcard) + last_login = idcard.registered_name + else + to_chat(usr, SPAN_WARNING("You require an ID card to access this terminal!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(authentication) + login_list += "[last_login] at [worldtime2text()], Access Level [authentication] - [ares_auth_to_text(authentication)]." + current_menu = "main" + + if("logout") + last_menu = current_menu + current_menu = "login" + login_list += "[last_login] logged out at [worldtime2text()]." + + if("home") + last_menu = current_menu + current_menu = "main" + if("page_logins") + last_menu = current_menu + current_menu = "login_records" + if("page_apollo") + last_menu = current_menu + current_menu = "apollo" + if("page_request") + last_menu = current_menu + current_menu = "access_requests" + if("page_returns") + last_menu = current_menu + current_menu = "access_returns" + if("page_report") + last_menu = current_menu + current_menu = "maint_reports" + if("page_tickets") + last_menu = current_menu + current_menu = "access_tickets" + if("page_maintenance") + last_menu = current_menu + current_menu = "maint_claim" + + if("new_report") + var/name = tgui_input_text(usr, "What is the type of maintenance item you wish to report?\n\nExample:\n 'Broken light in Aft Hallway.'", "Ticket Name", encode = FALSE) + if(!name) + return FALSE + var/details = tgui_input_text(usr, "What are the details for this report?", "Ticket Details", encode = FALSE) + if(!details) + return FALSE + var/confirm = tgui_alert(usr, "Please confirm the submission of your maintenance report. \n\n [name] \n\n [details] \n\n Is this correct?", "Confirmation", list("Yes", "No")) + if(confirm == "Yes") + if(link) + var/datum/ares_ticket/maintenance/maint_ticket = new(last_login, name, details) + link.tickets_maintenance += maint_ticket + log_game("ARES: Maintenance Ticket created by [key_name(operator)] as [last_login] with Header '[name]' and Details of '[details]'.") + return TRUE + return FALSE + + if(playsound) + playsound(src, "keyboard_alt", 15, 1) diff --git a/code/game/machinery/ARES/ARES_records.dm b/code/game/machinery/ARES/ARES_records.dm new file mode 100644 index 000000000000..9cb8574e58f7 --- /dev/null +++ b/code/game/machinery/ARES/ARES_records.dm @@ -0,0 +1,99 @@ +/datum/ares_record + var/record_name = "ARES Data Core" + /// World time in text format. + var/time + /// The title of the record, usually announcement title. + var/title + /// The content of the record, announcement text/bioscan info etc. + var/details + /// The name of the initiator of certain records. Who fired an OB, or who deleted something etc. + var/user + +/datum/ares_record/New(title, details) + time = worldtime2text() + src.title = title + src.details = details + +/datum/ares_record/announcement + record_name = ARES_RECORD_ANNOUNCE + +/datum/ares_record/bioscan + record_name = ARES_RECORD_BIOSCAN + +/datum/ares_record/requisition_log + record_name = ARES_RECORD_ASRS + +/datum/ares_record/requisition_log/New(title, details, user) + time = worldtime2text() + src.title = title + src.details = details + src.user = user + +/datum/ares_record/security + record_name = ARES_RECORD_SECURITY + +/datum/ares_record/antiair + record_name = ARES_RECORD_ANTIAIR + +/datum/ares_record/antiair/New(details, user) + time = worldtime2text() + src.title = "AntiAir Adjustment" + src.details = details + src.user = user + +/datum/ares_record/bombardment + record_name = ARES_RECORD_BOMB + +/datum/ares_record/bombardment/New(title, details, user) + time = worldtime2text() + src.title = title + src.details = details + src.user = user + +/datum/ares_record/deletion + record_name = ARES_RECORD_DELETED + +/datum/ares_record/deletion/New() + time = worldtime2text() + +/datum/ares_record/talk_log + record_name = "1:1 Data Log" + var/conversation = list() + +/datum/ares_record/talk_log/New(user) + src.user = user + src.title = "1:1 Log ([user])" + +/datum/ares_record/deleted_talk + record_name = ARES_RECORD_DELETED + var/conversation = list() + +/datum/ares_record/deleted_talk/New() + time = worldtime2text() + + +/datum/ares_ticket + var/ticket_type = "Root Ticket" + var/ticket_status = TICKET_PENDING + /// Name of who is handling the ticket. Derived from last login. + var/ticket_assignee + /// World time in text format. + var/ticket_time + /// Who submitted the ticket. Derived from last login. + var/ticket_submitter + /// The name of the ticket. + var/ticket_name + /// The content of the ticket, usually an explanation of what it is for. + var/ticket_details + +/datum/ares_ticket/New(user, name, details) + ticket_time = worldtime2text() + ticket_submitter = user + ticket_details = details + ticket_name = name + +/datum/ares_ticket/maintenance + ticket_type = ARES_RECORD_MAINTENANCE + +/datum/ares_ticket/access_ticket + ticket_type = ARES_RECORD_ACCESS diff --git a/code/game/machinery/ARES/ARES_step_triggers.dm b/code/game/machinery/ARES/ARES_step_triggers.dm new file mode 100644 index 000000000000..1562f1badaab --- /dev/null +++ b/code/game/machinery/ARES/ARES_step_triggers.dm @@ -0,0 +1,197 @@ +/obj/effect/step_trigger/ares_alert + name = "ARES Apollo Sensor" + layer = 5 + /// Link alerts to ARES Link + var/datum/ares_link/link + var/link_id = MAIN_SHIP_DEFAULT_NAME + /// Alert message to report unless area based. + var/alert_message = "ALERT: Unauthorized movement detected in ARES Core!" + /// Connect alerts to use same cooldowns + var/alert_id + /// Set to true if it should report area name and not specific alert. + var/area_based = FALSE + /// Cooldown duration and next time. + var/cooldown_duration = COOLDOWN_ARES_SENSOR + COOLDOWN_DECLARE(sensor_cooldown) + /// The job on a mob to enter + var/list/pass_jobs = list(JOB_WORKING_JOE, JOB_CHIEF_ENGINEER, JOB_CO) + /// The accesses on an ID card to enter + var/pass_accesses = list(ACCESS_MARINE_AI, ACCESS_ARES_DEBUG) + +/obj/effect/step_trigger/ares_alert/Crossed(mob/living/passer) + if(!COOLDOWN_FINISHED(src, sensor_cooldown))//Don't want alerts spammed. + return FALSE + if(!passer) + return FALSE + if(!(ishuman(passer) || isxeno(passer))) + return FALSE + if(passer.alpha <= 100)//Can't be seen/detected to trigger alert. + return FALSE + if(pass_jobs) + if(passer.job in pass_jobs) + return FALSE + if(isxeno(passer) && (JOB_XENOMORPH in pass_jobs)) + return FALSE + if(ishuman(passer)) + var/mob/living/carbon/human/trespasser = passer + if(pass_accesses && (trespasser.wear_id)) + for(var/tag in pass_accesses) + if(tag in trespasser.wear_id.access) + return FALSE + Trigger(passer) + return TRUE + + +/obj/effect/step_trigger/ares_alert/Initialize(mapload, ...) + link_systems(override = FALSE) + . = ..() + +/obj/effect/step_trigger/ares_alert/Destroy() + delink() + return ..() + +/obj/effect/step_trigger/ares_alert/proc/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + if(link && !override) + return FALSE + if(new_link.link_id == link_id) + link = new_link + new_link.linked_alerts += src + return TRUE +/obj/effect/step_trigger/ares_alert/proc/delink() + if(link) + link.linked_alerts -= src + link = null + + +/obj/effect/step_trigger/ares_alert/Trigger(mob/living/passer) + var/broadcast_message = alert_message + if(area_based) + var/area_name = get_area_name(src, TRUE) + broadcast_message = "ALERT: Unauthorized movement detected in [area_name]!" + + var/datum/ares_link/link = GLOB.ares_link + if(link.p_apollo.inoperable()) + return FALSE + + to_chat(passer, SPAN_BOLDWARNING("You hear a soft beeping sound as you cross the threshold.")) + var/datum/language/apollo/apollo = GLOB.all_languages[LANGUAGE_APOLLO] + for(var/mob/living/silicon/decoy/ship_ai/ai in ai_mob_list) + apollo.broadcast(ai, broadcast_message) + for(var/mob/listener as anything in (GLOB.human_mob_list + GLOB.dead_mob_list)) + if(listener.hear_apollo())//Only plays sound to mobs and not observers, to reduce spam. + playsound_client(listener.client, sound('sound/misc/interference.ogg'), listener, vol = 45) + COOLDOWN_START(src, sensor_cooldown, cooldown_duration) + if(alert_id && link) + for(var/obj/effect/step_trigger/ares_alert/sensor in link.linked_alerts) + if(sensor.alert_id == src.alert_id) + COOLDOWN_START(sensor, sensor_cooldown, cooldown_duration) + return TRUE + +/obj/effect/step_trigger/ares_alert/public + pass_accesses = list(ACCESS_MARINE_AI_TEMP, ACCESS_MARINE_AI, ACCESS_ARES_DEBUG) +/obj/effect/step_trigger/ares_alert/core + alert_id = "AresCore" + pass_accesses = list(ACCESS_MARINE_AI_TEMP, ACCESS_MARINE_AI, ACCESS_ARES_DEBUG) + +/obj/effect/step_trigger/ares_alert/mainframe + alert_id = "AresMainframe" + alert_message = "ALERT: Unauthorized movement detected in ARES Mainframe!" + +/obj/effect/step_trigger/ares_alert/terminals + alert_id = "AresTerminals" + alert_message = "ALERT: Unauthorized movement detected in ARES' Operations Center!" + +/obj/effect/step_trigger/ares_alert/comms + area_based = TRUE + alert_id = "TComms" + pass_accesses = list(ACCESS_MARINE_CE) + + +/// Trigger will remove ACCESS_MARINE_AI_TEMP unless ACCESS_MARINE_AI is also present. +/obj/effect/step_trigger/ares_alert/access_control + name = "ARES Access Control Sensor" + alert_message = "HARDCODED" + alert_id = "ARES Access" + cooldown_duration = COOLDOWN_ARES_ACCESS_CONTROL + + +/obj/effect/step_trigger/ares_alert/access_control/Crossed(atom/passer as mob|obj) + if(isobserver(passer) || isxeno(passer)) + return FALSE + if(!COOLDOWN_FINISHED(src, sensor_cooldown))//Don't want alerts spammed. + return FALSE + if(!passer) + return FALSE + if(passer.alpha <= 100)//Can't be seen/detected to trigger alert. + return FALSE + var/area/pass_area = get_area(get_step(passer, passer.dir)) + if(istype(pass_area, /area/almayer/command/airoom))//Don't want it to freak out over someone /entering/ the area. Only leaving. + return FALSE + var/obj/item/card/id/idcard + var/check_contents = TRUE + if(ishuman(passer)) + var/mob/living/carbon/human/human_passer = passer + idcard = human_passer.wear_id + if(istype(idcard)) + check_contents = FALSE + else + idcard = null + + if(istype(passer, /obj/item/card/id)) + idcard = passer + check_contents = FALSE + + if(check_contents) + idcard = locate(/obj/item/card/id) in passer + if(!idcard) + for(var/obj/item/holder in passer.contents) + idcard = locate(/obj/item/card/id) in holder.contents + if(idcard) + break + if(!istype(idcard) && ismob(passer)) + Trigger(passer, failure = TRUE) + return FALSE + if(!(ACCESS_MARINE_AI_TEMP in idcard.access))//No temp access, don't care + return FALSE + if((ACCESS_MARINE_AI in idcard.access) || (ACCESS_ARES_DEBUG in idcard.access))//Permanent access prevents loss of temporary + return FALSE + Trigger(passer, idcard) + return TRUE + +/obj/effect/step_trigger/ares_alert/access_control/Trigger(atom/passer, obj/item/card/id/idcard, failure = FALSE) + var/broadcast_message = get_broadcast(passer, idcard, failure) + + var/datum/ares_link/link = GLOB.ares_link + if(link.p_apollo.inoperable()) + return FALSE + + to_chat(passer, SPAN_BOLDWARNING("You hear a harsh buzzing sound as you cross the threshold!")) + var/datum/language/apollo/apollo = GLOB.all_languages[LANGUAGE_APOLLO] + for(var/mob/living/silicon/decoy/ship_ai/ai in ai_mob_list) + apollo.broadcast(ai, broadcast_message) + for(var/mob/listener in (GLOB.human_mob_list + GLOB.dead_mob_list)) + if(listener.hear_apollo())//Only plays sound to mobs and not observers, to reduce spam. + playsound_client(listener.client, sound('sound/misc/interference.ogg'), listener, vol = 45) + if(idcard) + idcard.access -= ACCESS_MARINE_AI_TEMP + COOLDOWN_START(src, sensor_cooldown, COOLDOWN_ARES_ACCESS_CONTROL) + if(alert_id && link) + for(var/obj/effect/step_trigger/ares_alert/sensor in link.linked_alerts) + if(sensor.alert_id == src.alert_id) + COOLDOWN_START(sensor, sensor_cooldown, COOLDOWN_ARES_ACCESS_CONTROL) + return TRUE + +/obj/effect/step_trigger/ares_alert/access_control/proc/get_broadcast(atom/passer, obj/item/card/id/idcard, failure = FALSE) + if(isxeno(passer)) + return "Unidentified lifeform detected departing AI Chamber." + if(ishuman(passer)) + var/mob/living/carbon/human/human_passer = passer + if(failure) + return "CAUTION: [human_passer.name] left the AI Chamber without a locatable ID card." + return "ALERT: [human_passer.name] left the AI Chamber with a temporary access ticket. Removing access." + + if(idcard) + return "ALERT: ID Card assigned to [idcard.registered_name] left the AI Chamber with a temporary access ticket. Removing access." + + log_debug("ARES ERROR 337: Passer: '[passer]', ID: '[idcard]', F Status: '[failure]'") + return "Warning: Error 337 - Access Control Anomaly." diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 1a15d40eba9c..a8735cbc06a8 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -110,6 +110,10 @@ /obj/structure/machinery/camera/autoname/almayer/containment/hidden network = list(CAMERA_NET_CONTAINMENT_HIDDEN) +/obj/structure/machinery/camera/autoname/almayer/containment/ares + name = "ares core camera" + network = list(CAMERA_NET_ALMAYER, CAMERA_NET_ARES) + //used by the landing camera dropship equipment. Do not place them right under where the dropship lands. //Should place them near each corner of your LZs. /obj/structure/machinery/camera/autoname/lz_camera diff --git a/code/game/machinery/computer/almayer_control.dm b/code/game/machinery/computer/almayer_control.dm index ec4abc68511b..b2a931224464 100644 --- a/code/game/machinery/computer/almayer_control.dm +++ b/code/game/machinery/computer/almayer_control.dm @@ -118,7 +118,7 @@ return FALSE usr.set_interaction(src) - + var/datum/ares_link/link = GLOB.ares_link switch(href_list["operation"]) if("main") state = STATE_DEFAULT @@ -163,6 +163,7 @@ log_game("[key_name(usr)] has called for an emergency evacuation.") message_admins("[key_name_admin(usr)] has called for an emergency evacuation.") + link.log_ares_security("Initiate Evacuation", "[usr] has called for an emergency evacuation.") return TRUE state = STATE_EVACUATION @@ -182,6 +183,7 @@ log_game("[key_name(usr)] has canceled the emergency evacuation.") message_admins("[key_name_admin(usr)] has canceled the emergency evacuation.") + link.log_ares_security("Cancel Evacuation", "[usr] has cancelled the emergency evacuation.") return TRUE state = STATE_EVACUATION_CANCEL diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm index d7fe2ed83e02..d4feca457f4a 100644 --- a/code/game/machinery/computer/camera_console.dm +++ b/code/game/machinery/computer/camera_console.dm @@ -318,6 +318,10 @@ name = "Containment Cameras" network = list(CAMERA_NET_CONTAINMENT) +/obj/structure/machinery/computer/cameras/almayer/ares + name = "ARES Core Cameras" + network = list(CAMERA_NET_ARES) + /obj/structure/machinery/computer/cameras/almayer/vehicle name = "Ship Security Cameras" network = list(CAMERA_NET_ALMAYER, CAMERA_NET_VEHICLE) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 2a7b5017d1ed..edc39faf3ddc 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -65,6 +65,7 @@ if(..()) return FALSE usr.set_interaction(src) + var/datum/ares_link/link = GLOB.ares_link switch(href_list["operation"]) if("mapview") tacmap.tgui_interact(usr) @@ -148,6 +149,7 @@ log_game("[key_name(usr)] has called for an emergency evacuation.") message_admins("[key_name_admin(usr)] has called for an emergency evacuation.") + link.log_ares_security("Initiate Evacuation", "[usr] has called for an emergency evacuation.") return TRUE state = STATE_EVACUATION @@ -167,6 +169,7 @@ log_game("[key_name(usr)] has canceled the emergency evacuation.") message_admins("[key_name_admin(usr)] has canceled the emergency evacuation.") + link.log_ares_security("Cancel Evacuation", "[usr] has cancelled the emergency evacuation.") return TRUE state = STATE_EVACUATION_CANCEL diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm index 40bdd68b3b34..8be8609d6008 100644 --- a/code/game/machinery/door_control.dm +++ b/code/game/machinery/door_control.dm @@ -52,6 +52,11 @@ /obj/structure/machinery/door_control/attackby(obj/item/W, mob/user as mob) return src.attack_hand(user) +/obj/structure/machinery/door_control/ex_act(severity) + if(indestructible) + return FALSE + ..() + /obj/structure/machinery/door_control/proc/handle_dropship(ship_id) var/obj/docking_port/mobile/marine_dropship/shuttle = SSshuttle.getShuttle(ship_id) if (!istype(shuttle)) diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index 972ce6b7570e..da6137e5e8cb 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -287,10 +287,13 @@ /obj/structure/machinery/door/poddoor/almayer/blended icon_state = "almayer_pdoor1" base_icon_state = "almayer_pdoor" - +/obj/structure/machinery/door/poddoor/almayer/blended/open + density = FALSE /obj/structure/machinery/door/poddoor/almayer/blended/white icon_state = "w_almayer_pdoor1" base_icon_state = "w_almayer_pdoor" +/obj/structure/machinery/door/poddoor/almayer/blended/white/open + density = FALSE /obj/structure/machinery/door/poddoor/almayer/Initialize() . = ..() diff --git a/code/game/machinery/doors/railing.dm b/code/game/machinery/doors/railing.dm index 145a5d8191dc..8449d5d52256 100644 --- a/code/game/machinery/doors/railing.dm +++ b/code/game/machinery/doors/railing.dm @@ -19,7 +19,8 @@ . = ..() if(dir == SOUTH) closed_layer = ABOVE_MOB_LAYER - layer = closed_layer + if(density)//Allows preset-open to work + layer = closed_layer SetOpacity(initial(opacity)) @@ -63,3 +64,6 @@ addtimer(VARSET_CALLBACK(src, operating, FALSE), 1.2 SECONDS) return TRUE + +/obj/structure/machinery/door/poddoor/railing/open + density = FALSE diff --git a/code/game/objects/items/devices/cictablet.dm b/code/game/objects/items/devices/cictablet.dm index 2650a3057503..1a4aebe813cc 100644 --- a/code/game/objects/items/devices/cictablet.dm +++ b/code/game/objects/items/devices/cictablet.dm @@ -145,6 +145,8 @@ log_game("[key_name(usr)] has called for an emergency evacuation.") message_admins("[key_name_admin(usr)] has called for an emergency evacuation.") + var/datum/ares_link/link = GLOB.ares_link + link.log_ares_security("Initiate Evacuation", "[usr] has called for an emergency evacuation.") . = TRUE if("distress") diff --git a/code/game/objects/structures/misc.dm b/code/game/objects/structures/misc.dm index 60f29c8b40e4..9323bca2877e 100644 --- a/code/game/objects/structures/misc.dm +++ b/code/game/objects/structures/misc.dm @@ -143,7 +143,7 @@ unslashable = TRUE unacidable = TRUE health = null - layer = TURF_LAYER + layer = ABOVE_TURF_LAYER//Being on turf layer was causing issues with cameras. This SHOULDN'T cause any problems. plane = FLOOR_PLANE density = FALSE opacity = FALSE diff --git a/code/game/objects/structures/pipes/pipes.dm b/code/game/objects/structures/pipes/pipes.dm index aa5f56fb5d8c..9f2b70c70661 100644 --- a/code/game/objects/structures/pipes/pipes.dm +++ b/code/game/objects/structures/pipes/pipes.dm @@ -14,6 +14,8 @@ var/ventcrawl_message_busy = FALSE //Prevent spamming + /// Whether or not the pipe will explode (when on the Almayer) during hijack + var/explodey = TRUE /// The grenade subtypes that pipes will use when they explode var/static/list/exploding_types = list(/obj/item/explosive/grenade/high_explosive/bursting_pipe, /obj/item/explosive/grenade/incendiary/bursting_pipe) @@ -40,7 +42,8 @@ if(!is_mainship_level(z)) return - GLOB.mainship_pipes += src + if(explodey) + GLOB.mainship_pipes += src /obj/structure/pipes/Destroy() for(var/mob/living/M in src) diff --git a/code/game/objects/structures/pipes/standard/manifolds.dm b/code/game/objects/structures/pipes/standard/manifolds.dm index f7bd04ee3fb7..dfbc027455b6 100644 --- a/code/game/objects/structures/pipes/standard/manifolds.dm +++ b/code/game/objects/structures/pipes/standard/manifolds.dm @@ -104,6 +104,10 @@ layer = ATMOS_PIPE_SUPPLY_LAYER color = PIPE_COLOR_BLUE +/obj/structure/pipes/standard/manifold/hidden/supply/no_boom + name = "Reinforced Air supply pipe manifold" + explodey = FALSE + /obj/structure/pipes/standard/manifold/hidden/yellow color = PIPE_COLOR_YELLOW @@ -182,6 +186,10 @@ layer = ATMOS_PIPE_SUPPLY_LAYER color = PIPE_COLOR_BLUE +/obj/structure/pipes/standard/manifold/fourway/hidden/supply/no_boom + name = "reinforced 4-way air supply pipe manifold" + explodey = FALSE + /obj/structure/pipes/standard/manifold/fourway/hidden/yellow color = PIPE_COLOR_YELLOW diff --git a/code/game/objects/structures/pipes/standard/simple.dm b/code/game/objects/structures/pipes/standard/simple.dm index 7101bb3dd95f..93a92e51f71b 100644 --- a/code/game/objects/structures/pipes/standard/simple.dm +++ b/code/game/objects/structures/pipes/standard/simple.dm @@ -104,6 +104,10 @@ layer = ATMOS_PIPE_SUPPLY_LAYER color = PIPE_COLOR_BLUE +/obj/structure/pipes/standard/simple/hidden/supply/no_boom + name = "Reinforced Air supply pipe" + explodey = FALSE + /obj/structure/pipes/standard/simple/hidden/yellow color = PIPE_COLOR_YELLOW diff --git a/code/game/objects/structures/pipes/standard/standard_misc.dm b/code/game/objects/structures/pipes/standard/standard_misc.dm index a50774552b03..dc52da57c750 100644 --- a/code/game/objects/structures/pipes/standard/standard_misc.dm +++ b/code/game/objects/structures/pipes/standard/standard_misc.dm @@ -107,6 +107,10 @@ layer = ATMOS_PIPE_SUPPLY_LAYER color = PIPE_COLOR_BLUE +/obj/structure/pipes/standard/cap/hidden/supply/no_boom + name = "reinforced supply pipe endcap" + explodey = FALSE + /obj/structure/pipes/standard/tank icon = 'icons/obj/pipes/tank.dmi' diff --git a/code/game/objects/structures/pipes/vents/pump_scrubber.dm b/code/game/objects/structures/pipes/vents/pump_scrubber.dm index d0dd3f8301a7..a4565c610ad5 100644 --- a/code/game/objects/structures/pipes/vents/pump_scrubber.dm +++ b/code/game/objects/structures/pipes/vents/pump_scrubber.dm @@ -4,6 +4,10 @@ name = "Air Scrubber" vent_icon = "scrubber" +/obj/structure/pipes/vents/scrubber/no_boom + name = "Reinforced Air Scrubber" + explodey = FALSE + /obj/structure/pipes/vents/scrubber/on icon_state = "on" @@ -13,6 +17,10 @@ icon_state = "map_vent" name = "Air Vent" +/obj/structure/pipes/vents/pump/no_boom + name = "Reinforced Air Vent" + explodey = FALSE + /obj/structure/pipes/vents/pump/on icon_state = "on" diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index cacb8232fd60..fbd6920875ad 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -70,7 +70,7 @@ /obj/structure/sign/kiddieplaque name = "AI developers plaque" - desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child appears to be retarded. Beneath the image, someone has scratched the word \"PACKETS\"" + desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. Beneath the image, someone has scratched the word \"PACKETS\"" icon_state = "kiddieplaque" /obj/structure/sign/arcturianstopsign diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 7537d47c941f..4186ae8608a9 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -295,6 +295,11 @@ name = "Delta squad chair" desc = "A simple chair permanently attached to the floor. Covered with a squeaky and way too hard faux-leather, unevenly painted in Delta squad blue. This chair is most likely to be the first to fight and first to die." +/obj/structure/bed/chair/comfy/ares + icon_state = "comfychair_ares" + name = "AI core chair" + desc = "A functional chair designed for comfortably sitting a single person with intent to facilitate interactions with the ship AI." + /obj/structure/bed/chair/office anchored = FALSE drag_delay = 1 //Pulling something on wheels is easy diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index dcc854bfa71d..b760340004f5 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -1015,6 +1015,7 @@ var/datum/controller/supply/supply_controller = new() to_chat(usr, SPAN_DANGER("Current retrieval load has reached maximum capacity.")) return + var/datum/ares_link/link = GLOB.ares_link for(var/i=1, i<=supply_controller.requestlist.len, i++) var/datum/supply_order/SO = supply_controller.requestlist[i] if(SO.ordernum == ordernum) @@ -1030,6 +1031,12 @@ var/datum/controller/supply/supply_controller = new() temp += "
Back Main Menu" supply_order.approvedby = usr.name msg_admin_niche("[usr] confirmed supply order of [supply_pack.name].") + var/pack_source = "Cargo Hold" + var/pack_name = supply_pack.name + if(supply_pack.dollar_cost) + pack_source = "Unknown" + pack_name = "Unknown" + link.log_ares_requisition(pack_source, pack_name, usr) else temp = "Not enough money left.
" temp += "
Back Main Menu" diff --git a/code/game/turfs/floor_types.dm b/code/game/turfs/floor_types.dm index 25682f00df29..4e47fd004f74 100644 --- a/code/game/turfs/floor_types.dm +++ b/code/game/turfs/floor_types.dm @@ -272,7 +272,9 @@ /turf/open/floor/almayer/uscm/directional icon_state = "logo_directional" - +/turf/open/floor/almayer/no_build + allow_construction = FALSE + hull_floor = TRUE // RESEARCH STUFF /turf/open/floor/almayer/research/containment/entrance diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index debffa9b25b0..ba5d52a23f97 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -67,6 +67,7 @@ var/list/admin_verbs_default = list( /datum/admins/proc/subtlemessageall, /datum/admins/proc/alertall, /datum/admins/proc/imaginary_friend, + /client/proc/toggle_ares_ping, ) var/list/admin_verbs_admin = list( @@ -577,6 +578,16 @@ var/list/roundstart_mod_verbs = list( message_admins("[key_name(usr)] announced a random fact.") SSticker.mode?.declare_fun_facts() +/client/proc/toggle_ares_ping() + set name = "Toggle ARES notification sound" + set category = "Preferences.Logs" + + prefs.toggles_sound ^= SOUND_ARES_MESSAGE + if (prefs.toggles_sound & SOUND_ARES_MESSAGE) + to_chat(usr, SPAN_BOLDNOTICE("You will now hear a ping for ARES messages.")) + else + to_chat(usr, SPAN_BOLDNOTICE("You will no longer hear a ping for ARES messages.")) + #undef MAX_WARNS #undef AUTOBANTIME diff --git a/code/modules/admin/tabs/admin_tab.dm b/code/modules/admin/tabs/admin_tab.dm index 11ee49b65e61..c0ffeada9883 100644 --- a/code/modules/admin/tabs/admin_tab.dm +++ b/code/modules/admin/tabs/admin_tab.dm @@ -680,10 +680,14 @@ /proc/set_lz_resin_allowed(allowed = TRUE) if(allowed) for(var/area/A in all_areas) + if(A.flags_area & AREA_UNWEEDABLE) + continue A.is_resin_allowed = TRUE msg_admin_niche("Areas close to landing zones are now weedable.") else for(var/area/A in all_areas) + if(A.flags_area & AREA_UNWEEDABLE) + continue A.is_resin_allowed = initial(A.is_resin_allowed) msg_admin_niche("Areas close to landing zones cannot be weeded now.") GLOB.resin_lz_allowed = allowed diff --git a/code/modules/admin/tabs/event_tab.dm b/code/modules/admin/tabs/event_tab.dm index 8fca782ecd63..20d98776c5ab 100644 --- a/code/modules/admin/tabs/event_tab.dm +++ b/code/modules/admin/tabs/event_tab.dm @@ -440,7 +440,7 @@ return var/confirm = tgui_alert(usr, "Are you sure you want to hijack [dropship]?", "Force hijack", list("Yes", "No")) == "Yes" - if(!confirm) + if(!confirm) return var/obj/structure/machinery/computer/shuttle/dropship/flight/computer = dropship.getControlConsole() @@ -535,19 +535,15 @@ if(!input) return FALSE - for(var/obj/structure/machinery/computer/almayer_control/C in machines) - if(!(C.inoperable())) -// var/obj/item/paper/P = new /obj/item/paper(C.loc)//Don't need a printed copy currently. -// P.name = "'[MAIN_AI_SYSTEM] Update.'" -// P.info = input -// P.update_icon() - C.messagetitle.Add("[MAIN_AI_SYSTEM] Update") - C.messagetext.Add(input) - ai_announcement(input) - message_admins("[key_name_admin(src)] has created an AI comms report") - log_admin("AI comms report: [input]") - else - to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It may be offline or destroyed.")) + var/datum/ares_link/link = GLOB.ares_link + if(link.p_interface.inoperable()) + to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It may be offline or destroyed.")) + return + + ai_announcement(input) + message_admins("[key_name_admin(src)] has created an AI comms report") + log_admin("AI comms report: [input]") + /client/proc/cmd_admin_create_AI_apollo_report() set name = "Report: ARES Apollo" @@ -560,19 +556,19 @@ if(!input) return FALSE - for(var/obj/structure/machinery/computer/almayer_control/console in machines) - if(console.inoperable()) - to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It may be offline or destroyed.")) - return - else - var/datum/language/apollo = GLOB.all_languages[LANGUAGE_APOLLO] - for(var/mob/living/silicon/decoy/ship_ai/AI in ai_mob_list) - apollo.broadcast(AI, input) - for(var/mob/listener in (GLOB.human_mob_list + GLOB.dead_mob_list)) - if(listener.hear_apollo())//Only plays sound to mobs and not observers, to reduce spam. - playsound_client(listener.client, sound('sound/misc/interference.ogg'), listener, vol = 45) - message_admins("[key_name_admin(src)] has created an AI Apollo report") - log_admin("AI Apollo report: [input]") + var/datum/ares_link/link = GLOB.ares_link + if(link.p_apollo.inoperable()) + to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It may be offline or destroyed.")) + return FALSE + + var/datum/language/apollo/apollo = GLOB.all_languages[LANGUAGE_APOLLO] + for(var/mob/living/silicon/decoy/ship_ai/AI in ai_mob_list) + apollo.broadcast(AI, input) + for(var/mob/listener as anything in (GLOB.human_mob_list + GLOB.dead_mob_list)) + if(listener.hear_apollo())//Only plays sound to mobs and not observers, to reduce spam. + playsound_client(listener.client, sound('sound/misc/interference.ogg'), listener, vol = 45) + message_admins("[key_name_admin(src)] has created an AI APOLLO report") + log_admin("AI APOLLO report: [input]") /client/proc/cmd_admin_create_AI_shipwide_report() set name = "Report: ARES Shipwide" @@ -584,19 +580,14 @@ var/input = input(usr, "This is an announcement type message from the ship's AI. This will be announced to every conscious human on Almayer z-level. Be aware, this will work even if ARES unpowered/destroyed. Check with online staff before you send this.", "What?", "") as message|null if(!input) return FALSE + for(var/obj/structure/machinery/ares/processor/interface/processor in machines) + if(processor.inoperable()) + to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It may be offline or destroyed.")) + return - for(var/obj/structure/machinery/computer/almayer_control/C in machines) - if(!(C.inoperable())) -// var/obj/item/paper/P = new /obj/item/paper(C.loc)//Don't need a printed copy currently. -// P.name = "'[MAIN_AI_SYSTEM] Update.'" -// P.info = input -// P.update_icon() - C.messagetitle.Add("[MAIN_AI_SYSTEM] Shipwide Update") - C.messagetext.Add(input) - - shipwide_ai_announcement(input) - message_admins("[key_name_admin(src)] has created an AI shipwide report") - log_admin("[key_name_admin(src)] AI shipwide report: [input]") + shipwide_ai_announcement(input) + message_admins("[key_name_admin(src)] has created an AI shipwide report") + log_admin("[key_name_admin(src)] AI shipwide report: [input]") /client/proc/cmd_admin_create_predator_report() set name = "Report: Yautja AI" @@ -972,7 +963,11 @@ if("Xeno") GLOB.bioscan_data.qm_bioscan(variance) if("Marine") - GLOB.bioscan_data.ares_bioscan(FALSE, variance) + var/force_check = tgui_alert(usr, "Do you wish to force ARES to display the bioscan?", "Display force", list("Yes", "No"), 20 SECONDS) + var/force_status = FALSE + if(force_check == "Yes") + force_status = TRUE + GLOB.bioscan_data.ares_bioscan(force_status, variance) if("Yautja") GLOB.bioscan_data.yautja_bioscan() diff --git a/code/modules/admin/topic/topic.dm b/code/modules/admin/topic/topic.dm index 96c9312db7d1..b371db087be6 100644 --- a/code/modules/admin/topic/topic.dm +++ b/code/modules/admin/topic/topic.dm @@ -1882,7 +1882,7 @@ if(href_list["ccdeny"]) // CentComm-deny. The distress call is denied, without any further conditions var/mob/ref_person = locate(href_list["ccdeny"]) - marine_announcement("The distress signal has not received a response, the launch tubes are now recalibrating.", "Distress Beacon") + marine_announcement("The distress signal has not received a response, the launch tubes are now recalibrating.", "Distress Beacon", logging = ARES_LOG_SECURITY) log_game("[key_name_admin(usr)] has denied a distress beacon, requested by [key_name_admin(ref_person)]") message_admins("[key_name_admin(usr)] has denied a distress beacon, requested by [key_name_admin(ref_person)]", 1) @@ -1927,7 +1927,7 @@ if(href_list["sddeny"]) // CentComm-deny. The self-destruct is denied, without any further conditions var/mob/ref_person = locate(href_list["sddeny"]) - marine_announcement("The self-destruct request has not received a response, ARES is now recalculating statistics.", "Self-Destruct System") + marine_announcement("The self-destruct request has not received a response, ARES is now recalculating statistics.", "Self-Destruct System", logging = ARES_LOG_SECURITY) log_game("[key_name_admin(usr)] has denied self-destruct, requested by [key_name_admin(ref_person)]") message_admins("[key_name_admin(usr)] has denied self-destruct, requested by [key_name_admin(ref_person)]", 1) @@ -2006,6 +2006,45 @@ player_notes_all(checking.key) + if(href_list["AresReply"]) + var/mob/living/carbon/human/speaker = locate(href_list["AresReply"]) + + if(!istype(speaker)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return FALSE + + if((!GLOB.ares_link.interface) || (GLOB.ares_link.interface.inoperable())) + to_chat(usr, "ARES Interface offline.") + return FALSE + + var/input = input(src.owner, "Please enter a message from ARES to reply to [key_name(speaker)].","Outgoing message from ARES", "") + if(!input) + return FALSE + + to_chat(src.owner, "You sent [input] to [speaker] via ARES Interface.") + log_admin("[src.owner] replied to [key_name(speaker)]'s ARES message with the message [input].") + for(var/client/staff in GLOB.admins) + if((R_ADMIN|R_MOD) & staff.admin_holder.rights) + to_chat(staff, SPAN_STAFF_IC("ADMINS/MODS: [SPAN_RED("[src.owner] replied to [key_name(speaker)]'s ARES message")] with: [SPAN_BLUE(input)] ")) + GLOB.ares_link.interface.response_from_ares(input, href_list["AresRef"]) + + if(href_list["AresMark"]) + var/mob/living/carbon/human/speaker = locate(href_list["AresMark"]) + + if(!istype(speaker)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return FALSE + + if((!GLOB.ares_link.interface) || (GLOB.ares_link.interface.inoperable())) + to_chat(usr, "ARES Interface offline.") + return FALSE + + to_chat(src.owner, "You marked [speaker]'s ARES message for response.") + log_admin("[src.owner] marked [key_name(speaker)]'s ARES message. [src.owner] will be responding.") + for(var/client/staff in GLOB.admins) + if((R_ADMIN|R_MOD) & staff.admin_holder.rights) + to_chat(staff, SPAN_STAFF_IC("ADMINS/MODS: [SPAN_RED("[src.owner] marked [key_name(speaker)]'s ARES message for response.")]")) + return /datum/admins/proc/accept_ert(mob/approver, mob/ref_person) diff --git a/code/modules/cm_marines/anti_air.dm b/code/modules/cm_marines/anti_air.dm index 22d43456437b..fc67f9a2018d 100644 --- a/code/modules/cm_marines/anti_air.dm +++ b/code/modules/cm_marines/anti_air.dm @@ -102,6 +102,7 @@ var/obj/structure/anti_air_cannon/almayer_aa_cannon if(!almayer_aa_cannon) return + var/datum/ares_link/link = GLOB.ares_link switch(action) if("protect") almayer_aa_cannon.protecting_section = params["section_id"] @@ -109,10 +110,12 @@ var/obj/structure/anti_air_cannon/almayer_aa_cannon almayer_aa_cannon.protecting_section = "" return message_admins("[key_name(usr)] has set the AA to [html_encode(almayer_aa_cannon.protecting_section)].") + link.log_ares_antiair(usr, "Set AA to cover [html_encode(almayer_aa_cannon.protecting_section)].") . = TRUE if("deactivate") almayer_aa_cannon.protecting_section = "" message_admins("[key_name(usr)] has deactivated the AA cannon.") + link.log_ares_antiair(usr, "Deactivated Anti Air systems.") . = TRUE add_fingerprint(usr) diff --git a/code/modules/cm_marines/overwatch.dm b/code/modules/cm_marines/overwatch.dm index 401d8fd9784a..070cf1f6c1cf 100644 --- a/code/modules/cm_marines/overwatch.dm +++ b/code/modules/cm_marines/overwatch.dm @@ -866,6 +866,9 @@ message_admins(FONT_SIZE_HUGE("ALERT: [key_name(user)] fired an orbital bombardment in [A.name] for squad '[current_squad]' [ADMIN_JMP(T)]")) log_attack("[key_name(user)] fired an orbital bombardment in [A.name] for squad '[current_squad]'") + /// Project ARES interface log. + GLOB.ares_link.log_ares_bombardment(user, ob_name, "X[x_bomb], Y[y_bomb] in [A.name]") + busy = FALSE var/turf/target = locate(T.x + rand(-3, 3), T.y + rand(-3, 3), T.z) if(target && istype(target)) diff --git a/code/modules/cm_marines/smartgun_mount.dm b/code/modules/cm_marines/smartgun_mount.dm index ec79a2f7f3fd..2db33c10ed46 100644 --- a/code/modules/cm_marines/smartgun_mount.dm +++ b/code/modules/cm_marines/smartgun_mount.dm @@ -111,6 +111,11 @@ to_chat(usr, SPAN_WARNING("It's too cramped in here to deploy \a [src].")) return var/turf/T = get_turf(usr) + if(istype(T, /turf/open)) + var/turf/open/floor = T + if(!floor.allow_construction) + to_chat(user, SPAN_WARNING("You cannot install \the [src] here, find a more secure surface!")) + return FALSE var/fail = FALSE if(T.density) fail = TRUE @@ -195,6 +200,11 @@ to_chat(usr, SPAN_WARNING("It's too cramped in here to deploy \a [src].")) return var/turf/T = get_turf(user) + if(istype(T, /turf/open)) + var/turf/open/floor = T + if(!floor.allow_construction) + to_chat(user, SPAN_WARNING("You cannot install \the [src] here, find a more secure surface!")) + return FALSE var/fail = FALSE if(T.density) fail = TRUE @@ -370,6 +380,11 @@ if(fail) to_chat(user, SPAN_WARNING("You can't install \the [src] here, something is in the way.")) return + if(istype(T, /turf/open)) + var/turf/open/floor = T + if(!floor.allow_construction) + to_chat(user, SPAN_WARNING("You cannot install \the [src] here, find a more secure surface!")) + return FALSE if(gun_mounted) to_chat(user, "You're securing the M56D into place...") @@ -1061,7 +1076,7 @@ if(SSinterior.in_interior(user)) to_chat(usr, SPAN_WARNING("It's too cramped in here to deploy \a [src].")) return FALSE - if(OT.density || !isturf(OT)) + if(OT.density || !isturf(OT) || !OT.allow_construction) to_chat(user, SPAN_WARNING("You can't set up \the [src] here.")) return FALSE if(rotate_check.density) diff --git a/code/modules/defenses/defenses.dm b/code/modules/defenses/defenses.dm index ee6db2b10455..f47ae3e4d77b 100644 --- a/code/modules/defenses/defenses.dm +++ b/code/modules/defenses/defenses.dm @@ -303,6 +303,10 @@ playsound(src.loc, 'sound/items/Ratchet.ogg', 25, 1) return else + var/turf/open/floor = get_turf(src) + if(!floor.allow_construction) + to_chat(user, SPAN_WARNING("You cannot secure \the [src] here, find a more secure surface!")) + return FALSE user.visible_message(SPAN_NOTICE("[user] begins securing [src] to the ground."), SPAN_NOTICE("You begin securing [src] to the ground.")) diff --git a/code/modules/defenses/handheld.dm b/code/modules/defenses/handheld.dm index e68522871561..233dad313d25 100644 --- a/code/modules/defenses/handheld.dm +++ b/code/modules/defenses/handheld.dm @@ -66,7 +66,12 @@ blocked = TRUE break - if(istype(T, /turf/closed)) + if(istype(T, /turf/open)) + var/turf/open/floor = T + if(!floor.allow_construction) + to_chat(user, SPAN_WARNING("You cannot deploy \a [src] here, find a more secure surface!")) + return FALSE + else blocked = TRUE if(blocked) diff --git a/code/modules/gear_presets/uscm_ship.dm b/code/modules/gear_presets/uscm_ship.dm index 688a55d0f0f6..7aa9eabb3042 100644 --- a/code/modules/gear_presets/uscm_ship.dm +++ b/code/modules/gear_presets/uscm_ship.dm @@ -198,6 +198,7 @@ ACCESS_MARINE_MAINT, ACCESS_MARINE_OT, ACCESS_MARINE_SYNTH, + ACCESS_MARINE_AI, ) assignment = JOB_CHIEF_ENGINEER rank = JOB_CHIEF_ENGINEER diff --git a/code/modules/mob/language/languages.dm b/code/modules/mob/language/languages.dm index 546c2bf7714f..e5b693e02b80 100644 --- a/code/modules/mob/language/languages.dm +++ b/code/modules/mob/language/languages.dm @@ -147,7 +147,7 @@ /datum/language/apollo name = LANGUAGE_APOLLO - desc = "The Apollo Link is an AI subprocessor designed by SEEGSON, allowing for coordination of maintenance drones and Working Joes. WY denies claims the processor was stolen for ARES." + desc = "The APOLLO Link is an AI subprocessor designed by SEEGSON, allowing for coordination of maintenance drones and Working Joes. WY denies claims the processor was stolen for ARES." color = "skrell" speech_verb = "states" ask_verb = "queries" @@ -166,6 +166,8 @@ var/message_body = "broadcasts, \"[message]\"" GLOB.STUI.game.Add("\[[time_stamp()]]APOLLO: [key_name(speaker)] : [message]
") GLOB.STUI.processing |= STUI_LOG_GAME_CHAT + log_say("[speaker.name != "Unknown" ? speaker.name : "([speaker.real_name])"] \[APOLLO\]: [message] (CKEY: [speaker.key]) (JOB: [speaker.job])") + log_ares_apollo(speaker.real_name, message) for (var/mob/dead in GLOB.dead_mob_list) if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping dead.show_message("[message_start] [message_body]", SHOW_MESSAGE_VISIBLE) diff --git a/code/modules/mob/living/carbon/xenomorph/Abilities.dm b/code/modules/mob/living/carbon/xenomorph/Abilities.dm index dbadadf8ef23..eb5a629760ee 100644 --- a/code/modules/mob/living/carbon/xenomorph/Abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/Abilities.dm @@ -55,6 +55,9 @@ var/area/AR = get_area(T) if(isnull(AR) || !(AR.is_resin_allowed)) + if(AR.flags_area & AREA_UNWEEDABLE) + to_chat(X, SPAN_XENOWARNING("This area is unsuited to host the hive!")) + return to_chat(X, SPAN_XENOWARNING("It's too early to spread the hive this far.")) return diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm index 692fa31c72e7..921b61a23bc9 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm @@ -47,6 +47,9 @@ var/area/AR = get_area(T) if(isnull(AR) || !(AR.is_resin_allowed)) + if(AR.flags_area & AREA_UNWEEDABLE) + to_chat(X, SPAN_XENOWARNING("This area is unsuited to host the hive!")) + return to_chat(X, SPAN_XENOWARNING("It's too early to spread the hive this far.")) return @@ -597,6 +600,9 @@ var/area/AR = get_area(T) if(isnull(AR) || !(AR.is_resin_allowed)) + if(AR.flags_area & AREA_UNWEEDABLE) + to_chat(X, SPAN_XENOWARNING("This area is unsuited to host the hive!")) + return to_chat(X, SPAN_XENOWARNING("It's too early to spread the hive this far.")) return FALSE diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm index 944192530b0d..65ea443c133c 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm @@ -512,6 +512,9 @@ var/area/AR = get_area(T) if(!AR.is_resin_allowed) + if(AR.flags_area & AREA_UNWEEDABLE) + to_chat(X, SPAN_XENOWARNING("This area is unsuited to host the hive!")) + return to_chat(X, SPAN_XENOWARNING("It's too early to spread the hive this far.")) return diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm index 182d3d965832..fe4b4cca2fb1 100644 --- a/code/modules/mob/living/carbon/xenomorph/death.dm +++ b/code/modules/mob/living/carbon/xenomorph/death.dm @@ -117,7 +117,9 @@ // Tell the marines where the last one is. var/name = "[MAIN_AI_SYSTEM] Bioscan Status" var/input = "Bioscan complete.\n\nSensors indicate one remaining unknown lifeform signature in [get_area(X)]." - marine_announcement(input, name, 'sound/AI/bioscan.ogg') + var/datum/ares_link/link = GLOB.ares_link + link.log_ares_bioscan(name, input) + marine_announcement(input, name, 'sound/AI/bioscan.ogg', logging = ARES_LOG_NONE) // Tell the xeno she is the last one. if(X.client) to_chat(X, SPAN_XENOANNOUNCE("Your carapace rattles with dread. You are all that remains of the hive!")) diff --git a/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm b/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm index 4f3852a6a055..3bfb4e355416 100644 --- a/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm +++ b/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm @@ -31,6 +31,9 @@ GLOBAL_VAR_INIT(resin_lz_allowed, FALSE) var/area/AR = get_area(T) if(isnull(AR) || !(AR.is_resin_allowed)) + if(AR.flags_area & AREA_UNWEEDABLE) + to_chat(X, SPAN_XENOWARNING("This area is unsuited to host the hive!")) + return to_chat(X, SPAN_XENOWARNING("It's too early to spread the hive this far.")) return FALSE diff --git a/code/modules/mob/living/silicon/decoy/decoy.dm b/code/modules/mob/living/silicon/decoy/decoy.dm index abd07e056be7..b625b19b172d 100644 --- a/code/modules/mob/living/silicon/decoy/decoy.dm +++ b/code/modules/mob/living/silicon/decoy/decoy.dm @@ -10,6 +10,8 @@ bound_width = 96 custom_slashed_sound = "alien_claw_metal" var/obj/item/device/radio/headset/almayer/mcom/ai/ai_headset //The thing it speaks into. + maxHealth = 1000 + health = 1000 /mob/living/silicon/decoy/ship_ai //For the moment, pending better pathing. var/silent_announcement_cooldown = 0 @@ -20,6 +22,7 @@ desc = "This is the artificial intelligence system for the [MAIN_SHIP_NAME]. Like many other military-grade AI systems, this one was manufactured by Weyland-Yutani." ai_headset = new(src) ai_mob_list += src + real_name = MAIN_AI_SYSTEM /mob/living/silicon/decoy/ship_ai/Destroy() QDEL_NULL(ai_headset) diff --git a/code/modules/security_levels/security_levels.dm b/code/modules/security_levels/security_levels.dm index d8f61c11a3e6..be087444c99e 100644 --- a/code/modules/security_levels/security_levels.dm +++ b/code/modules/security_levels/security_levels.dm @@ -16,32 +16,32 @@ switch(level) if(SEC_LEVEL_GREEN) if(announce) - ai_announcement("Attention: Security level lowered to GREEN - all clear.", no_sound ? null : 'sound/AI/code_green.ogg') + ai_announcement("Attention: Security level lowered to GREEN - all clear.", no_sound ? null : 'sound/AI/code_green.ogg', ARES_LOG_SECURITY) security_level = SEC_LEVEL_GREEN if(SEC_LEVEL_BLUE) if(security_level < SEC_LEVEL_BLUE) if(announce) - ai_announcement("Attention: Security level elevated to BLUE - potentially hostile activity on board.", no_sound ? null : 'sound/AI/code_blue_elevated.ogg') + ai_announcement("Attention: Security level elevated to BLUE - potentially hostile activity on board.", no_sound ? null : 'sound/AI/code_blue_elevated.ogg', ARES_LOG_SECURITY) else if(announce) - ai_announcement("Attention: Security level lowered to BLUE - potentially hostile activity on board.", no_sound ? null : 'sound/AI/code_blue_lowered.ogg') + ai_announcement("Attention: Security level lowered to BLUE - potentially hostile activity on board.", no_sound ? null : 'sound/AI/code_blue_lowered.ogg', ARES_LOG_SECURITY) security_level = SEC_LEVEL_BLUE if(SEC_LEVEL_RED) if(security_level < SEC_LEVEL_RED) if(announce) - ai_announcement("Attention: Security level elevated to RED - there is an immediate threat to the ship.", no_sound ? null : 'sound/AI/code_red_elevated.ogg') + ai_announcement("Attention: Security level elevated to RED - there is an immediate threat to the ship.", no_sound ? null : 'sound/AI/code_red_elevated.ogg', ARES_LOG_SECURITY) else if(announce) - ai_announcement("Attention: Security level lowered to RED - there is an immediate threat to the ship.", no_sound ? null : 'sound/AI/code_red_lowered.ogg') + ai_announcement("Attention: Security level lowered to RED - there is an immediate threat to the ship.", no_sound ? null : 'sound/AI/code_red_lowered.ogg', ARES_LOG_SECURITY) security_level = SEC_LEVEL_RED if(SEC_LEVEL_DELTA) if(announce) var/name = "SELF-DESTRUCT SYSTEMS ACTIVE" var/input = "DANGER, THE EMERGENCY DESTRUCT SYSTEM IS NOW ACTIVATED. PROCEED TO THE SELF-DESTRUCT CHAMBER FOR CONTROL ROD INSERTION." - marine_announcement(input, name, 'sound/AI/selfdestruct_short.ogg') + marine_announcement(input, name, 'sound/AI/selfdestruct_short.ogg', logging = ARES_LOG_SECURITY) security_level = SEC_LEVEL_DELTA EvacuationAuthority.enable_self_destruct() diff --git a/code/modules/shuttle/computers/dropship_computer.dm b/code/modules/shuttle/computers/dropship_computer.dm index 19d9abfd81b4..ea4a7fdbc79d 100644 --- a/code/modules/shuttle/computers/dropship_computer.dm +++ b/code/modules/shuttle/computers/dropship_computer.dm @@ -267,7 +267,7 @@ hijack.fire() GLOB.alt_ctrl_disabled = TRUE - marine_announcement("Unscheduled dropship departure detected from operational area. Hijack likely. Shutting down autopilot.", "Dropship Alert", 'sound/AI/hijack.ogg') + marine_announcement("Unscheduled dropship departure detected from operational area. Hijack likely. Shutting down autopilot.", "Dropship Alert", 'sound/AI/hijack.ogg', logging = ARES_LOG_SECURITY) var/mob/living/carbon/xenomorph/xeno = user var/hivenumber = XENO_HIVE_NORMAL diff --git a/code/modules/shuttle/dropship_hijack.dm b/code/modules/shuttle/dropship_hijack.dm index 35009ad42485..ce151c14324c 100644 --- a/code/modules/shuttle/dropship_hijack.dm +++ b/code/modules/shuttle/dropship_hijack.dm @@ -123,7 +123,7 @@ if(!offset_target) offset_target = target // Welp the offsetting failed so... crash_site.forceMove(offset_target) - marine_announcement("A hostile aircraft on course for the [target_ship_section] has been successfully deterred.", "IX-50 MGAD System") + marine_announcement("A hostile aircraft on course for the [target_ship_section] has been successfully deterred.", "IX-50 MGAD System", logging = ARES_LOG_SECURITY) target_ship_section = new_target_ship_section // TODO mobs not alerted for(var/area/internal_area in shuttle.shuttle_areas) @@ -149,7 +149,7 @@ shuttle.crashing = TRUE - marine_announcement("DROPSHIP ON COLLISION COURSE. CRASH IMMINENT." , "EMERGENCY", 'sound/AI/dropship_emergency.ogg') + marine_announcement("DROPSHIP ON COLLISION COURSE. CRASH IMMINENT." , "EMERGENCY", 'sound/AI/dropship_emergency.ogg', logging = ARES_LOG_SECURITY) announce_dchat("The dropship is about to impact [get_area_name(crash_site)]", crash_site) final_announcement = TRUE @@ -202,7 +202,6 @@ turfs += get_area_turfs(/area/almayer/medical/hydroponics) if("Upper deck Aftship") turfs += get_area_turfs(/area/almayer/engineering/upper_engineering) - turfs += get_area_turfs(/area/almayer/command/computerlab) turfs += get_area_turfs(/area/almayer/engineering/laundry) if("Lower deck Foreship") turfs += get_area_turfs(/area/almayer/hallways/hangar) diff --git a/code/modules/shuttles/marine_ferry.dm b/code/modules/shuttles/marine_ferry.dm index 48a6c176293e..17caccde207e 100644 --- a/code/modules/shuttles/marine_ferry.dm +++ b/code/modules/shuttles/marine_ferry.dm @@ -414,7 +414,7 @@ // At halftime, we announce whether or not the AA forced the dropship to divert // The rounding is because transit time is decreased by 10 each loop. Travel time, however, might not be a multiple of 10 if(in_transit_time_left == round(travel_time / 2, 10) && true_crash_target_section != crash_target_section) - marine_announcement("A hostile aircraft on course for the [true_crash_target_section] has been successfully deterred.", "IX-50 MGAD System") + marine_announcement("A hostile aircraft on course for the [true_crash_target_section] has been successfully deterred.", "IX-50 MGAD System", logging = ARES_LOG_SECURITY) var/area/shuttle_area for(var/turf/T in turfs_int) @@ -438,7 +438,7 @@ //This is where things change and shit gets real - marine_announcement("DROPSHIP ON COLLISION COURSE. CRASH IMMINENT." , "EMERGENCY", 'sound/AI/dropship_emergency.ogg') + marine_announcement("DROPSHIP ON COLLISION COURSE. CRASH IMMINENT." , "EMERGENCY", 'sound/AI/dropship_emergency.ogg', logging = ARES_LOG_SECURITY) for(var/mob/dead/observer/observer as anything in GLOB.observer_list) to_chat(observer, SPAN_DEADSAY(FONT_SIZE_LARGE("The dropship is about to impact [get_area_name(T_trg)]" + " [OBSERVER_JMP(observer, T_trg)]"))) diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm index e765851c3b29..ecf1bacf080b 100644 --- a/code/modules/shuttles/shuttle_console.dm +++ b/code/modules/shuttles/shuttle_console.dm @@ -291,7 +291,7 @@ GLOBAL_LIST_EMPTY(shuttle_controls) if(round_statistics) round_statistics.track_hijack() - marine_announcement("Unscheduled dropship departure detected from operational area. Hijack likely. Shutting down autopilot.", "Dropship Alert", 'sound/AI/hijack.ogg') + marine_announcement("Unscheduled dropship departure detected from operational area. Hijack likely. Shutting down autopilot.", "Dropship Alert", 'sound/AI/hijack.ogg', logging = ARES_LOG_SECURITY) shuttle.alerts_allowed-- to_chat(Q, SPAN_DANGER("A loud alarm erupts from [src]! The fleshy hosts must know that you can access it!")) diff --git a/colonialmarines.dme b/colonialmarines.dme index 991c23d53bbe..ebd73b3544dd 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -31,6 +31,7 @@ #include "code\__DEFINES\_tick.dm" #include "code\__DEFINES\access.dm" #include "code\__DEFINES\admin.dm" +#include "code\__DEFINES\ARES.dm" #include "code\__DEFINES\atmospherics.dm" #include "code\__DEFINES\autolathe.dm" #include "code\__DEFINES\blood.dm" @@ -774,6 +775,10 @@ #include "code\game\machinery\teleporter.dm" #include "code\game\machinery\washing_machine.dm" #include "code\game\machinery\weather_siren.dm" +#include "code\game\machinery\ARES\ARES.dm" +#include "code\game\machinery\ARES\ARES_procs.dm" +#include "code\game\machinery\ARES\ARES_records.dm" +#include "code\game\machinery\ARES\ARES_step_triggers.dm" #include "code\game\machinery\atmoalter\canister.dm" #include "code\game\machinery\atmoalter\meter.dm" #include "code\game\machinery\atmoalter\portable_atmospherics.dm" diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi index 08a5c5fa8ef126487f6225627f74361015d8d72c..b62860559b16ea99d2b255a52127d1fc0b793ce1 100644 GIT binary patch delta 50355 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%0DfCH^To0|%NH3K?z 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 AQUCw| delta 45767 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 z zt0sAq5k_;5bR&e1luLOWO!)%)a9U?urnrbb|I>z91goNZe~O*+>Mw&D%SsX2Vq;Y_ z{mS2glzUgJki5S+>S09yv(d+GwbLTj%DBZdDl6TGTVO!DFx8bdneBduhXTwB!4*~m z=GNAb%J9n$B^$Ik$9PqtX-klCi$7_>)BITXskco&r>>A{!nMI~qqA}xoPLU#mHVk= z$SebxvNq-Ic)#9Jb~7rT{GMa6FrGvqcc4(BqD26pE1Z5Dh*h`|^W@rYwXe6v$qhob zDL?LlAG`xvfSgY^c|lUCLL08|iSqR!Qep%(lS5{$r>rm&+fHF*o~Q})=Nq;)ZPGTnU1brp^{+43w^r@Z6xvrpnr zRn2L;h$zu(#S6RqB8x>ysb_`lRO*OpaGz|ZFgS{6Yhur=#z`n)$NO_iN)*&_YmZ3= zR(rc#AcLhAI7{1@bYVp_Bcs9zWLcTy(2h>y(1ts}Ss7>j zvFF|`T_j`VHYY7|QGkz%hlCX0?KdukULCZmX$K$)UlmLIyda>rLPa;4xIv{zOFlln zNkX=rwd$vURs>!XJ@5pitFV9s6X6>oA}+(^>spfY^B)>VbxU@BG|QRQpT6f6k1uAB zBxwvPxR$W}h25Oz&khSU*1m$BmzVtN-YdzamB{SuTiMy!@=y^211VOkU`$0-RRL%r z)QJ*=JbdBI&*xv(iAKB~Mux=P#i4Esba&KqBU)+3WrIeE#O5c_lrqRax%*+57Qii* zoif(`Nkf;RYg#&;JmJxELKqGXAH^6(AxQO2Pm*Du%FjbV2)Qd~antm;(rb8jHtN@} zMRSTp&oQ)F}t2T^DS`~0dZ(oGzt2(yy4O0}fqfsM!rG!!k+xz#0&yK%H30oia zueGTYW|}mWOn2#35Zn08qny|-fsImGzy>x|$eSV}ZFUQ7ZR{2nZxSdYYJHD~9)5vC z%@fE^+?pIBB13y+3gmcCAh%+wekkD=w>~iy=&^cxf~h}wSUW-Ji%UO+*Eh+F$8TMl znwk=3dEedLE$`$cR9;c>LYQe1eJ ziM=DJ(ziOGZ@YvY_Pp!ii=#i!*?X0O&7_41pKe9g`bGPmd*bsSc46NKJTXE)uR{91 zkuyJPJfDB#r*2)S6MbOe95}U>rG#xco^{*459*Y()m!be)j(IB&hsz+sL0LuKp;p% zqj-&wX&^1s@&*abJj&tRZ0_!}(;&9RoVB!yv5~c!;D&&Kz$E2$nAxX! ze^58UOvo!j2I$M#6q^zN7q09Bv z7L|p}_p^n5&p}o}4^mHpR zF%j5Y6o73-pT3td%XK2^&9pdxydPvO4NuO@{LHz=)KU!W=;Y6Xq}QFj`a0w)rvH1()xMZkgrxNKnS^B(i{@bDms3i(3z zOhE6M?DX~pKM~?14^4dE=Hs;{QQy9xns5`Q#}t0`{8Ocr(s|rrt0S>J6>qej-QhJ_WPZFXWhritEsW{ z8*i+*YzJRks5?pa`lI=J5?dkmD^1pC5^Q}FYR|omhX2HQ=LkaN2iW8mZgo^Hvb_?K zU5bHep?^2wI)3EB#K0}n$PMbTQ2eMDxec_)l5<{{0iMmcJ=XLexK7y=#{e+BCDFum zN*yLSWCvH{-^j;ItgIaXnt|y*&I2ftZ!9?dDJ5X{O?dN080=)&RvE)6q3UC9&f)o3 zC)UiTP5t!|dWU#H=)GUYbTg>t3!od&a0)rvZ9qE$WF!FVt3?$%N8xwQG`uXhxpei(r<-?)YM{U2bTy?1{iJn1D4RQVI9e8Ny zdPkqomW`>^>S1!NpWx|9+vp^jad0Xku+vn?i}VLSMK&LVebeS?BC75PpETLmo}#H{ zY}7?!P6F4!{^Qv{aW}xpS}vFhow2XwEhB?0zfC7JGM)oc9k1{LpdN6J3(XGY(LTdV z9gUy$(3Qrm7+`GQR`}Zrl@R7<@OmGDvEe zdag?6yDAyf2`}=3kGAKzCFG z8*l4E}C`~Y$8X_RLViUa4PyTX9`KWxalqj&Ez-eyAYnXezL0qO>Bdo<)-LnwAG zIk!62G~|#wkNJYyALc8b5idkp@TCCiAzw+GP;;o9@%rKPEBkvi$z%N(=I8yI2Iw|n zP?^u&!{fWfos8VvE(h|cu)JUnf4uG+;j|EPFOnfDQhvTJ*#5PLhwH&`Y-S}!D~1Cn zd+)r5dlEA&R7}=?IlEJOezEX_{0>r5CBTw)Wug zG!y|=3m3xRD-H6P-XJmuM#@xiAW-;w-ckppKH|MK)AB($zCj15T}Sw*_P1J6HxAw{W1(AiFdwJ^6fC$)hgOzI``++ymG_k?RUW3t z4%c=?ukoPl?4>3@21`DU?GEX)pPk^lGQt81BfM~IJoo_$Z3XQTYj$umk4`N)*HX6; z1<>baUi$MbrKq5wv)r;c=?iEHzzNmAexx>GJxi3g7JxF>2Gj%Bfs|p6ooMN_y^< zC}8w`$yxqiRh2%EV$^y?s+vas_sdaa%{RK&ML893Q>5AG{1Mo2q#flp6#-$=hhKEmv$&uxI3CseC| z)jE8+8bBJpEEND@{_il1?Fcy&M&@vykz#!}YT#)w)713#p<6TRCR-H#$S@ zxF0v#M%dba|Kkj|Ozrnxflh`DEZ*IL{Kh=rX2K}lXEKvrs>xIbl_qkkb1JRJ-h9YZ zPNf%2A|T)J_(6@yzM^%N;S*(R;EW-8@bDgO(ibm^Tunr%+De2yd*2~USXip}+RYF$ ze5$4TCS1UuW!po#zM%oXsjboHyLd&I%CK!L>($6&;g=b49EC!IxZu+_RZ&RGR<}I% zJ0xFA4tNL_*P-0kD(W+6 zzyhopeGxlL+!Lny3#4YUQLgxX>H~Ja` z!9Ob3R_vjjJukxH&1?6<2$Ofu*|Gc5ZcfVj#(olV_fS5w{%bTa7?94@ZhTE%JVmoB zpVZ#&{h6%Cn&e<@Zf+Plj5g5I`&zvb`q8zj$g25Q+S`XiRDKsQMYZQN$%p%EEsuUU zSh-6M94n{{DaQ<>8D-flkBt&1ej%W+z|P20bfVQKtn&V0T7rE^Bl6oU)`k*$x^Pf? zQpAl5)`JZ!oRS-6O~>17d|lltv&C^|KI*e@@6AbM^2XVmdYOzri%;|2xvu$=t?^SI zLJ}t~cv-x|!Rq_sjckjf_V@b2{&%o?F+o}SRMd)U;myqE0 zohzgqybGZ(WoVHBBp%c{N`gWa*A!7e zIP>Y^)EW7t8VZG~bzPw_v5&#;fh)MTy{%+v$w?6}IdnMGFPz~&dV zx##$Ozq2$c!>cSq$3aIbynn)c1*Rrb7 zUHIXNhNovuy$l=g3kH$?p_czU4{~jCE@}%ao6*@F2Lu*=u zz3UW~tLEN(y#NUnW;DwYNlRV2&fKmAA?gdWPD-4o8O^%0)g3;{;vNb`-7lzdJN_=Y zdK0tPlEJ={_7xbvZ$JBjK%Q$^(+!?cUouF;LO6))zTp8ByTY&>eR}dj$;!K#7?tr; z3XLllLqlHA(0UW??JuAC7R^;I;CdcWUqRQ`#gufd9c>7DHq6~^7JosoDSgD;J24*^ zA5TA7iIUURQ*L(L+_r8XUWui|?iHhA>kD&Mi1Z4-1?>H@a!wQ$vXW%#$X^sW+0#g% zq=B!u#b!Y!!9fa=xp(3$ds$OAN_m86cm#hKKfm4?n`Hu%pXhn%;*f+)${X5Gw12px z@!S~WUuSP=qm3xeE)C9X5YJHGBbR+^kb0iKykG(-(|dg<*tFwEtyg^h!)?p!sD=~rrs;Ib0_|k^SHP3GndxKd>;HgirifX zJ7r93ep%T==pGg{Z^N2LP4*uCJ;Lxi1+8{RE5a}v3pl%pq6uTC<#Y8{7d3cqbNc#= zFGIQCcRcJI;ZF|8Zw(RFn?EHsG}N%xxWm?D-}x*YP5zL}|S;`6lGbLPGcKMYb{!$%bUd9Odz%rO5ar~JVWe+*8rF)xiw zK(wGiwAaobA+dWyN(kI9E4d>#3DaPME9pzlKzmNF|KOnuX820|K*Rok+vZWtryY6N7kLEL_-$Iz!8O}mk}yWRZ?D!r*ZQU0#q3KoQN%c+M@?;0D|IIlu6&F0+9 zY6J|%m-|nA3r?YJ`J0R!K`}71q1O``o8#26D^H(p9_b`TsQxo{@4`KgiY$)aG$rxJ z`Lq%0uhpnOIJSE~i!e?^=GD~b*N}?pflhX~^3x@wgk~ctlvii^lg8^4^op+LtZp^C z6oMyd7|pECOk7gaZ=JRd9U)M^to(OZpWEmWTk~lP$P=X3=$~Fd*u*u^ zb$v_zxeJ%WFK6VFF!9P=8ED!M%s6+SC-3Rrdge<9es3)Hl0Z!fJlvwY{?H~N{3Q6e zIXE~n3xSzB96WA|ZF$ST124Lz4BdkG%3oxoA3X~I{|V7reyRV9Is8k#WoB9{>^RrG zZaw~}COeFn2ORcEs6opM<7JOr?Hi89v00b4Bnm5|tIf65l?X?`*2jduO8gNAcEYRFHL0?FI(rCY-(Z8GCDK@M9@bnlr@K{{ zEvSckWry^lh0@$_XQ@k6p^MG;{EdZ~0)IX=_se?J@nj!=QLtWz@rg8iBO*r}T!P-m zUDpy2)F&@*B8~g!G*=quPK3InolFAfPJZmZu~q`Z)ccQT^ZVGLq1xAKGq)8A zb?~(G$#T~EMfJF@dPN<{vDeF>ZRZ~orZ8upldn;=@lT_9iLHU^6=dx6HRqtnLBO1& z#J|TV>J3ZCpj>m#3L%W$reyr?cU0u!osSH-?qnZR^9k{nC@Zv8d*rb2S(J*4Dhmu2S9Ck|;NRxsA#zpoI1pg8G zU9Z_xGBu-F({ttX%1AMeh+`s1Pd7dbSf=0zpZkiEoS%#t>U4j=ke<=6kb!!` zO?Z@uphRUZK$-s@8)EU=tUWT6p_bwNMqSs4Q(m+Ben1*_|H_dZ~qaG$g^+qI0j@6MyWB+Avb2iV@O z&So3swMc*5yM9JL?7Lt1tMK0+gWvc@y7}5{L3Zh<*R@G*4z|UEfs;QpFwo`uBJB7h zSwjqDFTImZXK_VA^gKtM2ymu87a6$xhgtE*S#hP&eLsPoKW#aAJnGf7_pY1N>)Z`< z_S^wK1!Zy!FVJiG+!azKbdgQQrUihF5bILHd5;1{$&}dZqT|WHNK4@@CH7MN^6mF zIM;g!SuGi?3^sAjEXQxuR|6p diff --git a/icons/obj/structures/machinery/ares.dmi b/icons/obj/structures/machinery/ares.dmi new file mode 100644 index 0000000000000000000000000000000000000000..77dd304310f63150b5f929eb8d95515c394b2f38 GIT binary patch literal 3840 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