From ad378142ec2e279a1265692dad5cb5bca8f3f7b1 Mon Sep 17 00:00:00 2001 From: craftxbox Date: Mon, 30 Sep 2024 23:00:16 -0230 Subject: [PATCH] Squashed commit of the following: commit 943006f473bfc236c7c9ff9478395785fe39d154 Author: Changelogs Date: Sat Sep 28 01:01:54 2024 +0000 Automatic changelog compile [ci skip] commit 771b608b4f0113906e003a05e99dad207589534b Author: Changelogs Date: Fri Sep 27 18:59:30 2024 -0500 Automatic changelog generation for PR #3450 [ci skip] commit c830d5f6ea455267f1a087d475e42be0716013a0 Author: Theos Date: Fri Sep 27 19:48:33 2024 -0400 Fixes some stuff with legion infections (#3450) homeless skulls no longer complain about not being fed :cl: fix: legion skulls will no longer check if they should rise up and consume their owner if they are ownerless /:cl: Signed-off-by: Theos commit 86659425ecc9a1577a068115034051b623dd4881 Author: Changelogs Date: Fri Sep 27 18:22:03 2024 -0500 Automatic changelog generation for PR #3402 [ci skip] commit 8bec073a1bee248c55888769ff25555b47f410e4 Author: Sadhorizon <108196626+Sadhorizon@users.noreply.github.com> Date: Sat Sep 28 01:11:18 2024 +0200 Adds a fax machine to the Dwayne. (#3402) ![obraz](https://github.com/user-attachments/assets/79430ae8-1e33-4d11-8dd5-1d687790a261) - Communication with the outpost is fun. - NT is like, THE tcomm company, even if the ship is meant to be their civ market garbage, it should still get one. :cl: add: Added a fax machine to the Dwayne-class. /:cl: commit a358a4dc45c636d84704ef429224075c5ac657d3 Author: Changelogs Date: Fri Sep 27 01:02:14 2024 +0000 Automatic changelog compile [ci skip] commit 1543835a520a43260c3661216301328cb43495d8 Author: Changelogs Date: Thu Sep 26 15:16:55 2024 -0500 Automatic changelog generation for PR #3440 [ci skip] commit 96c4fa999f2265d368905a4544e448d3175691c1 Author: Jedi-Toothpaste <53096233+Jedi-Toothpaste@users.noreply.github.com> Date: Thu Sep 26 21:06:07 2024 +0100 valor map fixes (#3440) So, currently the Valor is awaiting a remap, but this should fix a few problems that it currently has, most notably, the large areas, lack of firelocks and lack of lighting in some rooms. What's changed: - Added firelocks to every door, no more mid-corridor firelocks which don't do much. - Added firelocks across the cargo-bay door. Similar to the Mudskipper. - _I understand this may be a contentious change but i'm happy to remove it if the danger of the holofield falling would still like to be realised_. ![image](https://github.com/user-attachments/assets/48d83b56-7fec-4fb7-9917-337f7f41d78f) - Added lighting to the Corpsman prep room, and the EVA Room as it currently does not spawn with a light at all. (with this, I have also added extra light switches to said rooms). - Seperated the large area at the bottom of the ship. At the moment, the Surgery Room, Morgue Room, Corridor, Corpsman prep, and post-op area all share the same area. I have given each one a seperate area so you can control the lighting in each room. ![image](https://github.com/user-attachments/assets/29ed4c5c-d67a-407a-9ff9-587135f92483) - Similar to the above, I have added seperate areas for the Janitor Closet, EVA prep, Toilet and Laundry Room as well. ![image](https://github.com/user-attachments/assets/ee47bf9b-b07b-4794-911d-e310cc8db933) Being able to turn the lights off in the Morgue seperatly from the entire medbay's is a bit of a no-brainer, and helps enhance the roleplay. It is a little bit immerssion breaking to go to turn off the lights in the patient-care area and suddenly you've plunged the surgery into pitch-darkness. As for the firelocks, having consistent firelocks that are actually present on every door, is also a no brainer; but this change brings the Valor in-line with other IRMG ships in actually having fire-locks on every door. :cl: add: Firelocks to the Valor-Class' Doors add: Lighting to dark areas on the Valor-Class' Doors add: New areas on the Valor-Class to seperate rooms add: Added APC for the Surgical Area /:cl: commit 58eb610c1c1c1b48e1b5c308682b2746982bd86a Author: Changelogs Date: Thu Sep 26 10:59:29 2024 -0500 Automatic changelog generation for PR #3443 [ci skip] commit d67e5e2b91ac23c03ebaf00d5d32db90fceb808c Author: Imaginos16 <77556824+Imaginos16@users.noreply.github.com> Date: Thu Sep 26 08:48:25 2024 -0700 Makes a Slight Cosmetic Edit to Normal Rabbit Ears (#3443) It's subtle but I did it mostly because the current version was bothering me for some god forsaken reason and I guess I'm a perfectionist. ![image](https://github.com/user-attachments/assets/f9fdfe82-d59e-40bd-94a3-4e19b678e2d6) I hate creating characters :cl: PositiveEntropy imageadd: Adjusts the inner part of the normal rabbit ears. /:cl: commit 3d061395b682198f7b68a2c75b29e2f204709a3f Author: Changelogs Date: Thu Sep 26 01:01:48 2024 +0000 Automatic changelog compile [ci skip] commit 3f869318da50bb04241f389350db3f0ad60af111 Author: Changelogs Date: Wed Sep 25 15:43:55 2024 -0500 Automatic changelog generation for PR #3424 [ci skip] commit ddbcb281c1ed2e83fc0b06bddecfb9a386455782 Author: Jedi-Toothpaste <53096233+Jedi-Toothpaste@users.noreply.github.com> Date: Wed Sep 25 21:32:46 2024 +0100 kilo remap fixes (#3424) Kilo remap was good, asides the fact there was not a reinforced window on the thrusters to stop it being spaced if you open the blast doors. However, this problem was self-solving as the blast doors were not connected to the new button. This fixes both issues by adding windows to the thrusters, and linking the button correctly. ![image](https://github.com/user-attachments/assets/852855b1-98a7-4850-bf05-f327c809913e) ![image](https://github.com/user-attachments/assets/1066b7e4-5bb2-41dd-be5f-aa1101df9a00) :cl: fix: Fixed the lack of windows for the Kilo's Thrusters, and fixed the broken link for the new blast doors. /:cl: commit ce35cdda0b8c684a4d4c121871732dd51dec54fd Author: Changelogs Date: Wed Sep 25 10:57:35 2024 -0500 Automatic changelog generation for PR #3320 [ci skip] commit eb41937929ecefa9ea723a2d129ee9b208fa9183 Author: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Date: Wed Sep 25 08:58:42 2024 -0500 Partial port of tg points of intrest and improved orbit menu (#3320) Squash of #3219 rebased ontop of a revert of #3218 cause i fucked up the commit history - [x] Fix admin menu - [x] Fix auto-observe This massively improves the readability of the orbit menu. You can now add custom points of interest pretty easily as it uses an element now. :cl: add: You can now see ships in the orbit menu and its alot prettier! code: ported tg points of interest and a much improved orbit menu /:cl: --------- Signed-off-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> commit 833285300c5ad5867789ab46d5cc2f65ba485602 Author: Changelogs Date: Wed Sep 25 10:44:41 2024 -0500 Automatic changelog generation for PR #3352 [ci skip] commit 065b41dc33b4682678261952b4686c403b800552 Author: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Date: Wed Sep 25 08:52:29 2024 -0500 blank ammo (#3352) pending sprites! :cl: add: Added new blank shells for training drills! refactor: Minor refactor of design disks to reduce repeated code /:cl: commit 8839b3e262ea10ec415f2680140d805f71be5e32 Author: Changelogs Date: Wed Sep 25 10:31:47 2024 -0500 Automatic changelog generation for PR #3346 [ci skip] commit 06cc8b612d18ca841cb03140a7d816d14481bf43 Author: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Date: Wed Sep 25 08:52:11 2024 -0500 Ship joining starts on locked (#3346) Ship's start on locked instead of open Idea from #772 No longer can an assistant join your ship faster then you can, rejoice in time to write your memo and change your ships name. :cl: fix: ships now start closed. shiptesters be writing there memos and ship names. /:cl: commit 12f73cbb6e621e3891d853f4bdd3f28591bae609 Author: Changelogs Date: Wed Sep 25 10:18:15 2024 -0500 Automatic changelog generation for PR #3330 [ci skip] commit 7e9752abf56562c3608ba6598528820f1e9f8fc0 Author: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Date: Wed Sep 25 08:51:41 2024 -0500 minimum recoil for ballistics (#3330) gives a very small kick to all ballistics, not enough to affect your aim but makes them feel alot better to use. atomization of #3094 currently debating what the value should be.. 0 https://github.com/user-attachments/assets/1630a089-bf9f-4ec5-8853-c2728f420f4e .1 https://github.com/user-attachments/assets/2064b49b-37f5-4860-b273-1f28274724f7 .175 https://github.com/user-attachments/assets/6baba2ad-8100-403e-b6c4-d4e958ad21d6 .25 https://github.com/user-attachments/assets/ca3bdf37-bf30-493e-bb24-ae452cbc6481 a bit of an extreme case being a fast firing auto but it happens to be a gun with a recoil of 0 rn so it will be affected by the change without it, a surprising amount of ballistics get 0 recoil just but wielding them which feels really jarring. :cl: add: Ballistics now have a minimum recoil, not enough to mess up your shot! /:cl: commit af77144e59c474fea4831f0241dfb9d95c1ef2c2 Author: generalthrax <139387950+generalthrax@users.noreply.github.com> Date: Wed Sep 25 08:47:38 2024 -0500 Adds .38 Hearth and .38 Chilled ammo boxes, to the Black Market (#3425) Adds ammo boxes for hotshot and iceblox variants of .38 Special, and puts them in the black market. Slightly reflavoured to imply infusion of trickwines by black market elements. Sprites courtesy of @rye-rice ![stuff](https://github.com/user-attachments/assets/3c29840f-e46a-4780-ad92-091c5f5f81d1) Cute little thing to maybe make .38 attractive to some as a gimmicky cartridge :cl: add: Adds .38 Hearth and .38 Chilled specialty ammo boxes to the black market /:cl: commit 14a4b8c324f03571ee1a15be7696efe39c74018c Author: Changelogs Date: Wed Sep 25 09:50:32 2024 -0500 Automatic changelog generation for PR #3420 [ci skip] commit 4009cd5c74be78c030d042450c88e8d9f620f443 Author: generalthrax <139387950+generalthrax@users.noreply.github.com> Date: Wed Sep 25 08:47:03 2024 -0500 Exosuit Recharger Equipment in Cargo (#3420) Adds the exosuit recharger machine and computer boards to cargo You can't get them outside of ruins or RND and they're Way Cooler than cell-swapping :cl: add: Exosuit Recharger machines are now available from cargo /:cl: commit 9aab7f2d0df8b76a55d9f43886d655c679057325 Author: Changelogs Date: Wed Sep 25 09:37:14 2024 -0500 Automatic changelog generation for PR #3418 [ci skip] commit de480f809e1aabfc6590453820c5cd024f1b255e Author: generalthrax <139387950+generalthrax@users.noreply.github.com> Date: Wed Sep 25 08:46:49 2024 -0500 Pants Accessories (#3418) Most accessories fit on pants now I should be able to pin my captain's medal on the turtleneck I'm wearing with my black pants. :cl: balance: Most common accessories now fit on pants /:cl: commit b1038979ab692d27e64fbe6905001959322672dd Author: Changelogs Date: Wed Sep 25 09:24:04 2024 -0500 Automatic changelog generation for PR #3398 [ci skip] commit bad30456a4bfa0e495d6cdaf1ecb02c2bb1f184d Author: Gristlebee <56049844+Gristlebee@users.noreply.github.com> Date: Wed Sep 25 06:46:02 2024 -0700 Fixes deconstructing walls causing runtimes (#3398) Fixes the while loops so they dont do silly shit and call procs on turfs they shouldnt. Kill 9 billion runtimes. :cl: fix: fixes wall deconstruction causing runtimes /:cl: commit 053a7ba7721e7924d6698f6bc4b9879746943d82 Author: Changelogs Date: Wed Sep 25 09:10:35 2024 -0500 Automatic changelog generation for PR #3408 [ci skip] commit f93fa2a563c40653ab0d349bc19a2506c29f6cd2 Author: zimon9 <122945887+zimon9@users.noreply.github.com> Date: Wed Sep 25 09:45:50 2024 -0400 Makes Vegan rations actually Vegan (#3408) Exchanges the pizza crackers snack, which is a meat foodtype, with fruit puree, in the vegan chili ration. It always felt like a really minor and silly oversight that pizza crackers weren't actually vegan, which, in turn, made the _vegan ration_ not actually entirely vegan. This isn't really a gamebreaking change, but I thought it might help with consistency. :cl: add: Added fruit puree to vegan rations del: Removed pizza crackers from vegan rations /:cl: commit 554905548d7b5de1591d04ffeb014aca091caec9 Author: Changelogs Date: Wed Sep 25 08:56:47 2024 -0500 Automatic changelog generation for PR #3423 [ci skip] commit 975debf86e1907ee0156a514e8d7fe14bb3d3d82 Author: generalthrax <139387950+generalthrax@users.noreply.github.com> Date: Wed Sep 25 08:44:46 2024 -0500 More Rust Reds (#3423) Increases rust reds on the black market from maximum 1 to a maximum of 3 Makes them about as available as the other suits on the market. They Suck, shouldn't really matter :cl: balance: Rust Reds on the blackmarket are now available to a maximum of 3 /:cl: commit d0171aa08ab7d4770422af584432490c1956b374 Author: Changelogs Date: Wed Sep 25 01:03:35 2024 +0000 Automatic changelog compile [ci skip] commit fcdc0c0dddfea17b3f62d5733bda8c95499f86bd Author: Changelogs Date: Tue Sep 24 18:55:45 2024 -0500 Automatic changelog generation for PR #3427 [ci skip] commit d52f36b1ce04ae3f2091c787858d3a4ddd205688 Author: Theos Date: Tue Sep 24 19:44:59 2024 -0400 Sawn variants for the illestren and improvised shotgun now properly have their stats set (#3427) If the illestren's sawn off accuracy is unreasonably high I'd like to know because it's TERRIBLE :cl: fix: sawn off illestren/improvised shotgun stats are now consistent if they are spawned in /:cl: --------- Signed-off-by: Theos commit 5a7fcb32088ac609ee462c51d7da4ff73e2fd076 Author: Changelogs Date: Tue Sep 24 17:57:55 2024 -0500 Automatic changelog generation for PR #3426 [ci skip] commit de14f00d60e1943d8dd43c1cd3c53154f696853c Author: Jedi-Toothpaste <53096233+Jedi-Toothpaste@users.noreply.github.com> Date: Tue Sep 24 23:47:10 2024 +0100 mudskipper and shetland window fix (#3426) Added windows to the mudskipper and shetland's engines as well for consistency see #3434 for the Kilo fixes too. Also seperated the Shetland's engine rooms so both buttons don't open both sides. Now the button in each engine room will open only it's respective side. :cl: fix: Added windows to the mudskipper and shetland's engines. fix: Adjusted the blast doors which open on the Shetland's engines. /:cl: --- _maps/map_files/generic/CentCom.dmm | 12 +- .../independent/independent_dwayne.dmm | 15 +- .../shuttles/independent/independent_kilo.dmm | 8 +- .../independent/independent_mudskipper.dmm | 6 + .../independent/independent_shetland.dmm | 24 +- _maps/shuttles/inteq/inteq_valor.dmm | 341 ++++++++++++++---- code/__DEFINES/dcs/signals/signals.dm | 6 + code/__HELPERS/_lists.dm | 36 ++ code/__HELPERS/roundend.dm | 2 +- code/__HELPERS/unsorted.dm | 61 +--- code/_globalvars/lists/objects.dm | 2 - .../subsystem/points_of_interest.dm | 227 ++++++++++++ code/datums/elements/point_of_interest.dm | 22 ++ code/datums/spawners_menu.dm | 2 +- code/game/atom/atom_orbit.dm | 33 ++ code/game/atoms.dm | 5 - code/game/gamemodes/wizard/wizard.dm | 2 +- .../mecha/equipment/tools/mining_tools.dm | 7 +- code/game/mecha/mecha.dm | 4 +- code/game/objects/items.dm | 3 + code/game/objects/items/eightball.dm | 4 +- code/game/objects/items/storage/ration.dm | 2 +- code/game/turfs/closed/_closed.dm | 11 +- code/game/turfs/closed/minerals.dm | 8 +- code/game/turfs/closed/wall/reinf_walls.dm | 3 +- code/game/turfs/closed/walls.dm | 18 +- code/modules/admin/player_panel.dm | 12 +- code/modules/admin/verbs/adminjump.dm | 2 +- code/modules/antagonists/cult/runes.dm | 6 +- .../nukeop/equipment/nuclearbomb.dm | 8 +- .../nukeop/equipment/pinpointer.dm | 2 +- code/modules/antagonists/nukeop/nukeop.dm | 2 +- code/modules/awaymissions/capture_the_flag.dm | 4 +- code/modules/awaymissions/corpse.dm | 4 +- .../blackmarket/blackmarket_items/ammo.dm | 22 ++ .../blackmarket/blackmarket_items/clothing.dm | 2 +- code/modules/cargo/centcom_podlauncher.dm | 2 +- code/modules/cargo/packs/ammo.dm | 12 + code/modules/cargo/packs/mechs.dm | 9 + code/modules/clothing/under/accessories.dm | 4 +- code/modules/events/immovable_rod.dm | 4 +- code/modules/events/wizard/greentext.dm | 4 +- .../mining/lavaland/necropolis_chests.dm | 28 -- .../modules/mob/dead/new_player/new_player.dm | 1 + code/modules/mob/dead/observer/observer.dm | 21 +- code/modules/mob/dead/observer/orbit.dm | 271 +++++++++++--- code/modules/mob/living/living.dm | 1 + .../friendly/drone/drones_as_items.dm | 5 - .../hostile/megafauna/colossus.dm | 4 +- .../hostile/mining_mobs/hivelord.dm | 2 + code/modules/mob/mob.dm | 2 +- .../file_system/programs/radar.dm | 6 +- code/modules/overmap/helm.dm | 3 + .../overmap/ships/controlled_ship_datum.dm | 2 +- code/modules/power/singularity/singularity.dm | 4 +- code/modules/power/supermatter/supermatter.dm | 4 +- code/modules/power/tesla/energy_ball.dm | 2 +- .../ammunition/ballistic/revolver.dm | 8 +- .../ammunition/ballistic/shotgun.dm | 7 + .../projectiles/boxes_magazines/ammo_boxes.dm | 26 +- code/modules/projectiles/gun.dm | 11 +- code/modules/projectiles/guns/ballistic.dm | 2 + .../projectiles/guns/ballistic/rifle.dm | 2 + .../projectiles/guns/ballistic/shotgun.dm | 8 + code/modules/projectiles/guns/energy/pulse.dm | 4 +- .../projectile/bullets/revolver.dm | 4 +- .../projectiles/projectile/bullets/shotgun.dm | 6 + code/modules/research/designs.dm | 78 ++-- .../research/designs/autolathe_designs.dm | 8 + .../research/designs/weapon_designs.dm | 4 +- .../ruins/spaceruin_code/bigderelict1.dm | 10 - code/modules/spells/spell_types/lichdom.dm | 4 +- html/changelogs/archive/2024-09.yml | 41 +++ icons/mob/species/human/rabbit.dmi | Bin 1013 -> 1000 bytes icons/obj/ammo.dmi | Bin 63786 -> 59485 bytes icons/obj/ammo_shotshells.dmi | Bin 1296 -> 3149 bytes shiptest.dme | 3 + tgui/packages/tgui/interfaces/Orbit.js | 218 ----------- .../tgui/interfaces/Orbit/OrbitContent.tsx | 98 +++++ .../tgui/interfaces/Orbit/OrbitItem.tsx | 50 +++ .../tgui/interfaces/Orbit/OrbitSection.tsx | 65 ++++ .../tgui/interfaces/Orbit/OrbitTooltip.tsx | 57 +++ .../tgui/interfaces/Orbit/constants.ts | 8 + .../packages/tgui/interfaces/Orbit/helpers.ts | 119 ++++++ tgui/packages/tgui/interfaces/Orbit/index.tsx | 86 +++++ tgui/packages/tgui/interfaces/Orbit/types.ts | 38 ++ 86 files changed, 1681 insertions(+), 603 deletions(-) create mode 100644 code/controllers/subsystem/points_of_interest.dm create mode 100644 code/datums/elements/point_of_interest.dm create mode 100644 code/game/atom/atom_orbit.dm delete mode 100644 tgui/packages/tgui/interfaces/Orbit.js create mode 100644 tgui/packages/tgui/interfaces/Orbit/OrbitContent.tsx create mode 100644 tgui/packages/tgui/interfaces/Orbit/OrbitItem.tsx create mode 100644 tgui/packages/tgui/interfaces/Orbit/OrbitSection.tsx create mode 100644 tgui/packages/tgui/interfaces/Orbit/OrbitTooltip.tsx create mode 100644 tgui/packages/tgui/interfaces/Orbit/constants.ts create mode 100644 tgui/packages/tgui/interfaces/Orbit/helpers.ts create mode 100644 tgui/packages/tgui/interfaces/Orbit/index.tsx create mode 100644 tgui/packages/tgui/interfaces/Orbit/types.ts diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index e25bceb1dd44e..405950bfe6333 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -26,7 +26,7 @@ /turf/open/floor/plasteel/dark, /area/tdome/tdomeadmin) "afh" = ( -/obj/machinery/computer/helm{ +/obj/machinery/computer{ dir = 4 }, /obj/effect/turf_decal/industrial/warning{ @@ -1356,7 +1356,7 @@ /turf/open/floor/plasteel, /area/wizard_station) "ara" = ( -/obj/machinery/computer/helm, +/obj/machinery/computer, /turf/open/floor/plasteel, /area/wizard_station) "ard" = ( @@ -3939,7 +3939,7 @@ /turf/open/floor/mineral/titanium/blue, /area/centcom/evac) "aLP" = ( -/obj/machinery/computer/helm{ +/obj/machinery/computer{ dir = 1 }, /turf/open/floor/mineral/titanium/blue, @@ -8827,7 +8827,7 @@ }, /area/centcom) "gFU" = ( -/obj/machinery/computer/helm, +/obj/machinery/computer, /obj/effect/turf_decal/industrial/warning{ dir = 6 }, @@ -12230,7 +12230,7 @@ /turf/open/floor/plasteel/dark, /area/tdome/tdomeadmin) "nEL" = ( -/obj/machinery/computer/helm, +/obj/machinery/computer, /obj/effect/turf_decal/industrial/warning{ dir = 10 }, @@ -15778,7 +15778,7 @@ /turf/open/floor/plasteel/dark, /area/ctf) "vcL" = ( -/obj/machinery/computer/helm, +/obj/machinery/computer, /obj/effect/turf_decal/corner/transparent/bar, /obj/effect/turf_decal/corner/transparent/bar{ dir = 1 diff --git a/_maps/shuttles/independent/independent_dwayne.dmm b/_maps/shuttles/independent/independent_dwayne.dmm index a0383e507ec14..d1cc698c0c923 100644 --- a/_maps/shuttles/independent/independent_dwayne.dmm +++ b/_maps/shuttles/independent/independent_dwayne.dmm @@ -886,12 +886,15 @@ dir = 1 }, /obj/item/radio/weather_monitor{ - pixel_x = 5; + pixel_x = 8; pixel_y = 7 }, -/obj/item/reagent_containers/food/drinks/mug{ - pixel_x = -8 +/obj/machinery/newscaster/directional/west, +/obj/item/paper_bin{ + pixel_x = -8; + pixel_y = 6 }, +/obj/item/pen/fountain, /turf/open/floor/plasteel/mono/dark, /area/ship/bridge) "mR" = ( @@ -2686,9 +2689,8 @@ "Oz" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/corner/opaque/ntblue/half, -/obj/machinery/newscaster/directional/west, -/obj/item/megaphone/cargo{ - pixel_y = 5 +/obj/machinery/fax/indie{ + pixel_y = 7 }, /turf/open/floor/plasteel/mono/dark, /area/ship/bridge) @@ -2711,6 +2713,7 @@ /obj/item/ammo_box/c38, /obj/item/ammo_box/c38, /obj/item/gun/ballistic/revolver/detective, +/obj/item/megaphone/cargo, /turf/open/floor/plasteel/mono/dark, /area/ship/bridge) "OP" = ( diff --git a/_maps/shuttles/independent/independent_kilo.dmm b/_maps/shuttles/independent/independent_kilo.dmm index 0dad29cb9f9ba..35f955ff0b3d4 100644 --- a/_maps/shuttles/independent/independent_kilo.dmm +++ b/_maps/shuttles/independent/independent_kilo.dmm @@ -22,6 +22,9 @@ dir = 4; id = "kilothrusters" }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plating/airless, /area/ship/engineering) "av" = ( @@ -1581,6 +1584,9 @@ dir = 4; id = "kilothrusters" }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plating, /area/ship/engineering) "MY" = ( @@ -1890,7 +1896,7 @@ /obj/effect/decal/cleanable/oil, /obj/machinery/button/door{ dir = 8; - id = "amogusthrusters"; + id = "kilothrusters"; name = "Thruster Lockdown"; pixel_x = 21 }, diff --git a/_maps/shuttles/independent/independent_mudskipper.dmm b/_maps/shuttles/independent/independent_mudskipper.dmm index ac2be582662aa..be3d9a994e7f0 100644 --- a/_maps/shuttles/independent/independent_mudskipper.dmm +++ b/_maps/shuttles/independent/independent_mudskipper.dmm @@ -1096,6 +1096,9 @@ dir = 4; id = "mudskipper_engine" }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plating, /area/ship/engineering/engine) "zR" = ( @@ -1670,6 +1673,9 @@ dir = 4; id = "mudskipper_engine" }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plating, /area/ship/engineering/engine) "MK" = ( diff --git a/_maps/shuttles/independent/independent_shetland.dmm b/_maps/shuttles/independent/independent_shetland.dmm index 256e9bc75c88d..89dd45bb2262a 100644 --- a/_maps/shuttles/independent/independent_shetland.dmm +++ b/_maps/shuttles/independent/independent_shetland.dmm @@ -1492,7 +1492,7 @@ }, /obj/machinery/button/door{ dir = 1; - id = "amogusthrusters"; + id = "shetportthrusters"; name = "Thruster Lockdown"; pixel_y = -21 }, @@ -2297,7 +2297,7 @@ pixel_y = 5 }, /obj/machinery/button/door{ - id = "amogusthrusters"; + id = "shetstarboardengine"; name = "Thruster Lockdown"; pixel_y = 24 }, @@ -2748,11 +2748,14 @@ }, /obj/machinery/door/poddoor{ dir = 4; - id = "amogusthrusters" + id = "shetstarboardengine" }, /obj/effect/turf_decal/industrial/warning{ dir = 4 }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plating, /area/ship/maintenance/starboard) "wU" = ( @@ -4423,11 +4426,14 @@ }, /obj/machinery/door/poddoor{ dir = 4; - id = "amogusthrusters" + id = "shetportthrusters" }, /obj/effect/turf_decal/industrial/warning{ dir = 4 }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plating, /area/ship/maintenance/port) "Lx" = ( @@ -4989,11 +4995,14 @@ }, /obj/machinery/door/poddoor{ dir = 4; - id = "amogusthrusters" + id = "shetportthrusters" }, /obj/effect/turf_decal/industrial/warning{ dir = 4 }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plating, /area/ship/maintenance/port) "PR" = ( @@ -5157,11 +5166,14 @@ }, /obj/machinery/door/poddoor{ dir = 4; - id = "amogusthrusters" + id = "shetstarboardengine" }, /obj/effect/turf_decal/industrial/warning{ dir = 4 }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plating, /area/ship/maintenance/starboard) "Ri" = ( diff --git a/_maps/shuttles/inteq/inteq_valor.dmm b/_maps/shuttles/inteq/inteq_valor.dmm index 737e424096fd2..dac3ac7a0ebb2 100644 --- a/_maps/shuttles/inteq/inteq_valor.dmm +++ b/_maps/shuttles/inteq/inteq_valor.dmm @@ -123,7 +123,7 @@ /obj/effect/turf_decal/borderfloorwhite, /obj/machinery/light/directional/south, /turf/open/floor/plasteel/white, -/area/ship/medical) +/area/ship/medical/surgery) "bJ" = ( /obj/effect/turf_decal/siding/thinplating/dark, /obj/effect/turf_decal/trimline/opaque/brown/line, @@ -136,7 +136,7 @@ dir = 4 }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "bN" = ( /obj/structure/catwalk/over/plated_catwalk, /obj/machinery/power/apc/auto_name/directional/east, @@ -353,7 +353,7 @@ }, /obj/structure/chair, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "dG" = ( /obj/effect/turf_decal/industrial/traffic/corner{ dir = 4 @@ -366,6 +366,12 @@ dir = 8; name = "Custodian Closet" }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, /turf/open/floor/plasteel/tech/techmaint, /area/ship/crew/canteen) "dM" = ( @@ -407,7 +413,7 @@ name = "Surgery" }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "dO" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -546,7 +552,7 @@ pixel_y = 8 }, /turf/open/floor/plasteel/white, -/area/ship/medical) +/area/ship/medical/surgery) "eV" = ( /obj/structure/cable{ icon_state = "1-4" @@ -733,8 +739,13 @@ dir = 5 }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "gq" = ( +/obj/machinery/light_switch{ + dir = 1; + pixel_y = -20; + pixel_x = -3 + }, /turf/open/floor/plasteel/mono/dark, /area/ship/cargo) "gt" = ( @@ -762,7 +773,7 @@ dir = 4 }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "gZ" = ( /obj/machinery/door/airlock/external{ dir = 4 @@ -840,6 +851,9 @@ }, /turf/open/floor/plasteel/tech/grid, /area/ship/crew/cryo) +"hJ" = ( +/turf/open/floor/plasteel/dark, +/area/ship/medical/surgery) "hN" = ( /obj/effect/turf_decal/siding/thinplating{ dir = 4 @@ -862,8 +876,13 @@ dir = 8; pixel_x = 12 }, +/obj/machinery/light_switch{ + dir = 8; + pixel_x = 20; + pixel_y = 8 + }, /turf/open/floor/plasteel/patterned/brushed, -/area/ship/medical) +/area/ship/medical/surgery) "id" = ( /obj/structure/cable{ icon_state = "1-2" @@ -1018,7 +1037,7 @@ id = "valor_external" }, /turf/open/floor/plating, -/area/ship/medical) +/area/ship/medical/surgery) "jN" = ( /obj/structure/chair/office, /obj/machinery/power/apc/auto_name/directional/west, @@ -1063,6 +1082,11 @@ pixel_x = 1; pixel_y = 16 }, +/obj/machinery/light_switch{ + dir = 1; + pixel_y = -20; + pixel_x = 4 + }, /turf/open/floor/plasteel/patterned/ridged, /area/ship/medical) "jU" = ( @@ -1094,6 +1118,12 @@ dir = 4; name = "Starboard Engines" }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/ship/maintenance/starboard) "kx" = ( @@ -1178,6 +1208,10 @@ /obj/machinery/door/airlock/grunge{ name = "Medbay" }, +/obj/machinery/door/firedoor/border_only, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/ship/medical) "lc" = ( @@ -1329,6 +1363,10 @@ }, /turf/open/floor/plasteel/dark, /area/ship/crew/canteen) +"ml" = ( +/obj/machinery/light/directional/west, +/turf/open/floor/plasteel/patterned, +/area/ship/medical) "mp" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -1338,6 +1376,9 @@ }, /turf/open/floor/plasteel/tech, /area/ship/medical) +"mr" = ( +/turf/closed/wall/mineral/plastitanium, +/area/ship/medical/surgery) "mt" = ( /obj/structure/rack, /obj/item/tank/internals/plasmaman/full, @@ -1479,8 +1520,9 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 }, +/obj/machinery/light/directional/north, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "nz" = ( /obj/machinery/door/firedoor/border_only{ dir = 8 @@ -1509,8 +1551,12 @@ /obj/machinery/door/airlock/medical/glass{ name = "Surgical Bay" }, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only, /turf/open/floor/plasteel/white, -/area/ship/medical) +/area/ship/medical/surgery) "nU" = ( /obj/effect/turf_decal/corner/opaque/yellow{ dir = 1 @@ -1551,6 +1597,9 @@ /obj/item/flashlight/lamp/green, /turf/open/floor/carpet/black, /area/ship/crew/dorm) +"ou" = ( +/turf/open/floor/plasteel/mono/dark, +/area/ship/cargo) "oy" = ( /obj/effect/turf_decal/trimline/opaque/brown/warning{ dir = 6 @@ -1569,7 +1618,7 @@ dir = 4 }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "oz" = ( /obj/structure/cable{ icon_state = "6-8" @@ -1719,7 +1768,7 @@ /obj/structure/table/optable, /obj/structure/curtain, /turf/open/floor/plasteel/patterned/brushed, -/area/ship/medical) +/area/ship/medical/surgery) "pL" = ( /obj/machinery/power/terminal{ dir = 8 @@ -1789,8 +1838,12 @@ icon_state = "1-2" }, /obj/machinery/door/airlock/hatch, +/obj/machinery/door/firedoor/border_only, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, /turf/open/floor/plasteel/patterned, -/area/ship/medical) +/area/ship/medical/surgery) "qt" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable{ @@ -1846,7 +1899,7 @@ id = "valor_surgery" }, /turf/open/floor/plating, -/area/ship/medical) +/area/ship/medical/surgery) "qW" = ( /obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/layer2{ dir = 4 @@ -1890,6 +1943,20 @@ }, /turf/open/floor/plating, /area/ship/crew/dorm) +"rh" = ( +/obj/structure/catwalk/over/plated_catwalk/dark, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/light_switch{ + dir = 4; + pixel_x = -20; + pixel_y = -1 + }, +/turf/open/floor/plating, +/area/ship/hallway/central) "rL" = ( /turf/open/floor/plasteel/patterned/cargo_one, /area/ship/cargo) @@ -1905,7 +1972,7 @@ icon_state = "1-8" }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "rX" = ( /obj/structure/sign/poster/contraband/inteq_gec{ pixel_y = 32 @@ -1996,8 +2063,12 @@ /obj/machinery/door/airlock/medical{ name = "Morgue" }, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only, /turf/open/floor/plasteel/white, -/area/ship/medical) +/area/ship/medical/surgery) "ss" = ( /obj/structure/rack, /obj/item/pickaxe/emergency, @@ -2011,8 +2082,12 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/light_switch{ + dir = 8; + pixel_x = 20 + }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "sy" = ( /obj/effect/turf_decal/corner/opaque/yellow{ dir = 1 @@ -2083,6 +2158,11 @@ pixel_y = 10 }, /obj/machinery/firealarm/directional/west, +/obj/machinery/light_switch{ + dir = 4; + pixel_x = -20; + pixel_y = -10 + }, /turf/open/floor/plasteel/patterned/grid, /area/ship/hallway/central) "sM" = ( @@ -2192,6 +2272,10 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/power/apc/auto_name/directional/south, /obj/structure/cable, +/obj/machinery/light_switch{ + dir = 1; + pixel_y = -20 + }, /turf/open/floor/plasteel/patterned/grid, /area/ship/hallway/port) "tZ" = ( @@ -2234,7 +2318,7 @@ dir = 1 }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "uA" = ( /obj/effect/turf_decal/trimline/opaque/yellow/filled/warning{ dir = 4 @@ -2466,12 +2550,11 @@ /turf/open/floor/plasteel/dark, /area/ship/crew/canteen) "xg" = ( -/obj/machinery/door/firedoor/border_only, /obj/effect/turf_decal/siding/thinplating/dark/corner{ dir = 8 }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "xj" = ( /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ship/cargo) @@ -2727,7 +2810,7 @@ /obj/effect/turf_decal/borderfloorblack, /obj/structure/bodycontainer/morgue, /turf/open/floor/plasteel/patterned/brushed, -/area/ship/medical) +/area/ship/medical/surgery) "zE" = ( /obj/effect/turf_decal/siding/thinplating/dark{ dir = 1 @@ -2768,8 +2851,12 @@ "zI" = ( /obj/effect/turf_decal/borderfloorblack, /obj/machinery/door/airlock/hatch, +/obj/machinery/door/firedoor/border_only, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, /turf/open/floor/plasteel/patterned, -/area/ship/medical) +/area/ship/medical/surgery) "zK" = ( /obj/docking_port/stationary{ dir = 4; @@ -2800,6 +2887,10 @@ /obj/effect/turf_decal/siding/thinplating/dark{ dir = 9 }, +/obj/machinery/light_switch{ + dir = 4; + pixel_x = -20 + }, /turf/open/floor/plasteel/dark, /area/ship/medical) "zT" = ( @@ -2889,7 +2980,7 @@ pixel_y = -4 }, /turf/open/floor/plasteel/patterned/brushed, -/area/ship/medical) +/area/ship/medical/surgery) "AG" = ( /obj/structure/bed, /obj/item/bedsheet/hos{ @@ -2968,6 +3059,10 @@ desc = "A poster encouraging you to work for your future."; pixel_y = 32 }, +/obj/machinery/light_switch{ + dir = 4; + pixel_x = -20 + }, /turf/open/floor/plasteel/dark, /area/ship/medical) "Bc" = ( @@ -2984,6 +3079,13 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plasteel/dark, /area/ship/crew/canteen) +"BB" = ( +/obj/machinery/light_switch{ + dir = 1; + pixel_y = -20 + }, +/turf/template_noop, +/area/template_noop) "BC" = ( /obj/structure/filingcabinet/double, /obj/structure/sign/poster/official/help_others{ @@ -3082,7 +3184,7 @@ pixel_x = 28 }, /turf/open/floor/plasteel/white, -/area/ship/medical) +/area/ship/medical/surgery) "CH" = ( /obj/effect/turf_decal/trimline/opaque/yellow/filled/warning, /obj/structure/cable{ @@ -3330,8 +3432,9 @@ /obj/effect/turf_decal/trimline/opaque/brown/line{ dir = 5 }, +/obj/machinery/light/directional/north, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "EJ" = ( /obj/effect/turf_decal/siding/thinplating/corner{ dir = 1 @@ -3463,7 +3566,7 @@ /area/ship/crew/canteen) "FY" = ( /turf/open/floor/plasteel/patterned/brushed, -/area/ship/medical) +/area/ship/medical/surgery) "FZ" = ( /obj/effect/turf_decal/siding/thinplating{ dir = 1 @@ -3532,6 +3635,20 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plasteel/patterned/grid, /area/ship/hallway/central) +"GT" = ( +/obj/structure/catwalk/over/plated_catwalk/dark, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/light_switch{ + dir = 4; + pixel_x = -20; + pixel_y = 4 + }, +/turf/open/floor/plating, +/area/ship/hallway/central) "Hg" = ( /obj/effect/turf_decal/siding/thinplating{ dir = 1 @@ -3567,6 +3684,9 @@ /obj/machinery/door/airlock/hatch{ name = "Port Hallway" }, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, /turf/open/floor/plasteel/tech/grid, /area/ship/cargo) "HA" = ( @@ -3631,6 +3751,10 @@ /obj/structure/mirror{ pixel_y = -24 }, +/obj/machinery/light_switch{ + dir = 4; + pixel_x = -20 + }, /turf/open/floor/plasteel/patterned/brushed, /area/ship/crew/canteen) "HT" = ( @@ -4042,7 +4166,7 @@ pixel_y = -23 }, /turf/open/floor/plasteel/white, -/area/ship/medical) +/area/ship/medical/surgery) "LL" = ( /obj/structure/closet/secure_closet{ icon_state = "med_secure"; @@ -4089,6 +4213,10 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 }, +/obj/machinery/light_switch{ + dir = 1; + pixel_y = -20 + }, /turf/open/floor/plasteel/stairs{ dir = 8 }, @@ -4158,6 +4286,14 @@ "Nh" = ( /turf/closed/wall/mineral/plastitanium, /area/ship/cargo) +"Nk" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/dark, +/area/ship/medical/surgery) "Nn" = ( /obj/structure/table/reinforced, /obj/effect/decal/cleanable/cobweb, @@ -4175,6 +4311,10 @@ /obj/item/soap{ pixel_x = -6 }, +/obj/machinery/light_switch{ + dir = 4; + pixel_x = -20 + }, /turf/open/floor/plasteel/tech/techmaint, /area/ship/crew/canteen) "NA" = ( @@ -4309,6 +4449,7 @@ /obj/effect/turf_decal/techfloor{ dir = 4 }, +/obj/machinery/light/directional/east, /turf/open/floor/plasteel/tech/grid, /area/ship/cargo) "Ok" = ( @@ -4318,6 +4459,14 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/patterned, /area/ship/cargo) +"Ox" = ( +/obj/structure/grille, +/obj/structure/window/plasma/reinforced/plastitanium, +/obj/machinery/door/poddoor/shutters{ + id = "valor_external" + }, +/turf/open/floor/plating, +/area/ship/medical/surgery) "Oz" = ( /obj/structure/table, /obj/item/folder{ @@ -4351,7 +4500,7 @@ /obj/effect/turf_decal/borderfloorblack, /obj/machinery/light/directional/south, /turf/open/floor/plasteel/patterned/brushed, -/area/ship/medical) +/area/ship/medical/surgery) "OM" = ( /turf/open/floor/pod, /area/ship/cargo) @@ -4410,14 +4559,19 @@ dir = 8 }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "Pg" = ( /obj/structure/sink{ dir = 4; pixel_x = -12 }, +/obj/machinery/light_switch{ + dir = 4; + pixel_x = -20; + pixel_y = 8 + }, /turf/open/floor/plasteel/white, -/area/ship/medical) +/area/ship/medical/surgery) "Pk" = ( /obj/effect/turf_decal/corner/opaque/brown{ dir = 4 @@ -4451,10 +4605,9 @@ /obj/effect/turf_decal/trimline/opaque/brown/line{ dir = 1 }, -/obj/machinery/light/directional/north, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "PU" = ( /turf/closed/wall/mineral/plastitanium, /area/ship/crew/cryo) @@ -4582,8 +4735,12 @@ /turf/open/floor/plasteel/tech/grid, /area/ship/cargo) "Re" = ( +/obj/structure/cable{ + icon_state = "0-4" + }, +/obj/machinery/power/apc/auto_name/directional/west, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "Rh" = ( /turf/closed/wall/mineral/plastitanium, /area/ship/security) @@ -4704,6 +4861,9 @@ }, /turf/open/floor/carpet/black, /area/ship/crew/dorm) +"SL" = ( +/turf/closed/wall/mineral/plastitanium/nodiagonal, +/area/ship/medical/surgery) "SX" = ( /obj/machinery/power/terminal{ dir = 1 @@ -4808,7 +4968,7 @@ dir = 1 }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "Uj" = ( /obj/effect/turf_decal/siding/thinplating/dark, /obj/structure/cable{ @@ -4860,6 +5020,15 @@ }, /turf/open/floor/plasteel/dark, /area/ship/crew/canteen) +"UD" = ( +/obj/machinery/suit_storage_unit/inherit, +/obj/item/clothing/suit/space/inteq, +/obj/item/clothing/head/helmet/space/inteq, +/obj/effect/turf_decal/techfloor{ + dir = 4 + }, +/turf/open/floor/plasteel/tech/grid, +/area/ship/cargo) "UN" = ( /obj/effect/turf_decal/siding/thinplating, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ @@ -5046,10 +5215,12 @@ dir = 9 }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4, -/obj/machinery/firealarm/directional/west, +/obj/machinery/firealarm/directional/west{ + pixel_y = 4 + }, /obj/structure/chair, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "WQ" = ( /obj/structure/cable/yellow{ icon_state = "0-2" @@ -5221,12 +5392,18 @@ /area/ship/medical) "Yi" = ( /turf/open/floor/plasteel/white, -/area/ship/medical) +/area/ship/medical/surgery) "Yn" = ( /obj/machinery/door/airlock/grunge{ dir = 8; name = "Restroom" }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, /turf/open/floor/plasteel/patterned/brushed, /area/ship/crew/canteen) "Yt" = ( @@ -5262,14 +5439,16 @@ /turf/open/floor/plating, /area/ship/maintenance/starboard) "YL" = ( -/obj/machinery/door/firedoor/border_only, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/structure/cable{ icon_state = "1-2" }, +/obj/structure/cable{ + icon_state = "2-8" + }, /turf/open/floor/plasteel/dark, -/area/ship/medical) +/area/ship/medical/surgery) "YM" = ( /obj/effect/turf_decal/corner/opaque/yellow{ dir = 1 @@ -5304,6 +5483,12 @@ dir = 4; name = "Port Engines" }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, /turf/open/floor/plating, /area/ship/maintenance/port) "Zc" = ( @@ -5481,7 +5666,7 @@ cu Td Td Td -Td +BB Nh xj qG @@ -5595,13 +5780,13 @@ xj Td Td Td -bB -LI +mr +SL ns -LI +SL pC zD -LI +SL "} (8,1,1) = {" Zu @@ -5628,13 +5813,13 @@ xj Td Td Td -WC +Ox WO gp -LI +SL FY OK -LI +SL "} (9,1,1) = {" Zu @@ -5661,13 +5846,13 @@ xj Td Td Td -WC +Ox dA Pe si hW AE -LI +SL "} (10,1,1) = {" Zu @@ -5690,17 +5875,17 @@ OM OM Kz ZF -LI +SL jL jL jL -LI +SL PL bJ -LI -LI -LI -LI +SL +SL +SL +SL "} (11,1,1) = {" Zu @@ -5724,8 +5909,8 @@ Mn de KU zI -Re -Re +hJ +hJ xg Re Ui @@ -5733,7 +5918,7 @@ gU nK Pg eU -LI +SL "} (12,1,1) = {" tZ @@ -5758,15 +5943,15 @@ Fa MR qk su -su +Nk +Nk YL -su ux rO qR Yi bI -LI +SL "} (13,1,1) = {" tZ @@ -5799,7 +5984,7 @@ oy qR CF LJ -LI +SL "} (14,1,1) = {" tZ @@ -5824,15 +6009,15 @@ zT nX LI jG -Io +ml Au LI -LI +SL dN -LI -LI -LI -LI +SL +SL +SL +SL "} (15,1,1) = {" tZ @@ -5842,9 +6027,9 @@ tZ Qc AP HC -gq -gq -gq +ou +ou +ou Hw nX ct @@ -5875,8 +6060,8 @@ ME iN xl HC -gq -gq +ou +ou gq xj Rc @@ -5908,9 +6093,9 @@ tZ VD Um DT +UD Oj -Oj -Oj +UD DT DT DT @@ -5974,7 +6159,7 @@ mB ma CH jk -lc +GT Sh lc ht @@ -5990,7 +6175,7 @@ hj id lc Sh -lc +rh bR XD NZ diff --git a/code/__DEFINES/dcs/signals/signals.dm b/code/__DEFINES/dcs/signals/signals.dm index 38f7d86928539..f3295b737904d 100644 --- a/code/__DEFINES/dcs/signals/signals.dm +++ b/code/__DEFINES/dcs/signals/signals.dm @@ -735,3 +735,9 @@ ///sent when the access on an id is changed/updated, ensures wallets get updated once ids generate there access #define COSMIG_ACCESS_UPDATED "acces_updated" + +// Point of interest signals +/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_added : (atom/new_poi) +#define COMSIG_ADDED_POINT_OF_INTEREST "added_point_of_interest" +/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_removed : (atom/old_poi) +#define COMSIG_REMOVED_POINT_OF_INTEREST "removed_point_of_interest" diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 435b83e297974..b231b4e944c98 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -87,6 +87,42 @@ };\ } while(FALSE) + +/** + * Custom binary search sorted insert utilising comparison procs instead of vars. + * INPUT: Object to be inserted + * LIST: List to insert object into + * TYPECONT: The typepath of the contents of the list + * COMPARE: The object to compare against, usualy the same as INPUT + * COMPARISON: The plaintext name of a proc on INPUT that takes a single argument to accept a single element from LIST and returns a positive, negative or zero number to perform a comparison. + * COMPTYPE: How should the values be compared? Either COMPARE_KEY or COMPARE_VALUE. + */ +#define BINARY_INSERT_PROC_COMPARE(INPUT, LIST, TYPECONT, COMPARE, COMPARISON, COMPTYPE) \ + do {\ + var/list/__BIN_LIST = LIST;\ + var/__BIN_CTTL = length(__BIN_LIST);\ + if(!__BIN_CTTL) {\ + __BIN_LIST += INPUT;\ + } else {\ + var/__BIN_LEFT = 1;\ + var/__BIN_RIGHT = __BIN_CTTL;\ + var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\ + var ##TYPECONT/__BIN_ITEM;\ + while(__BIN_LEFT < __BIN_RIGHT) {\ + __BIN_ITEM = COMPTYPE;\ + if(__BIN_ITEM.##COMPARISON(COMPARE) <= 0) {\ + __BIN_LEFT = __BIN_MID + 1;\ + } else {\ + __BIN_RIGHT = __BIN_MID;\ + };\ + __BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\ + };\ + __BIN_ITEM = COMPTYPE;\ + __BIN_MID = __BIN_ITEM.##COMPARISON(COMPARE) > 0 ? __BIN_MID : __BIN_MID + 1;\ + __BIN_LIST.Insert(__BIN_MID, INPUT);\ + };\ + } while(FALSE) + //Returns a list in plain english as a string /proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) var/total = length(input) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 97740a79537ef..01fd964120ea6 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -116,7 +116,7 @@ SSblackbox.record_feedback("associative", "antagonists", 1, antag_info) /datum/controller/subsystem/ticker/proc/record_nuke_disk_location() - var/obj/item/disk/nuclear/N = locate() in GLOB.poi_list + var/obj/item/disk/nuclear/N = locate() in SSpoints_of_interest.other_points_of_interest if(N) var/list/data = list() var/turf/T = get_turf(N) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 36764c6bae9f8..d831296dbb627 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -294,65 +294,6 @@ Turf and target are separate in case you want to teleport some distance from a t /proc/ionnum() return "[pick("!","@","#","$","%","^","&")][pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")]" -//Returns a list of all items of interest with their name -/proc/getpois(mobs_only = FALSE, skip_mindless = FALSE, specify_dead_role = TRUE) - var/list/mobs = sortmobs() - var/list/namecounts = list() - var/list/pois = list() - for(var/mob/M in mobs) - if(skip_mindless && (!M.mind && !M.ckey)) - if(!isbot(M) && !iscameramob(M) && !ismegafauna(M)) - continue - if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins - continue - var/name = avoid_assoc_duplicate_keys(M.name, namecounts) + M.get_realname_string() - - if(M.stat == DEAD && specify_dead_role) - if(isobserver(M)) - name += " \[ghost\]" - else - name += " \[dead\]" - pois[name] = M - - if(!mobs_only) - for(var/atom/A in GLOB.poi_list) - if(!A || !A.loc) - continue - pois[avoid_assoc_duplicate_keys(A.name, namecounts)] = A - - return pois -//Orders mobs by type then by name -/proc/sortmobs() - var/list/moblist = list() - var/list/sortmob = sortNames(GLOB.mob_list) - for(var/mob/living/silicon/ai/M in sortmob) - moblist.Add(M) - for(var/mob/camera/M in sortmob) - moblist.Add(M) - for(var/mob/living/silicon/pai/M in sortmob) - moblist.Add(M) - for(var/mob/living/silicon/robot/M in sortmob) - moblist.Add(M) - for(var/mob/living/carbon/human/M in sortmob) - moblist.Add(M) - for(var/mob/living/brain/M in sortmob) - moblist.Add(M) - for(var/mob/living/carbon/alien/M in sortmob) - moblist.Add(M) - for(var/mob/dead/observer/M in sortmob) - moblist.Add(M) - for(var/mob/dead/new_player/M in sortmob) - moblist.Add(M) - for(var/mob/living/carbon/monkey/M in sortmob) - moblist.Add(M) - for(var/mob/living/simple_animal/slime/M in sortmob) - moblist.Add(M) - for(var/mob/living/simple_animal/M in sortmob) - moblist.Add(M) - for(var/mob/living/carbon/true_devil/M in sortmob) - moblist.Add(M) - return moblist - // Format a power value in W, kW, MW, or GW. /proc/DisplayPower(powerused) if(powerused < 1000) //Less than a kW @@ -384,7 +325,7 @@ Turf and target are separate in case you want to teleport some distance from a t /proc/get_mob_by_ckey(key) if(!key) return - var/list/mobs = sortmobs() + var/list/mobs = SSpoints_of_interest.get_mob_pois() for(var/mob/M in mobs) if(M.ckey == key) return M diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 7ee53ec1f37bc..6d08f1d1bceba 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -46,8 +46,6 @@ GLOBAL_LIST_EMPTY(apcs_list) GLOBAL_LIST_EMPTY(tracked_implants) /// List of implants the prisoner console can track and send inject commands too GLOBAL_LIST_EMPTY(tracked_chem_implants) -/// List of points of interest for observe/follow -GLOBAL_LIST_EMPTY(poi_list) /// List of all pinpointers. Used to change stuff they are pointing to all at once. GLOBAL_LIST_EMPTY(pinpointer_list) /// List of all zombie_infection organs, for any mass "animation" diff --git a/code/controllers/subsystem/points_of_interest.dm b/code/controllers/subsystem/points_of_interest.dm new file mode 100644 index 0000000000000..6de327bc86666 --- /dev/null +++ b/code/controllers/subsystem/points_of_interest.dm @@ -0,0 +1,227 @@ +/// Subsystem for managing all POIs. +SUBSYSTEM_DEF(points_of_interest) + name = "Points of Interest" + + flags = SS_NO_FIRE | SS_NO_INIT + + /// List of mob POIs. This list is automatically sorted. + var/list/datum/point_of_interest/mob_poi/mob_points_of_interest = list() + /// List of non-mob POIs. This list is automatically sorted. + var/list/datum/point_of_interest/other_points_of_interest = list() + /// List of all value:POI datums by their key:target refs. + var/list/datum/point_of_interest/points_of_interest_by_target_ref = list() + +/** + * Turns new_poi into a new point of interest by adding the /datum/element/point_of_interest element to it. + */ +/datum/controller/subsystem/points_of_interest/proc/make_point_of_interest(atom/new_poi) + new_poi.AddElement(/datum/element/point_of_interest) + +/** + * Stops old_poi from being a point of interest by removing the /datum/element/point_of_interest element from it. + */ +/datum/controller/subsystem/points_of_interest/proc/remove_point_of_interest(atom/old_poi) + old_poi.RemoveElement(/datum/element/point_of_interest) + +/** + * Called by [/datum/element/point_of_interest] when it gets removed from old_poi. + */ +/datum/controller/subsystem/points_of_interest/proc/on_poi_element_added(atom/new_poi) + var/datum/point_of_interest/new_poi_datum + if(ismob(new_poi)) + new_poi_datum = new /datum/point_of_interest/mob_poi(new_poi) + BINARY_INSERT_PROC_COMPARE(new_poi_datum, mob_points_of_interest, /datum/point_of_interest/mob_poi, new_poi_datum, compare_to, COMPARE_KEY) + points_of_interest_by_target_ref[REF(new_poi)] = new_poi_datum + else + new_poi_datum = new /datum/point_of_interest(new_poi) + BINARY_INSERT_PROC_COMPARE(new_poi_datum, other_points_of_interest, /datum/point_of_interest, new_poi_datum, compare_to, COMPARE_KEY) + points_of_interest_by_target_ref[REF(new_poi)] = new_poi_datum + + + SEND_SIGNAL(src, COMSIG_ADDED_POINT_OF_INTEREST, new_poi) + +/** + * Called by [/datum/element/point_of_interest] when it gets removed from old_poi. + */ +/datum/controller/subsystem/points_of_interest/proc/on_poi_element_removed(atom/old_poi) + var/poi_ref = REF(old_poi) + var/datum/point_of_interest/poi_to_remove = points_of_interest_by_target_ref[poi_ref] + + if(!poi_to_remove) + return + + if(ismob(old_poi)) + mob_points_of_interest -= poi_to_remove + else + other_points_of_interest -= poi_to_remove + + points_of_interest_by_target_ref -= poi_ref + + poi_to_remove.target = null + + SEND_SIGNAL(src, COMSIG_REMOVED_POINT_OF_INTEREST, old_poi) + +/** + * If there is a valid POI for a given reference, it returns that POI's associated atom. Otherwise, it returns null. + */ +/datum/controller/subsystem/points_of_interest/proc/get_poi_atom_by_ref(reference) + return points_of_interest_by_target_ref[reference]?.target + +/** + * Returns a list of mob POIs with names as keys and mobs as values. + * + * If multiple POIs have the same name, then avoid_assoc_duplicate_keys is used alongside used_name_list to + * tag them as Mob Name (1), Mob Name (2), Mob Name (3) etc. + * + * Arguments: + * * poi_validation_override - [OPTIONAL] Callback to a proc that takes a single argument for the POI and returns TRUE if this POI should be included. Overrides standard POI validation. + * * append_dead_role - [OPTIONAL] If TRUE, adds a ghost tag to the end of observer names and a dead tag to the end of any other mob which is not alive. + */ +/datum/controller/subsystem/points_of_interest/proc/get_mob_pois(datum/callback/poi_validation_override = null, append_dead_role = TRUE) + var/list/pois = list() + var/list/used_name_list = list() + + for(var/datum/point_of_interest/mob_poi/mob_poi as anything in mob_points_of_interest) + if(poi_validation_override) + if(!poi_validation_override.Invoke(mob_poi)) + continue + else if(!mob_poi.validate()) + continue + + var/mob/target_mob = mob_poi.target + var/name = avoid_assoc_duplicate_keys(target_mob.name, used_name_list) + target_mob.get_realname_string() + + // Add the ghost/dead tag to the end of dead mob POIs. + if(append_dead_role && target_mob.stat == DEAD) + if(isobserver(target_mob)) + name += " \[ghost\]" + else + name += " \[dead\]" + + pois[name] = target_mob + + return pois + +/** + * Returns a list of non-mob POIs with names as keys and atoms as values. + * + * If multiple POIs have the same name, then avoid_assoc_duplicate_keys is used alongside used_name_list to + * tag them as Object Name (1), Object Name (2), Object Name (3) etc. + * + * Arguments: + * * poi_validation_override - [OPTIONAL] Callback to a proc that takes a single argument for the POI and returns TRUE if this POI should be included. Overrides standard POI validation. + */ +/datum/controller/subsystem/points_of_interest/proc/get_other_pois(datum/callback/poi_validation_override = null) + var/list/pois = list() + var/list/used_name_list = list() + + for(var/datum/point_of_interest/other_poi as anything in other_points_of_interest) + if(poi_validation_override) + if(!poi_validation_override.Invoke(other_poi)) + continue + else if(!other_poi.validate()) + continue + + var/atom/target_poi = other_poi.target + + pois[avoid_assoc_duplicate_keys(target_poi.name, used_name_list)] = target_poi + + return pois + +/// Returns TRUE if potential_poi has an associated poi_datum that validates. +/datum/controller/subsystem/points_of_interest/proc/is_valid_poi(atom/potential_poi, datum/callback/poi_validation_override = null) + var/datum/point_of_interest/poi_datum = points_of_interest_by_target_ref[REF(potential_poi)] + + if(!poi_datum) + return FALSE + + if(poi_validation_override) + return poi_validation_override.Invoke(poi_datum) + + return poi_datum.validate() + +/// Simple helper datum for points of interest. +/datum/point_of_interest + /// The specific point of interest this datum references. This won't hard del as the POI element will be removed from the target when it qdels, which will clear this reference. + var/atom/target + /// The type of POI this datum references. + var/poi_type = /atom + +/datum/point_of_interest/New(poi_target) + if(!istype(poi_target, poi_type)) + CRASH("Incorrect target type provided to /datum/point_of_interest/New: Expected \[[poi_type]\]") + + target = poi_target + +/// Validates the POI. Returns TRUE if the POI has valid state, returns FALSE if the POI has invalid state. +/datum/point_of_interest/proc/validate() + // In nullspace, invalid as a POI. + if(!target.loc) + return FALSE + + return TRUE + +/// Comparison proc used to sort POIs. Override to implement logic used doing binary sort insertions. +/datum/point_of_interest/proc/compare_to(datum/point_of_interest/rhs) + return cmp_name_asc(target, rhs.target) + +/datum/point_of_interest/mob_poi + poi_type = /mob + +/// Validation for mobs is expanded to invalidate stealthmins and /mob/dead/new_player as POIs. +/datum/point_of_interest/mob_poi/validate() + . = ..() + + if(!.) + return + + var/mob/poi_mob = target + + // Stealthmin, invalid as a POI. + if(poi_mob.client?.holder?.fakekey) + return FALSE + + /* + // POI is a /mob/dead/new_player, players in the lobby are invalid as POIs. + if(isnewplayer(poi_mob)) + return FALSE + */ + + return TRUE + +/// Mob POIs are sorted by a simple priority list depending on their type. When their type priority is identical, they're sub-sorted by name. +/datum/point_of_interest/mob_poi/compare_to(datum/point_of_interest/mob_poi/rhs) + var/sort_difference = get_type_sort_priority() - rhs.get_type_sort_priority() + + // If they're equal in priority, call parent to sort by name. + if(sort_difference == 0) + return ..() + // Else sort by priority. + else + return sort_difference + +/// Priority list broadly stolen from /proc/sortmobs(). Lower numbers are higher priorities when sorted and appear closer to the top or start of lists. +/datum/point_of_interest/mob_poi/proc/get_type_sort_priority() + if(isAI(target)) + return 0 + if(iscameramob(target)) + return 1 + if(ispAI(target)) + return 2 + if(iscyborg(target)) + return 3 + if(ishuman(target)) + return 4 + if(isbrain(target)) + return 5 + if(isalien(target)) + return 6 + if(isobserver(target)) + return 7 + if(isnewplayer(target)) + return 8 + if(isslime(target)) + return 9 + if(isanimal(target)) + return 10 + return 11 diff --git a/code/datums/elements/point_of_interest.dm b/code/datums/elements/point_of_interest.dm new file mode 100644 index 0000000000000..d64ee5466ace9 --- /dev/null +++ b/code/datums/elements/point_of_interest.dm @@ -0,0 +1,22 @@ +/// Designates the atom as a "point of interest", meaning it can be directly orbited +/datum/element/point_of_interest + element_flags = ELEMENT_DETACH + +/datum/element/point_of_interest/Attach(datum/target) + if (!isatom(target)) + return ELEMENT_INCOMPATIBLE + + /* + // New players are abstract mobs assigned to people who are still in the lobby screen. + // As a result, they are not a valid POI and should never be a valid POI. If they + // somehow get this element attached to them, there's something we need to debug. + if(isnewplayer(target)) + return ELEMENT_INCOMPATIBLE + */ + + SSpoints_of_interest.on_poi_element_added(target) + return ..() + +/datum/element/point_of_interest/Detach(datum/target) + SSpoints_of_interest.on_poi_element_removed(target) + return ..() diff --git a/code/datums/spawners_menu.dm b/code/datums/spawners_menu.dm index 9e7e4b334ddc0..01709a00c1a12 100644 --- a/code/datums/spawners_menu.dm +++ b/code/datums/spawners_menu.dm @@ -53,7 +53,7 @@ if(!spawnerlist.len) return var/obj/effect/mob_spawn/MS = pick(spawnerlist) - if(!istype(MS) || !(MS in GLOB.poi_list)) + if(!istype(MS) || !(MS in SSpoints_of_interest.other_points_of_interest)) return switch(action) if("jump") diff --git a/code/game/atom/atom_orbit.dm b/code/game/atom/atom_orbit.dm new file mode 100644 index 0000000000000..2294293bd8b70 --- /dev/null +++ b/code/game/atom/atom_orbit.dm @@ -0,0 +1,33 @@ +/atom + ///Reference to atom being orbited + var/atom/orbit_target + ///The orbiter component, if there's anything orbiting this atom + var/datum/component/orbiter/orbiters + +/** + * Recursive getter method to return a list of all ghosts orbitting this atom + * + * This will work fine without manually passing arguments. + * * processed - The list of atoms we've already convered + * * source - Is this the atom for who we're counting up all the orbiters? + * * ignored_stealthed_admins - If TRUE, don't count admins who are stealthmoded and orbiting this + */ +/atom/proc/get_all_orbiters(list/processed, source = TRUE, ignore_stealthed_admins = TRUE) + var/list/output = list() + if(!processed) + processed = list() + else if(src in processed) + return output + + if(!source) + output += src + + processed += src + for(var/atom/atom_orbiter as anything in orbiters?.orbiters) + output += atom_orbiter.get_all_orbiters(processed, source = FALSE) + return output + +/mob/get_all_orbiters(list/processed, source = TRUE, ignore_stealthed_admins = TRUE) + if(!source && ignore_stealthed_admins && client?.holder?.fakekey) + return list() + return ..() diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f52b9bdace9e3..b96e8a53c824b 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -75,9 +75,6 @@ ///Economy cost of item in premium vendor var/custom_premium_price - //List of datums orbiting this atom - var/datum/component/orbiter/orbiters - /// Radiation insulation types var/rad_insulation = RAD_NO_INSULATION @@ -154,8 +151,6 @@ /// The current connector overlay appearance. Saved so that it can be cut when necessary. var/connector_overlay - ///Reference to atom being orbited - var/atom/orbit_target ///Default X pixel offset var/base_pixel_x ///Default Y pixel offset diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index c3895f3022790..83d7a32d1fd9f 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -56,7 +56,7 @@ if(isliving(wizard.current) && wizard.current.stat!=DEAD) return FALSE - for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead() + for(var/obj/item/phylactery/P in SSpoints_of_interest.other_points_of_interest) //TODO : IsProperlyDead() if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard)) return FALSE diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index e99d24e3f558f..d330865a4be26 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -65,17 +65,20 @@ /turf/closed/wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) while(drill.do_after_mecha(src, 15 / drill.drill_level)) drill.log_message("Drilled through [src]", LOG_MECHA) - alter_integrity(-drill.wall_decon_damage) drill.occupant_message("You drill through some of the outer plating...") playsound(src,'sound/weapons/drill.ogg',60,TRUE) + if(!alter_integrity(-drill.wall_decon_damage)) + return TRUE /turf/closed/wall/r_wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) if(drill.drill_level >= DRILL_HARDENED) while(drill.do_after_mecha(src, 20 / drill.drill_level)) drill.log_message("Drilled through [src]", LOG_MECHA) - alter_integrity(-drill.wall_decon_damage) drill.occupant_message("You drill through some of the outer plating...") playsound(src,'sound/weapons/drill.ogg',60,TRUE) + if(!alter_integrity(-drill.wall_decon_damage)) + return TRUE + else drill.occupant_message("[src] is too durable to drill through.") diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index b903564c88d6d..a1b46fd2fbfa5 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -137,7 +137,7 @@ add_scanmod() add_capacitor() START_PROCESSING(SSobj, src) - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) log_message("[src.name] created.", LOG_MECHA) GLOB.mechas_list += src //global mech list prepare_huds() @@ -176,7 +176,7 @@ AI.gib() //No wreck, no AI to recover AI = null STOP_PROCESSING(SSobj, src) - GLOB.poi_list.Remove(src) + SSpoints_of_interest.remove_point_of_interest(src) equipment.Cut() for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 17d6cf96b21a9..a1302008cf89a 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -957,6 +957,9 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb /// Called when a mob tries to use the item as a tool.Handles most checks. /obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks) + // we have no target, why are we even doing this? + if(isnull(target)) + return // No delay means there is no start message, and no reason to call tool_start_check before use_tool. // Run the start check here so we wouldn't have to call it manually. if(!delay && !tool_start_check(user, amount)) diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm index 1396521aaf9aa..b721393e85edf 100644 --- a/code/game/objects/items/eightball.dm +++ b/code/game/objects/items/eightball.dm @@ -136,10 +136,10 @@ become_hearing_sensitive(ROUNDSTART_TRAIT) for (var/answer in haunted_answers) votes[answer] = 0 - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) /obj/item/toy/eightball/haunted/Destroy() - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) . = ..() /obj/item/toy/eightball/haunted/MakeHaunted() diff --git a/code/game/objects/items/storage/ration.dm b/code/game/objects/items/storage/ration.dm index b016cc3392601..169e0dfad0a6a 100644 --- a/code/game/objects/items/storage/ration.dm +++ b/code/game/objects/items/storage/ration.dm @@ -54,7 +54,7 @@ /obj/item/reagent_containers/food/snacks/ration/entree/vegan_chili = 1, /obj/item/reagent_containers/food/snacks/ration/side/vegan_crackers = 1, /obj/item/reagent_containers/food/snacks/ration/side/cornbread = 1, - /obj/item/reagent_containers/food/snacks/ration/snack/pizza_crackers = 1, + /obj/item/reagent_containers/food/snacks/ration/snack/fruit_puree = 1, /obj/item/reagent_containers/food/snacks/ration/condiment/cheese_spread = 1, /obj/item/reagent_containers/food/snacks/ration/pack/grape_beverage = 1, /obj/item/ration_heater = 1 diff --git a/code/game/turfs/closed/_closed.dm b/code/game/turfs/closed/_closed.dm index dc410d027504e..766d7e0e5a24c 100644 --- a/code/game/turfs/closed/_closed.dm +++ b/code/game/turfs/closed/_closed.dm @@ -227,6 +227,8 @@ return ..() /turf/closed/proc/attack_override(obj/item/W, mob/user, turf/loc) + if(!isclosedturf(src)) + return //the istype cascade has been spread among various procs for easy overriding or if we want to call something specific if(try_decon(W, user, loc) || try_destroy(W, user, loc)) return @@ -252,15 +254,18 @@ return TRUE /turf/closed/proc/try_decon(obj/item/I, mob/user, turf/T) + var/act_duration = breakdown_duration if(I.tool_behaviour == TOOL_WELDER) if(!I.tool_start_check(user, amount=0)) return FALSE - to_chat(user, "You begin slicing through the outer plating...") - while(I.use_tool(src, user, breakdown_duration, volume=50)) + while(I.use_tool(src, user, act_duration, volume=50)) if(iswallturf(src)) to_chat(user, "You slice through some of the outer plating...") - alter_integrity(-(I.wall_decon_damage),user,FALSE,TRUE) + if(!alter_integrity(-(I.wall_decon_damage),user,FALSE,TRUE)) + return TRUE + else + break return FALSE diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm index 0d9b3205cc278..3970cc403d73b 100644 --- a/code/game/turfs/closed/minerals.dm +++ b/code/game/turfs/closed/minerals.dm @@ -79,16 +79,20 @@ return ..() /turf/closed/mineral/try_decon(obj/item/I, mob/user, turf/T) + var/act_duration = breakdown_duration if(I.tool_behaviour == TOOL_MINING) if(!I.tool_start_check(user, amount=0)) return FALSE to_chat(user, "You begin breaking through the rock...") - while(I.use_tool(src, user, breakdown_duration, volume=50)) + while(I.use_tool(src, user, act_duration, volume=50)) if(ismineralturf(src)) to_chat(user, "You break through some of the stone...") SSblackbox.record_feedback("tally", "pick_used_mining", 1, I.type) - alter_integrity(-(I.wall_decon_damage),user,FALSE,TRUE) + if(!alter_integrity(-(I.wall_decon_damage),user,FALSE,TRUE)) + return TRUE + else + break return FALSE diff --git a/code/game/turfs/closed/wall/reinf_walls.dm b/code/game/turfs/closed/wall/reinf_walls.dm index ed2f0141eaff5..c0fb9232ad286 100644 --- a/code/game/turfs/closed/wall/reinf_walls.dm +++ b/code/game/turfs/closed/wall/reinf_walls.dm @@ -78,7 +78,8 @@ to_chat(user, "You begin slicing through the [src].") while(W.use_tool(src,user,30,volume = 100)) to_chat(user, "You slice through some of the outer plating...") - alter_integrity(-(W.wall_decon_damage)) + if(!alter_integrity(-(W.wall_decon_damage))) + return TRUE return 1 switch(d_state) diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index bed648ff592b2..1d8f242e216a3 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -85,9 +85,10 @@ return null /turf/closed/wall/attack_override(obj/item/W, mob/user, turf/loc) - if(try_clean(W, user, loc) || try_wallmount(W, user, loc)) + if(!iswallturf(src)) + return + if(try_clean(W, user, loc) || try_wallmount(W, user, loc) || try_decon(W, user, loc) || try_destroy(W, user, loc)) return - ..() /turf/closed/wall/proc/try_clean(obj/item/W, mob/user, turf/T) if((user.a_intent != INTENT_HELP)) @@ -122,19 +123,6 @@ return FALSE -/turf/closed/wall/try_decon(obj/item/I, mob/user, turf/T) - if(I.tool_behaviour == TOOL_WELDER) - if(!I.tool_start_check(user, amount=0)) - return FALSE - - to_chat(user, "You begin slicing through the outer plating...") - while(I.use_tool(src, user, breakdown_duration, volume=50)) - if(iswallturf(src)) - to_chat(user, "You slice through some of the outer plating...") - alter_integrity(-(I.wall_decon_damage),FALSE,TRUE) - - return FALSE - /turf/closed/wall/singularity_pull(S, current_size) ..() wall_singularity_pull(current_size) diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index cf834c9f9c5d0..e5888f8088dfd 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -216,9 +216,10 @@ "} - var/list/mobs = sortmobs() + var/list/mobs = SSpoints_of_interest.get_mob_pois() var/i = 1 - for(var/mob/M in mobs) + for(var/mob_name in mobs) + var/mob/M = mobs[mob_name] if(M.ckey) var/color = "#e6e6e6" @@ -254,12 +255,7 @@ M_job = "Silicon-based" else if(isanimal(M)) //simple animals - if(iscorgi(M)) - M_job = "Corgi" - else if(isslime(M)) - M_job = "slime" - else - M_job = "Animal" + M_job = "Animal" else M_job = "Living" diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index 9b84224317a95..708448cf52cdf 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -140,7 +140,7 @@ usr.forceMove(M.loc) SSblackbox.record_feedback("tally", "admin_verb", 1, "Get Key") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/sendmob(mob/M in sortmobs()) +/client/proc/sendmob(mob/M in SSpoints_of_interest.get_mob_pois()) set category = "Admin.Game" set name = "Send Mob" if(!src.holder) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index b0fb446405c2b..3382672071cc2 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -450,10 +450,10 @@ structure_check() searches for nearby cultist structures required for the invoca /obj/effect/rune/narsie/Initialize(mapload, set_keyword) . = ..() - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) /obj/effect/rune/narsie/Destroy() - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) . = ..() /obj/effect/rune/narsie/conceal() //can't hide this, and you wouldn't want to @@ -469,7 +469,7 @@ structure_check() searches for nearby cultist structures required for the invoca if(!(place in summon_objective.summon_spots)) to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!") return - if(locate(/obj/singularity/narsie) in GLOB.poi_list) + if(locate(/obj/singularity/narsie) in SSpoints_of_interest.other_points_of_interest) for(var/M in invokers) to_chat(M, "Nar'Sie is already on this plane!") log_game("Nar'Sie rune failed - already summoned") diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm index 26d7321eb813c..9c65e50130cf9 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm @@ -38,7 +38,7 @@ core = new /obj/item/nuke_core(src) STOP_PROCESSING(SSobj, core) update_appearance() - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) previous_level = get_security_level() /obj/machinery/nuclearbomb/Destroy() @@ -46,7 +46,7 @@ if(!exploding) // If we're not exploding, set the alert level back to normal set_safety() - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) GLOB.nuke_list -= src QDEL_NULL(countdown) QDEL_NULL(core) @@ -611,7 +611,7 @@ This is here to make the tiles around the station mininuke change when it's arme AddElement(/datum/element/bed_tuckable, 6, -6, 0) if(!fake) - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) last_disk_move = world.time START_PROCESSING(SSobj, src) @@ -661,7 +661,7 @@ This is here to make the tiles around the station mininuke change when it's arme /obj/item/disk/nuclear/Destroy(force=FALSE) // respawning is handled in /obj/Destroy() if(force) - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) . = ..() /obj/item/disk/nuclear/fake diff --git a/code/modules/antagonists/nukeop/equipment/pinpointer.dm b/code/modules/antagonists/nukeop/equipment/pinpointer.dm index b316e60c5e141..c1f9ffa374281 100644 --- a/code/modules/antagonists/nukeop/equipment/pinpointer.dm +++ b/code/modules/antagonists/nukeop/equipment/pinpointer.dm @@ -32,7 +32,7 @@ target = null switch(mode) if(TRACK_NUKE_DISK) - var/obj/item/disk/nuclear/N = locate() in GLOB.poi_list + var/obj/item/disk/nuclear/N = locate() in SSpoints_of_interest.other_points_of_interest target = N if(TRACK_MALF_AI) for(var/V in GLOB.ai_list) diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index 9f807d9521e77..f51c641424506 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -345,7 +345,7 @@ /datum/team/nuclear/antag_listing_entry() var/disk_report = "Nuclear Disk(s)
" disk_report += "
" - for(var/obj/item/disk/nuclear/N in GLOB.poi_list) + for(var/obj/item/disk/nuclear/N in SSpoints_of_interest.other_points_of_interest) disk_report += "
[N.name], " var/atom/disk_loc = N.loc while(!isturf(disk_loc)) diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm index 42d7643fb9266..5fc667c4db4a8 100644 --- a/code/modules/awaymissions/capture_the_flag.dm +++ b/code/modules/awaymissions/capture_the_flag.dm @@ -195,10 +195,10 @@ /obj/machinery/capture_the_flag/Initialize() . = ..() - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) /obj/machinery/capture_the_flag/Destroy() - GLOB.poi_list.Remove(src) + SSpoints_of_interest.remove_point_of_interest(src) return ..() /obj/machinery/capture_the_flag/process() diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 0bf0b74c715af..26361b99cfc60 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -61,11 +61,11 @@ if(instant || (roundstart && (mapload || (SSticker && SSticker.current_state > GAME_STATE_SETTING_UP)))) INVOKE_ASYNC(src, PROC_REF(create)) else if(ghost_usable) - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) LAZYADD(GLOB.mob_spawners[name], src) /obj/effect/mob_spawn/Destroy() - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) var/list/spawners = GLOB.mob_spawners[name] LAZYREMOVE(spawners, src) if(!LAZYLEN(spawners)) diff --git a/code/modules/cargo/blackmarket/blackmarket_items/ammo.dm b/code/modules/cargo/blackmarket/blackmarket_items/ammo.dm index 47f7fd8849933..d5489edeb3e04 100644 --- a/code/modules/cargo/blackmarket/blackmarket_items/ammo.dm +++ b/code/modules/cargo/blackmarket/blackmarket_items/ammo.dm @@ -271,3 +271,25 @@ stock_min = 2 stock_max = 10 availability_prob = 10 + +/datum/blackmarket_item/ammo/c38hotshot + name = ".38 Hearth Ammo Box" + desc = "We got our ship cook to marinade some .38 in some hearthwine we pocketed off some hunters. It'll cook your targets to a nice well done." + item = /obj/item/ammo_box/c38/hotshot + + price_min = 300 + price_max = 500 + stock_min = 3 + stock_max = 8 + availability_prob = 50 + +/datum/blackmarket_item/ammo/c38iceblox + name = ".38 Chilled Ammo Box" + desc = "One of our runners accidentally spilled some .38 into a fucking pristine icewine shipment. It'll freeze your targets faster than our runner froze solid outside for making a mess." + item = /obj/item/ammo_box/c38/iceblox + + price_min = 300 + price_max = 500 + stock_min = 3 + stock_max = 8 + availability_prob = 50 diff --git a/code/modules/cargo/blackmarket/blackmarket_items/clothing.dm b/code/modules/cargo/blackmarket/blackmarket_items/clothing.dm index d049589fe40a8..7a9803085ab8d 100644 --- a/code/modules/cargo/blackmarket/blackmarket_items/clothing.dm +++ b/code/modules/cargo/blackmarket/blackmarket_items/clothing.dm @@ -264,7 +264,7 @@ price_min = 1500 price_max = 2500 - stock = 1 + stock_max = 3 availability_prob = 30 /datum/blackmarket_item/clothing/frontiersmen_hardsuit diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index dfec659e1644f..0b302925e10e7 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -383,7 +383,7 @@ if (specificTarget) specificTarget = null return - var/list/mobs = getpois()//code stolen from observer.dm + var/list/mobs = SSpoints_of_interest.get_mob_pois() var/inputTarget = input("Select a mob! (Smiting does this automatically)", "Target", null, null) as null|anything in mobs if (isnull(inputTarget)) return diff --git a/code/modules/cargo/packs/ammo.dm b/code/modules/cargo/packs/ammo.dm index 6fa0b54966c1d..a7ab407b428e5 100644 --- a/code/modules/cargo/packs/ammo.dm +++ b/code/modules/cargo/packs/ammo.dm @@ -72,6 +72,18 @@ cost = 500 contains = list(/obj/item/ammo_box/a12g/slug) +/datum/supply_pack/ammo/blank_shells + name = "Blank Shell Crate" + desc = "Contains a box of blank shells." + cost = 500 + contains = list(/obj/item/ammo_box/a12g/blanks) + +/datum/supply_pack/ammo/blank_ammo_disk + name = "Blank Ammo Design Disk Crate" + desc = "Run your own training drills!" + cost = 1000 + contains = list(/obj/item/disk/design_disk/blanks) + /datum/supply_pack/ammo/techshells name = "Unloaded Shotgun Technological Shells Crate" desc = "Contains a box of 7 versatile tech shells, capable of producing a variety of deadly effects for any situation. Some assembly required." diff --git a/code/modules/cargo/packs/mechs.dm b/code/modules/cargo/packs/mechs.dm index 7790e696ee15b..744e9f67e2f21 100644 --- a/code/modules/cargo/packs/mechs.dm +++ b/code/modules/cargo/packs/mechs.dm @@ -220,6 +220,15 @@ Mech Equipment /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster ) +/datum/supply_pack/mech/equipment/recharger + name = "Exosuit Recharger kit" + desc = "Two boards for an exosuit recharger and recharger console. For the stylish exosuit bay." + cost = 400 + contains = list( + /obj/item/circuitboard/computer/mech_bay_power_console, + /obj/item/circuitboard/machine/mech_recharger + ) + /* weapons */ diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index d1ee50d1a629a..0d05c4e0cf7fb 100644 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -137,6 +137,7 @@ icon_state = "bronze" custom_materials = list(/datum/material/iron=1000) resistance_flags = FIRE_PROOF + attachment_slot = null var/medaltype = "medal" //Sprite used for medalbox var/commended = FALSE @@ -409,6 +410,7 @@ icon_state = "holster" item_state = "holster" pocket_storage_component_path = /datum/component/storage/concrete/pockets/holster + attachment_slot = null /obj/item/clothing/accessory/holster/detective name = "detective's shoulder holster" @@ -477,7 +479,7 @@ icon_state = "rilena_pin" above_suit = FALSE minimize_when_attached = TRUE - attachment_slot = CHEST + attachment_slot = null /obj/item/clothing/accessory/rilena_pin/on_uniform_equip(obj/item/clothing/under/U, user) var/mob/living/L = user diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index adde1124935fd..4ba2d878ad463 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -62,7 +62,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 z_original = z destination = end special_target = aimed_at - GLOB.poi_list += src + SSpoints_of_interest.make_point_of_interest(src) var/special_target_valid = FALSE if(special_target) @@ -81,7 +81,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 ghost.ManualFollow(src) /obj/effect/immovablerod/Destroy() - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) . = ..() /obj/effect/immovablerod/Moved() diff --git a/code/modules/events/wizard/greentext.dm b/code/modules/events/wizard/greentext.dm index 890bbc0f1f2b7..8e4baab893fc5 100644 --- a/code/modules/events/wizard/greentext.dm +++ b/code/modules/events/wizard/greentext.dm @@ -34,7 +34,7 @@ /obj/item/greentext/Initialize(mapload) . = ..() - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) roundend_callback = CALLBACK(src, PROC_REF(check_winner)) SSticker.OnRoundend(roundend_callback) @@ -83,7 +83,7 @@ if(!(resistance_flags & ON_FIRE) && !force) return QDEL_HINT_LETMELIVE - GLOB.poi_list.Remove(src) + SSpoints_of_interest.remove_point_of_interest(src) LAZYREMOVE(SSticker.round_end_events, roundend_callback) roundend_callback = null //This ought to free the callback datum, and prevent us from harddeling for(var/i in GLOB.player_list) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index afae0dd0a6c04..e3e9f6aac8f0b 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -150,34 +150,6 @@ if(28) new /obj/item/clothing/suit/armor/ascetic(src) -//KA modkit design discs -/obj/item/disk/design_disk/modkit_disc - name = "KA Mod Disk" - desc = "A design disc containing the design for a unique kinetic accelerator modkit. It's compatible with a research console." - illustration = "accel" - color = "#6F6F6F" - var/modkit_design = /datum/design/unique_modkit - -/obj/item/disk/design_disk/modkit_disc/Initialize() - . = ..() - blueprints[1] = new modkit_design - -/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe - name = "Offensive Mining Explosion Mod Disk" - modkit_design = /datum/design/unique_modkit/offensive_turf_aoe - -/obj/item/disk/design_disk/modkit_disc/rapid_repeater - name = "Rapid Repeater Mod Disk" - modkit_design = /datum/design/unique_modkit/rapid_repeater - -/obj/item/disk/design_disk/modkit_disc/resonator_blast - name = "Resonator Blast Mod Disk" - modkit_design = /datum/design/unique_modkit/resonator_blast - -/obj/item/disk/design_disk/modkit_disc/bounty - name = "Death Syphon Mod Disk" - modkit_design = /datum/design/unique_modkit/bounty - /datum/design/unique_modkit category = list("Mining Designs", "Cyborg Upgrade Modules") //can't be normally obtained build_type = PROTOLATHE | MECHFAB diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 8fbf9c32a38e6..2dbbd9d4b65b4 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -35,6 +35,7 @@ . = ..() GLOB.new_player_list += src + SSpoints_of_interest.make_point_of_interest(src) /mob/dead/new_player/Destroy() GLOB.new_player_list -= src diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index c15c4a1af8354..0fcfa5c13940b 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -62,6 +62,9 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) var/datum/orbit_menu/orbit_menu var/datum/spawners_menu/spawners_menu + // The POI we're orbiting (orbit menu) + var/orbiting_ref + /mob/dead/observer/Initialize() set_invisibility(GLOB.observer_default_invisibility) @@ -142,6 +145,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) . = ..() + SSpoints_of_interest.make_point_of_interest(src) + grant_all_languages() show_data_huds() data_huds_on = 1 @@ -499,7 +504,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/list/dest = list() //List of possible destinations (mobs) var/target = null //Chosen target. - dest += getpois(mobs_only = TRUE) //Fill list, prompt user with list + dest += SSpoints_of_interest.get_mob_pois() target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest if (!target)//Make sure we actually have a target @@ -839,20 +844,24 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/reset_perspective(atom/A) if(client) if(ismob(client.eye) && (client.eye != src)) - var/mob/target = client.eye - observetarget = null - if(target.observers) - LAZYREMOVE(target.observers, src) + cleanup_observe() if(..()) if(hud_used) client.screen = list() hud_used.show_hud(hud_used.hud_version) +/mob/dead/observer/proc/cleanup_observe() + var/mob/target = client.eye + observetarget = null + client?.perspective = initial(client.perspective) + if(target.observers) + LAZYREMOVE(target.observers, src) + /mob/dead/observer/verb/observe() set name = "Observe" set category = "Ghost" - var/list/creatures = getpois() + var/list/creatures = SSpoints_of_interest.get_mob_pois() reset_perspective(null) diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index 86d54577538cb..051faa5bedac1 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -1,6 +1,9 @@ /datum/orbit_menu + ///mobs worth orbiting. Because spaghetti, all mobs have the point of interest, but only some are allowed to actually show up. + ///this obviously should be changed in the future, so we only add mobs as POI if they actually are interesting, and we don't use + ///a typecache. + var/static/list/mob_allowed_typecache var/mob/dead/observer/owner - var/auto_observe = FALSE /datum/orbit_menu/New(mob/dead/observer/new_owner) if(!istype(new_owner)) @@ -23,87 +26,243 @@ switch(action) if ("orbit") var/ref = params["ref"] - var/atom/movable/poi = (locate(ref) in GLOB.mob_list) || (locate(ref) in GLOB.poi_list) - if (poi == null) - . = TRUE - return + var/auto_observe = params["auto_observe"] + var/atom/movable/poi = SSpoints_of_interest.get_poi_atom_by_ref(ref) + + if((ismob(poi) && !SSpoints_of_interest.is_valid_poi(poi, CALLBACK(src, PROC_REF(validate_mob_poi)))) \ + || !SSpoints_of_interest.is_valid_poi(poi) + ) + to_chat(usr, span_notice("That point of interest is no longer valid.")) + return TRUE + + var/mob/dead/observer/user = usr owner.ManualFollow(poi) owner.reset_perspective(null) + user.orbiting_ref = ref if (auto_observe) owner.do_observe(poi) . = TRUE if ("refresh") update_static_data(owner, ui) . = TRUE - if ("toggle_observe") - auto_observe = !auto_observe - if (auto_observe && owner.orbit_target) - owner.do_observe(owner.orbit_target) - else - owner.reset_perspective(null) + /datum/orbit_menu/ui_data(mob/user) var/list/data = list() - data["auto_observe"] = auto_observe + + if(isobserver(user)) + data["orbiting"] = get_currently_orbiting(user) + return data /datum/orbit_menu/ui_static_data(mob/user) - var/list/data = list() + var/list/new_mob_pois = SSpoints_of_interest.get_mob_pois(CALLBACK(src, PROC_REF(validate_mob_poi)), append_dead_role = FALSE) + var/list/new_other_pois = SSpoints_of_interest.get_other_pois() var/list/alive = list() var/list/antagonists = list() + var/list/critical = list() var/list/dead = list() var/list/ghosts = list() var/list/misc = list() var/list/npcs = list() + var/list/ships = list() - var/list/pois = getpois(skip_mindless = TRUE, specify_dead_role = FALSE) - for (var/name in pois) + for(var/name in new_mob_pois) var/list/serialized = list() - serialized["name"] = name - - var/poi = pois[name] - - serialized["ref"] = REF(poi) - - var/mob/M = poi - if (istype(M)) - if (isobserver(M)) - ghosts += list(serialized) - else if (M.stat == DEAD) - dead += list(serialized) - else if (M.mind == null) - npcs += list(serialized) - else - var/number_of_orbiters = M.orbiters?.orbiters?.len - if (number_of_orbiters) - serialized["orbiters"] = number_of_orbiters - - var/datum/mind/mind = M.mind - var/was_antagonist = FALSE - - for (var/_A in mind.antag_datums) - var/datum/antagonist/A = _A - if (A.show_to_ghosts) - was_antagonist = TRUE - serialized["antag"] = A.name - antagonists += list(serialized) - break - - if (!was_antagonist) - alive += list(serialized) + var/mob/mob_poi = new_mob_pois[name] + var/number_of_orbiters = length(mob_poi.get_all_orbiters()) + + if(isnewplayer(mob_poi)) + continue + + serialized["ref"] = REF(mob_poi) + serialized["full_name"] = mob_poi.name + serialized["job"] = mob_poi.job + if(number_of_orbiters) + serialized["orbiters"] = number_of_orbiters + + if(isobserver(mob_poi)) + ghosts += list(serialized) + continue + + if(mob_poi.stat == DEAD) + dead += list(serialized) + continue + + if(isnull(mob_poi.mind)) + if(isliving(mob_poi)) + var/mob/living/npc = mob_poi + serialized["health"] = FLOOR((npc.health / npc.maxHealth * 100), 1) + + npcs += list(serialized) + continue + + serialized["client"] = !!mob_poi.client + serialized["name"] = mob_poi.real_name + + if(isliving(mob_poi)) + serialized += get_living_data(mob_poi) + + var/list/antag_data = get_antag_data(mob_poi.mind) + if(length(antag_data)) + serialized += antag_data + antagonists += list(serialized) + continue + + alive += list(serialized) + + for(var/name in new_other_pois) + var/atom/atom_poi = new_other_pois[name] + + var/list/other_data = get_misc_data(atom_poi) + var/misc_data = list(other_data[1]) + + if(istype(atom_poi, /obj/machinery/computer/helm)) + ships += misc_data else - misc += list(serialized) - - data["alive"] = alive - data["antagonists"] = antagonists - data["dead"] = dead - data["ghosts"] = ghosts - data["misc"] = misc - data["npcs"] = npcs - return data + misc += misc_data + + if(other_data[2]) // Critical = TRUE + critical += misc_data + + return list( + "alive" = alive, + "antagonists" = antagonists, + "critical" = critical, + "dead" = dead, + "ghosts" = ghosts, + "misc" = misc, + "npcs" = npcs, + "ships" = ships, + ) /datum/orbit_menu/ui_assets() . = ..() || list() . += get_asset_datum(/datum/asset/simple/orbit) +/// Helper function to get threat type, group, overrides for job and icon +/datum/orbit_menu/proc/get_antag_data(datum/mind/poi_mind) as /list + var/list/serialized = list() + + for(var/datum/antagonist/antag as anything in poi_mind.antag_datums) + if(!antag.show_to_ghosts) + continue + + serialized["antag"] = antag.name + serialized["antag_group"] = antag.antagpanel_category + serialized["job"] = antag.name + serialized["icon"] = antag.antag_hud_name + + return serialized + +/// Helper to get the current thing we're orbiting (if any) +/datum/orbit_menu/proc/get_currently_orbiting(mob/dead/observer/user) + if(isnull(user.orbiting_ref)) + return + + var/atom/poi = SSpoints_of_interest.get_poi_atom_by_ref(user.orbiting_ref) + if(isnull(poi)) + user.orbiting_ref = null + return + + if((ismob(poi) && !SSpoints_of_interest.is_valid_poi(poi, CALLBACK(src, PROC_REF(validate_mob_poi)))) \ + || !SSpoints_of_interest.is_valid_poi(poi) + ) + user.orbiting_ref = null + return + + var/list/serialized = list() + + if(!ismob(poi)) + var/list/misc_info = get_misc_data(poi) + serialized += misc_info[1] + return serialized + + var/mob/mob_poi = poi + serialized["full_name"] = mob_poi.name + serialized["ref"] = REF(poi) + + if(mob_poi.mind) + serialized["client"] = !!mob_poi.client + serialized["name"] = mob_poi.real_name + + if(isliving(mob_poi)) + serialized += get_living_data(mob_poi) + + return serialized + +/// Helper function to get job / icon / health data for a living mob +/datum/orbit_menu/proc/get_living_data(mob/living/player) as /list + var/list/serialized = list() + + serialized["health"] = FLOOR((player.health / player.maxHealth * 100), 1) + + return serialized + + +/// Gets a list: Misc data and whether it's critical. Handles all snowflakey type cases +/datum/orbit_menu/proc/get_misc_data(atom/movable/atom_poi) as /list + var/list/misc = list() + var/critical = FALSE + + misc["ref"] = REF(atom_poi) + misc["full_name"] = atom_poi.name + + // Display the nuke timer + if(istype(atom_poi, /obj/machinery/nuclearbomb)) + var/obj/machinery/nuclearbomb/bomb = atom_poi + + if(bomb.timing) + misc["extra"] = "Timer: [bomb.countdown?.displayed_text]s" + critical = TRUE + + return list(misc, critical) + + // Display the holder if its a nuke disk + if(istype(atom_poi, /obj/item/disk/nuclear)) + var/obj/item/disk/nuclear/disk = atom_poi + var/mob/holder = disk.pulledby || get(disk, /mob) + misc["extra"] = "Location: [holder?.real_name || "Unsecured"]" + + return list(misc, critical) + + // Display singuloths if they exist + if(istype(atom_poi, /obj/singularity)) + var/obj/singularity/singulo = atom_poi + misc["extra"] = "Energy: [round(singulo.energy)]" + + if(singulo.current_size > 2) + critical = TRUE + + return list(misc, critical) + + if(istype(atom_poi, /obj/machinery/computer/helm)) + var/obj/machinery/computer/helm/helm_poi = atom_poi + if(helm_poi.current_ship) + misc["extra"] = "Ship: [helm_poi.current_ship.name]" + + return list(misc, critical) + + return list(misc, critical) + +/** + * Helper POI validation function passed as a callback to various SSpoints_of_interest procs. + * + * Provides extended validation above and beyond standard, limiting mob POIs without minds or ckeys + * unless they're mobs, camera mobs or megafauna. Also allows exceptions for mobs that are deadchat controlled. + * + * If they satisfy that requirement, falls back to default validation for the POI. + */ +/datum/orbit_menu/proc/validate_mob_poi(datum/point_of_interest/mob_poi/potential_poi) + var/mob/potential_mob_poi = potential_poi.target + if(!potential_mob_poi.mind && !potential_mob_poi.ckey) + if(!mob_allowed_typecache) + mob_allowed_typecache = typecacheof(list( + /mob/living/simple_animal/hostile/megafauna, + /mob/living/simple_animal/hostile/boss + )) + if(!is_type_in_typecache(potential_mob_poi, mob_allowed_typecache) && !potential_mob_poi.GetComponent(/datum/component/deadchat_control)) + return FALSE + + return potential_poi.validate() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 1258df8b84c5c..6046cfe82b633 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -9,6 +9,7 @@ diag_hud.add_to_hud(src) faction += "[REF(src)]" GLOB.mob_living_list += src + SSpoints_of_interest.make_point_of_interest(src) if(speed) update_living_varspeed() diff --git a/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm b/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm index e0537594c8ffe..76dc1f0950096 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm @@ -30,11 +30,6 @@ var/area/A = get_area(src) if(A) notify_ghosts("A drone shell has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_DRONE) - GLOB.poi_list |= src - -/obj/effect/mob_spawn/drone/Destroy() - GLOB.poi_list -= src - . = ..() //ATTACK GHOST IGNORING PARENT RETURN VALUE /obj/effect/mob_spawn/drone/attack_ghost(mob/user) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 863abf56dad1e..ff06df9c6113d 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -607,12 +607,12 @@ GLOBAL_DATUM(blackbox, /obj/machinery/smartfridge/black_box) var/ready_to_deploy = FALSE /obj/machinery/anomalous_crystal/helpers/Destroy() - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) . = ..() /obj/machinery/anomalous_crystal/helpers/ActivationReaction(mob/user, method) if(..() && !ready_to_deploy) - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) ready_to_deploy = TRUE notify_ghosts("An anomalous crystal has been activated in [get_area(src)]! This crystal can always be used by ghosts hereafter.", enter_link = "(Click to enter)", ghost_sound = 'sound/effects/ghost2.ogg', source = src, action = NOTIFY_ATTACK, header = "Anomalous crystal activated") diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm index b7ca291a5be46..bd9133ffce20f 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm @@ -297,6 +297,8 @@ /// track our timers and reagents /obj/item/organ/legion_skull/proc/skull_check() + if(!owner) + return if(!malignance) malignance = new() malignance.infect(owner, FALSE) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index b1788a7aa50d3..a05c2e65688eb 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -462,7 +462,7 @@ else client.perspective = EYE_PERSPECTIVE client.eye = loc - return 1 + return TRUE /// Show the mob's inventory to another mob /mob/proc/show_inv(mob/user) diff --git a/code/modules/modular_computers/file_system/programs/radar.dm b/code/modules/modular_computers/file_system/programs/radar.dm index d082503a012d1..06324b8f8b781 100644 --- a/code/modules/modular_computers/file_system/programs/radar.dm +++ b/code/modules/modular_computers/file_system/programs/radar.dm @@ -156,7 +156,7 @@ *something like "mob_209". In order to find the actual atom, we need *to search the appropriate list for the REF string. This is dependant *on the program (Lifeline uses GLOB.human_list, while Fission360 uses - *GLOB.poi_list), but the result will be the same; evaluate the string and + *SSpoints_of_interest.other_points_of_interest), but the result will be the same; evaluate the string and *return an atom reference. */ /datum/computer_file/program/radar/proc/find_atom() @@ -269,7 +269,7 @@ pointercolor = "red" /datum/computer_file/program/radar/fission360/find_atom() - return locate(selected) in GLOB.poi_list + return locate(selected) in SSpoints_of_interest.other_points_of_interest /datum/computer_file/program/radar/fission360/scan() if(world.time < next_scan) @@ -286,7 +286,7 @@ name = nuke.name, ) objects += list(nukeinfo) - var/obj/item/disk/nuclear/disk = locate() in GLOB.poi_list + var/obj/item/disk/nuclear/disk = locate() in SSpoints_of_interest.other_points_of_interest if(trackable(disk)) var/list/nukeinfo = list( ref = REF(disk), diff --git a/code/modules/overmap/helm.dm b/code/modules/overmap/helm.dm index 5b1f27fa2cb96..3b825ce395244 100644 --- a/code/modules/overmap/helm.dm +++ b/code/modules/overmap/helm.dm @@ -49,6 +49,8 @@ /obj/machinery/computer/helm/Initialize(mapload, obj/item/circuitboard/C) . = ..() + if(!viewer) + SSpoints_of_interest.make_point_of_interest(src) jump_allowed = world.time + CONFIG_GET(number/bluespace_jump_wait) ntnet_relay = new(src) @@ -76,6 +78,7 @@ SStgui.close_uis(src) ASSERT(length(concurrent_users) == 0) QDEL_NULL(ntnet_relay) + SSpoints_of_interest.remove_point_of_interest(src) if(current_ship) current_ship.helms -= src current_ship = null diff --git a/code/modules/overmap/ships/controlled_ship_datum.dm b/code/modules/overmap/ships/controlled_ship_datum.dm index 5d851e52f4fd3..efa4e36026c06 100644 --- a/code/modules/overmap/ships/controlled_ship_datum.dm +++ b/code/modules/overmap/ships/controlled_ship_datum.dm @@ -56,7 +56,7 @@ var/owner_check_timer_id /// The ship's join mode. Controls whether players can join freely, have to apply, or can't join at all. - var/join_mode = SHIP_JOIN_MODE_OPEN + var/join_mode = SHIP_JOIN_MODE_CLOSED /// Lazylist of /datum/ship_applications for this ship. Only used if join_mode == SHIP_JOIN_MODE_APPLY var/list/datum/ship_application/applications diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 9218b829e9407..499a88b161f1a 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -38,7 +38,7 @@ src.energy = starting_energy . = ..() START_PROCESSING(SSobj, src) - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) GLOB.singularities |= src for(var/obj/machinery/power/singularity_beacon/singubeacon in GLOB.machines) if(singubeacon.active) @@ -53,7 +53,7 @@ /obj/singularity/Destroy() STOP_PROCESSING(SSobj, src) - GLOB.poi_list.Remove(src) + SSpoints_of_interest.remove_point_of_interest(src) GLOB.singularities.Remove(src) return ..() diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 6ed294fa8936e..400366415d9a8 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -275,7 +275,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) SSair.start_processing_machine(src, mapload) countdown = new(src) countdown.start() - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) radio = new(src) radio.keyslot = new radio_key radio.listening = 0 @@ -293,7 +293,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) investigate_log("has been destroyed.", INVESTIGATE_SUPERMATTER) SSair.stop_processing_machine(src) QDEL_NULL(radio) - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) QDEL_NULL(countdown) if(is_main_engine && GLOB.main_supermatter_engine == src) GLOB.main_supermatter_engine = null diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index 7d58610fc7f72..d4a6f71cca4dc 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -151,7 +151,7 @@ /obj/singularity/energy_ball/orbit(obj/singularity/energy_ball/target) if (istype(target)) target.orbiting_balls += src - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) target.dissipate_strength = target.orbiting_balls.len . = ..() diff --git a/code/modules/projectiles/ammunition/ballistic/revolver.dm b/code/modules/projectiles/ammunition/ballistic/revolver.dm index e235e00b98f60..8705a932b392b 100644 --- a/code/modules/projectiles/ammunition/ballistic/revolver.dm +++ b/code/modules/projectiles/ammunition/ballistic/revolver.dm @@ -88,14 +88,14 @@ projectile_type = /obj/projectile/bullet/c38/dumdum /obj/item/ammo_casing/c38/hotshot - name = ".38 hot shot bullet casing" - desc = "A .38 hot shot bullet casing." + name = ".38 hearth bullet casing" + desc = "A .38 hearth bullet casing." bullet_skin = "incen" projectile_type = /obj/projectile/bullet/c38/hotshot /obj/item/ammo_casing/c38/iceblox - name = ".38 iceblox bullet casing" - desc = "A .38 iceblox bullet casing." + name = ".38 chilled bullet casing" + desc = "A .38 chilled bullet casing." bullet_skin = "surplus" projectile_type = /obj/projectile/bullet/c38/iceblox diff --git a/code/modules/projectiles/ammunition/ballistic/shotgun.dm b/code/modules/projectiles/ammunition/ballistic/shotgun.dm index 9f6a8c169ecdb..24854030c0413 100644 --- a/code/modules/projectiles/ammunition/ballistic/shotgun.dm +++ b/code/modules/projectiles/ammunition/ballistic/shotgun.dm @@ -46,6 +46,13 @@ icon_state = "incendiary" projectile_type = /obj/projectile/bullet/incendiary/shotgun +/obj/item/ammo_casing/shotgun/blank + name = "blank shell" + desc = "A shell packed with powder but no projectile." + icon_state = "blank" + projectile_type = /obj/projectile/bullet/pellet/blank + custom_materials = list(/datum/material/iron=250) + /obj/item/ammo_casing/shotgun/improvised name = "improvised shell" desc = "An extremely weak shotgun shell with multiple small pellets made out of metal shards." diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm index b590f0831df12..5b78f1fc93a15 100644 --- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm +++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm @@ -113,13 +113,13 @@ ammo_type = /obj/item/ammo_casing/c38/dumdum /obj/item/ammo_box/c38/hotshot - name = "speed loader (.38 hot shot)" - desc = "A 6-round speed loader for quickly reloading .38 special revolvers. These hot shot bullets contain an incendiary payload that set targets alight." + name = "speed loader (.38 hearth)" + desc = "A 6-round speed loader for quickly reloading .38 special revolvers. These hearthwine bullets contain an incendiary payload that set targets alight." ammo_type = /obj/item/ammo_casing/c38/hotshot /obj/item/ammo_box/c38/iceblox - name = "speed loader (.38 iceblox)" - desc = "A 6-round speed loader for quickly reloading .38 special revolvers. These iceblox bullets contain a cryogenic payload that chills targets." + name = "speed loader (.38 chilled)" + desc = "A 6-round speed loader for quickly reloading .38 special revolvers. These icewine bullets contain a cryogenic payload that chills targets." ammo_type = /obj/item/ammo_casing/c38/iceblox /obj/item/ammo_box/c38/empty @@ -213,6 +213,18 @@ icon_state = "38box-surplus" ammo_type = /obj/item/ammo_casing/c38/surplus +/obj/item/ammo_box/c38_box/hotshot + name = "ammo box (.38 hearth)" + desc = "An unorthodox .38 Special cartridge infused with hearthwine. Catches the target on fire." + icon_state = "38hotshot" + ammo_type = /obj/item/ammo_casing/c38/hotshot + +/obj/item/ammo_box/c38_box/iceblox + name = "ammo box (.38 chilled)" + desc = "An unorthodox .38 Special cartridge infused with icewine. Chills the target, slowing them down." + icon_state = "38iceblox" + ammo_type = /obj/item/ammo_casing/c38/iceblox + /obj/item/ammo_box/a12g name = "ammo box (12g buckshot)" desc = "A box of 12-gauge buckshot shells, devastating at close range." @@ -238,6 +250,12 @@ icon_state = "12gbox-rubbershot" ammo_type = /obj/item/ammo_casing/shotgun/rubbershot +/obj/item/ammo_box/a12g/blanks + name = "ammo box (12g blanks)" + desc = "A box of 12-gauge blank shells, designed for training." + icon_state ="12gbox-slug" + ammo_type = /obj/item/ammo_casing/shotgun/blank + /obj/item/ammo_box/c9mm name = "ammo box (9mm)" desc = "A box of standard 9mm ammo." diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index b59a1530a2095..28ef8cecdd805 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -207,6 +207,12 @@ ///this is how much deviation the gun recoil can have, recoil pushes the screen towards the reverse angle you shot + some deviation which this is the max. var/recoil_deviation = 22.5 + ///Used if the guns recoil is lower then the min, it clamps the highest recoil + var/min_recoil = 0 + + var/gunslinger_recoil_bonus = 0 + var/gunslinger_spread_bonus = 0 + /// how many shots per burst, Ex: most machine pistols, M90, some ARs are 3rnd burst, while others like the GAR and laser minigun are 2 round burst. var/burst_size = 3 ///The rate of fire when firing in a burst. Not the delay between bursts @@ -318,9 +324,6 @@ ///This prevents gun from firing until the coodown is done, affected by lag var/current_cooldown = 0 - var/gunslinger_recoil_bonus = 0 - var/gunslinger_spread_bonus = 0 - /obj/item/gun/Initialize() . = ..() RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) @@ -815,7 +818,7 @@ /obj/item/gun/proc/calculate_recoil(mob/user, recoil_bonus = 0) if(HAS_TRAIT(user, TRAIT_GUNSLINGER)) recoil_bonus += gunslinger_recoil_bonus - return clamp(recoil_bonus, 0 , INFINITY) + return clamp(recoil_bonus, min_recoil , INFINITY) /obj/item/gun/proc/calculate_spread(mob/user, bonus_spread) var/final_spread = 0 diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 0288813fd0895..00f48cc29239c 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -13,6 +13,8 @@ has_safety = TRUE safety = TRUE + min_recoil = 0.1 + valid_attachments = list( /obj/item/attachment/silencer, /obj/item/attachment/laser_sight, diff --git a/code/modules/projectiles/guns/ballistic/rifle.dm b/code/modules/projectiles/guns/ballistic/rifle.dm index 2d3cb6908c83a..2be77ee208354 100644 --- a/code/modules/projectiles/guns/ballistic/rifle.dm +++ b/code/modules/projectiles/guns/ballistic/rifle.dm @@ -127,6 +127,8 @@ sawn_off = TRUE weapon_weight = WEAPON_MEDIUM w_class = WEIGHT_CLASS_NORMAL + spread = 24 + spread_unwielded = 30 slot_flags = ITEM_SLOT_BELT /obj/item/gun/ballistic/rifle/solgov diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index eb8ea3355fe9d..2d70bf9851bb2 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -432,6 +432,14 @@ EMPTY_GUN_HELPER(shotgun/automatic/bulldog/inteq) sawn_off = TRUE slot_flags = ITEM_SLOT_BELT + wield_slowdown = 0.25 + wield_delay = 0.3 SECONDS //OP? maybe + + spread = 8 + spread_unwielded = 15 + recoil = 3 //or not + recoil_unwielded = 5 + /obj/item/gun/ballistic/shotgun/automatic/combat/compact/compact name = "compact compact combat shotgun" desc = "A compact version of the compact version of the semi automatic combat shotgun. For when you want a gun the same size as your brain." diff --git a/code/modules/projectiles/guns/energy/pulse.dm b/code/modules/projectiles/guns/energy/pulse.dm index c2e5b4cb29330..40fd10e947856 100644 --- a/code/modules/projectiles/guns/energy/pulse.dm +++ b/code/modules/projectiles/guns/energy/pulse.dm @@ -46,7 +46,7 @@ /obj/item/gun/energy/pulse/prize/Initialize() . = ..() - GLOB.poi_list += src + SSpoints_of_interest.make_point_of_interest(src) var/turf/T = get_turf(src) message_admins("A pulse rifle prize has been created at [ADMIN_VERBOSEJMP(T)]") @@ -55,7 +55,7 @@ notify_ghosts("Someone won a pulse rifle as a prize!", source = src, action = NOTIFY_ORBIT, header = "Pulse rifle prize") /obj/item/gun/energy/pulse/prize/Destroy() - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) . = ..() /obj/item/gun/energy/pulse/pistol diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm index dede2ce0d7ce5..340aa692f5b24 100644 --- a/code/modules/projectiles/projectile/bullets/revolver.dm +++ b/code/modules/projectiles/projectile/bullets/revolver.dm @@ -69,7 +69,7 @@ imp.implant(M) /obj/projectile/bullet/c38/hotshot //similar to incendiary bullets, but do not leave a flaming trail - name = ".38 hot shot bullet" + name = ".38 hearth bullet" ricochets_max = 0 /obj/projectile/bullet/c38/hotshot/on_hit(atom/target, blocked = FALSE) @@ -80,7 +80,7 @@ M.IgniteMob() /obj/projectile/bullet/c38/iceblox //see /obj/projectile/temp for the original code - name = ".38 iceblox bullet" + name = ".38 chilled bullet" var/temperature = 100 ricochets_max = 0 diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm index ba9c8c88d7f8f..a069102a39cc3 100644 --- a/code/modules/projectiles/projectile/bullets/shotgun.dm +++ b/code/modules/projectiles/projectile/bullets/shotgun.dm @@ -114,3 +114,9 @@ damage = 30 armour_penetration = -25 tile_dropoff = 3 + +/obj/projectile/bullet/pellet/blank + name = "blank" + damage = 30 + range = 2 + armour_penetration = -70 diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 79b28ccef3312..340119a4e78a0 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -97,18 +97,25 @@ other types of metals and chemistry for reagents). color = "#8b70ff" illustration = "design" custom_materials = list(/datum/material/iron =300, /datum/material/glass =100) + var/disk_name = "Design Disk" + var/design_name var/list/blueprints = list() - var/list/starting_blueprints = list() + var/starting_blueprints = list() var/max_blueprints = 1 /obj/item/disk/design_disk/Initialize() . = ..() pixel_x = base_pixel_x + rand(-5, 5) pixel_y = base_pixel_y + rand(-5, 5) - blueprints = new/list(max_blueprints) + if(design_name) + name = jointext(list(disk_name, design_name), " - ") + if(length(starting_blueprints)) + for(var/design in starting_blueprints) + blueprints += new design() /obj/item/disk/design_disk/adv name = "Advanced Component Design Disk" + disk_name = "Advanced Design Disk" color = "#bed876" desc = "A disk for storing device design data for construction in lathes. This one has a little bit of extra storage space." custom_materials = list(/datum/material/iron =300, /datum/material/glass = 100, /datum/material/silver = 50) @@ -116,6 +123,7 @@ other types of metals and chemistry for reagents). /obj/item/disk/design_disk/super name = "Super Component Design Disk" + disk_name = "Super Design Disk" color = "#c25454" desc = "A disk for storing device design data for construction in lathes. This one has more extra storage space." custom_materials = list(/datum/material/iron =300, /datum/material/glass = 100, /datum/material/silver = 50, /datum/material/gold = 50) @@ -123,6 +131,7 @@ other types of metals and chemistry for reagents). /obj/item/disk/design_disk/elite name = "Elite Component Design Disk" + disk_name = "Elite Design Disk" color = "#333333" desc = "A disk for storing device design data for construction in lathes. This one has absurd amounts of extra storage space." custom_materials = list(/datum/material/iron =300, /datum/material/glass = 100, /datum/material/silver = 100, /datum/material/gold = 100, /datum/material/bluespace = 50) @@ -130,39 +139,60 @@ other types of metals and chemistry for reagents). //Disks with content /obj/item/disk/design_disk/ammo_c10mm - name = "Design Disk - 10mm Ammo" + design_name = "10mm Ammo" desc = "A design disk containing the pattern for a refill box of standard 10mm ammo, used in Stechkin pistols." - -/obj/item/disk/design_disk/ammo_c10mm/Initialize() - . = ..() - blueprints[1] = new /datum/design/c10mm() - + starting_blueprints = (/datum/design/c10mm) /obj/item/disk/design_disk/disposable_gun - name = "design disk - disposable gun" + design_name = "Disposable gun" desc = "A design disk containing designs for a cheap and disposable gun." illustration = "gun" max_blueprints = 2 - -/obj/item/disk/design_disk/disposable_gun/Initialize() - . = ..() - blueprints[1] = new /datum/design/disposable_gun() + starting_blueprints = list(/datum/design/disposable_gun) /obj/item/disk/design_disk/clip_mechs - name = "design disk - CLIP exosuit modifications" + design_name = "CLIP exosuit modifications" desc = "A design disk containing specifications for CLIP-custom exosuit conversions." color = "#57b8f0" max_blueprints = 2 - -/obj/item/disk/design_disk/clip_mechs/Initialize() - . = ..() - blueprints[1] = new /datum/design/clip_ripley_upgrade() - blueprints[2] = new /datum/design/clip_durand_upgrade() + starting_blueprints = list(/datum/design/clip_ripley_upgrade, /datum/design/clip_durand_upgrade) /obj/item/disk/design_disk/ammo_c9mm - name = "Design Disk - 9mm Ammo" + design_name = "9mm Ammo" desc = "A design disk containing the pattern for a refill box of standard 9mm ammo, used in Commander pistols." - -/obj/item/disk/design_disk/ammo_c9mm/Initialize() - . = ..() - blueprints[1] = new /datum/design/c9mmautolathe() + starting_blueprints = list(/datum/design/c9mmautolathe) + +/obj/item/disk/design_disk/blanks + design_name = "Blank Ammo" + starting_blueprints = list(/datum/design/blank_shell) + + +/obj/item/disk/design_disk/ammo_1911 + design_name = "1911 Magazine" + desc = "A design disk containing the pattern for the classic 1911's seven round .45ACP magazine." + illustration = "ammo" + starting_blueprints = list(/datum/design/colt_1911_magazine) + +//KA modkit design discs +/obj/item/disk/design_disk/modkit_disc + design_name = "KA Mod" + desc = "A design disc containing the design for a unique kinetic accelerator modkit. It's compatible with a research console." + illustration = "accel" + color = "#6F6F6F" + starting_blueprints = list(/datum/design/unique_modkit) + +/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe + design_name = "Offensive Mining Explosion Mod" + starting_blueprints = list(/datum/design/unique_modkit/offensive_turf_aoe) + +/obj/item/disk/design_disk/modkit_disc/rapid_repeater + design_name = "Rapid Repeater Mod" + starting_blueprints = list(/datum/design/unique_modkit/rapid_repeater) + +/obj/item/disk/design_disk/modkit_disc/resonator_blast + design_name = "Resonator Blast Mod" + starting_blueprints = list(/datum/design/unique_modkit/resonator_blast) + +/obj/item/disk/design_disk/modkit_disc/bounty + design_name = "Death Syphon Mod" + starting_blueprints = list(/datum/design/unique_modkit/bounty) diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index d1fe330249195..0b679dfcc4bf3 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -796,6 +796,14 @@ build_path = /obj/item/ammo_casing/shotgun/beanbag category = list("initial", "Security", "Ammo") +/datum/design/blank_shell + name = "Shotgun Blank" + id = "blank_shell" + build_type = AUTOLATHE | PROTOLATHE + materials = list(/datum/material/iron = 2000) + build_path = /obj/item/ammo_casing/shotgun/blank + category = list("Security", "Ammo") + /datum/design/riot_dart name = "Foam Riot Dart" id = "riot_dart" diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 2a8f390e9e368..1c3edc8b7c327 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -18,7 +18,7 @@ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_BALLISTICS /datum/design/c38_hotshot - name = "Speed Loader (.38 Hot Shot)" + name = "Speed Loader (.38 Hearth)" desc = "Designed to quickly reload revolvers. Hot Shot bullets contain an incendiary payload." id = "c38_hotshot" build_type = PROTOLATHE @@ -28,7 +28,7 @@ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_BALLISTICS /datum/design/c38_iceblox - name = "Speed Loader (.38 Iceblox)" + name = "Speed Loader (.38 Chilled)" desc = "Designed to quickly reload revolvers. Iceblox bullets contain a cryogenic payload." id = "c38_iceblox" build_type = PROTOLATHE diff --git a/code/modules/ruins/spaceruin_code/bigderelict1.dm b/code/modules/ruins/spaceruin_code/bigderelict1.dm index 99af3b9efa283..9e2a0957547b8 100644 --- a/code/modules/ruins/spaceruin_code/bigderelict1.dm +++ b/code/modules/ruins/spaceruin_code/bigderelict1.dm @@ -6,13 +6,3 @@ /obj/item/paper/crumpled/ruins/bigderelict1/coward icon_state = "scrap_bloodied" default_raw_text = "If anyone finds this, please, don't let my kids know I died a coward.." - -/obj/item/disk/design_disk/ammo_1911 - name = "design disk - 1911 magazine" - desc = "A design disk containing the pattern for the classic 1911's seven round .45ACP magazine." - illustration = "ammo" - -/obj/item/disk/design_disk/ammo_1911/Initialize() - . = ..() - var/datum/design/colt_1911_magazine/M = new - blueprints[1] = M diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm index 720670e3fc218..38e2f0df145ea 100644 --- a/code/modules/spells/spell_types/lichdom.dm +++ b/code/modules/spells/spell_types/lichdom.dm @@ -99,7 +99,7 @@ name = "phylactery of [mind.name]" active_phylacteries++ - GLOB.poi_list |= src + SSpoints_of_interest.make_point_of_interest(src) START_PROCESSING(SSobj, src) if(initial(SSticker.mode.round_ends_with_antag_death)) SSticker.mode.round_ends_with_antag_death = FALSE @@ -107,7 +107,7 @@ /obj/item/phylactery/Destroy(force=FALSE) STOP_PROCESSING(SSobj, src) active_phylacteries-- - GLOB.poi_list -= src + SSpoints_of_interest.remove_point_of_interest(src) if(!active_phylacteries) SSticker.mode.round_ends_with_antag_death = initial(SSticker.mode.round_ends_with_antag_death) . = ..() diff --git a/html/changelogs/archive/2024-09.yml b/html/changelogs/archive/2024-09.yml index 130805ee50eb4..d5ef254581961 100644 --- a/html/changelogs/archive/2024-09.yml +++ b/html/changelogs/archive/2024-09.yml @@ -163,3 +163,44 @@ - bugfix: miso soup spelling error zimon9: - rscadd: Adds a bit more contrast to the output of health analyzers +2024-09-25: + Jedi-Toothpaste: + - bugfix: Added windows to the mudskipper and shetland's engines. + - bugfix: Adjusted the blast doors which open on the Shetland's engines. + SomeguyManperson: + - bugfix: sawn off illestren/improvised shotgun stats are now consistent if they + are spawned in +2024-09-26: + FalloutFalcon: + - rscadd: Added new blank shells for training drills! + - refactor: Minor refactor of design disks to reduce repeated code + - rscadd: Ballistics now have a minimum recoil, not enough to mess up your shot! + - bugfix: ships now start closed. shiptesters be writing there memos and ship names. + - rscadd: You can now see ships in the orbit menu and its alot prettier! + - code_imp: ported tg points of interest and a much improved orbit menu + Gristlebee: + - bugfix: fixes wall deconstruction causing runtimes + Jedi-Toothpaste: + - bugfix: Fixed the lack of windows for the Kilo's Thrusters, and fixed the broken + link for the new blast doors. + generalthrax: + - balance: Most common accessories now fit on pants + - rscadd: Exosuit Recharger machines are now available from cargo + - balance: Rust Reds on the blackmarket are now available to a maximum of 3 + zimon9: + - rscadd: Added fruit puree to vegan rations + - rscdel: Removed pizza crackers from vegan rations +2024-09-27: + Jedi-Toothpaste: + - rscadd: Firelocks to the Valor-Class' Doors + - rscadd: Lighting to dark areas on the Valor-Class' Doors + - rscadd: New areas on the Valor-Class to seperate rooms + - rscadd: Added APC for the Surgical Area + PositiveEntropy: + - imageadd: Adjusts the inner part of the normal rabbit ears. +2024-09-28: + Sadhorizon: + - rscadd: Added a fax machine to the Dwayne-class. + SomeguyManperson: + - bugfix: legion skulls will no longer check if they should rise up and consume + their owner if they are ownerless diff --git a/icons/mob/species/human/rabbit.dmi b/icons/mob/species/human/rabbit.dmi index fcc6599f735685713dabb3bf310c4d1e26339c1e..26f0cb080d22653f3ac9a61223c4a9c877225522 100644 GIT binary patch delta 745 zcmV$i?pxq@o`qVe&}9 zM}2~p?T02UmuD4G9oxaazD_G&?%+ycM|~!3t7t*0WGBkmE2e+@uDl_Ajn^ZkNh`id zEnh?HUh%Bj>rK@G0000000919;yvs{cn+*}N0~3$&J{7{y9+)B%kX->$Nc!MWvpk) zyi0C%U|1QPqUwUyueCYR&r#vpMN}yI`8Kn&x2uG82|tPID(_nl1KQ=>m4{O^Lm8O zX5WGO=&7hO2X|2wQ^tm(nH2xzf_8c`5puKbv4R>28vp2B9n!Jow$-00000NkvXXu0mjfHg8{w delta 758 zcmVl{`oHxo*4LYw0{{R30002|zpS^g6A>7&wZF=F`%C5Tc}(?1LHlSS((1GEnBbWA zm@LEVg%P3||WskQYKJjSIe!epktn96mhRb=b8EoA=*+n`G@ChbVy)a3dAWsj2A93F?M)vv96G;oXGSt_y$p(4mq&w63%_srAA(Kr-~b z@67#vj3592000000Dyz2CSM1TPrml&dFGEZVgLa6Ma*npFNAk}K-|HM-?;yX_zt~T zA1bz$ac?<9GTZ1MqS{!lK5j(;0002|4Kk7^E}eRL;o6ho5=oS#CVl}X@$$ku5(Gms zZZ$FS3)p|)WUvO&xitiS0KyA~egT}{!%qZ#|1YzGBK3?e2^y1l!S;w=8J#VJX^FlE zL1_~IgpXj2YIG+N)(PH*$Fwk8UYD>29bA0}Z1+xv=RT7gVCpsZtDv$CbuKWyU}4+D zf^QwTHvZG6EaNJZh|VA7>5~%v_ovycLdA$RNMP3i^(d;`=AH5V+=HMZ!VvN{O6bbQ9E@;O$GcLYUAqn+3#C*8yiMHA9 o8dGkzJyuX7U;_XE003$D2SExfS^H-GdjJ3c07*qoM6N<$f*}lQQUCw| diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index 403b198c179bcfddd76bc5ec6100a098244fa217..ec5f147485401833d8ad24fb12c0cf6a26dc9a09 100644 GIT binary patch literal 59485 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�|5v&&(+6#QTH|7xXxCio~B9FI+ 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

)AGle|iV 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 diff --git a/icons/obj/ammo_shotshells.dmi b/icons/obj/ammo_shotshells.dmi index fe37023686bdb306d3b9d05aceb053a4352be841..55b00cdd0b21797c4f752dd63dc42530a6d6b336 100644 GIT binary patch literal 3149 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 diff --git a/shiptest.dme b/shiptest.dme index 88900c60e222e..e460d129f655a 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -370,6 +370,7 @@ #include "code\controllers\subsystem\persistence.dm" #include "code\controllers\subsystem\physics.dm" #include "code\controllers\subsystem\ping.dm" +#include "code\controllers\subsystem\points_of_interest.dm" #include "code\controllers\subsystem\profiler.dm" #include "code\controllers\subsystem\radiation.dm" #include "code\controllers\subsystem\radio.dm" @@ -672,6 +673,7 @@ #include "code\datums\elements\lazy_fishing_spot.dm" #include "code\datums\elements\light_blocking.dm" #include "code\datums\elements\mobappearance.dm" +#include "code\datums\elements\point_of_interest.dm" #include "code\datums\elements\plant_backfire.dm" #include "code\datums\elements\renamemob.dm" #include "code\datums\elements\selfknockback.dm" @@ -857,6 +859,7 @@ #include "code\game\area\areas\ruins\space.dm" #include "code\game\area\areas\ruins\templates.dm" #include "code\game\area\areas\ruins\wasteplanet.dm" +#include "code\game\atom\atom_orbit.dm" #include "code\game\gamemodes\events.dm" #include "code\game\gamemodes\game_mode.dm" #include "code\game\gamemodes\objective.dm" diff --git a/tgui/packages/tgui/interfaces/Orbit.js b/tgui/packages/tgui/interfaces/Orbit.js deleted file mode 100644 index 91bf9d1f79297..0000000000000 --- a/tgui/packages/tgui/interfaces/Orbit.js +++ /dev/null @@ -1,218 +0,0 @@ -import { createSearch } from 'common/string'; -import { multiline } from 'common/string'; -import { resolveAsset } from '../assets'; -import { useBackend, useLocalState } from '../backend'; -import { - Box, - Button, - Divider, - Flex, - Icon, - Input, - Section, -} from '../components'; -import { Window } from '../layouts'; - -const PATTERN_NUMBER = / \(([0-9]+)\)$/; - -const searchFor = (searchText) => - createSearch(searchText, (thing) => thing.name); - -const compareString = (a, b) => (a < b ? -1 : a > b); - -const compareNumberedText = (a, b) => { - const aName = a.name; - const bName = b.name; - - // Check if aName and bName are the same except for a number at the end - // e.g. Medibot (2) and Medibot (3) - const aNumberMatch = aName.match(PATTERN_NUMBER); - const bNumberMatch = bName.match(PATTERN_NUMBER); - - if ( - aNumberMatch && - bNumberMatch && - aName.replace(PATTERN_NUMBER, '') === bName.replace(PATTERN_NUMBER, '') - ) { - const aNumber = parseInt(aNumberMatch[1], 10); - const bNumber = parseInt(bNumberMatch[1], 10); - - return aNumber - bNumber; - } - - return compareString(aName, bName); -}; - -const BasicSection = (props, context) => { - const { act } = useBackend(context); - const { searchText, source, title } = props; - const things = source.filter(searchFor(searchText)); - things.sort(compareNumberedText); - return ( - source.length > 0 && ( -

- {things.map((thing) => ( -
- ) - ); -}; - -const OrbitedButton = (props, context) => { - const { act } = useBackend(context); - const { color, thing } = props; - - return ( - - ); -}; - -export const Orbit = (props, context) => { - const { act, data } = useBackend(context); - const { alive, antagonists, auto_observe, dead, ghosts, misc, npcs } = data; - - const [searchText, setSearchText] = useLocalState(context, 'searchText', ''); - - const collatedAntagonists = {}; - for (const antagonist of antagonists) { - if (collatedAntagonists[antagonist.antag] === undefined) { - collatedAntagonists[antagonist.antag] = []; - } - collatedAntagonists[antagonist.antag].push(antagonist); - } - - const sortedAntagonists = Object.entries(collatedAntagonists); - sortedAntagonists.sort((a, b) => { - return compareString(a[0], b[0]); - }); - - const orbitMostRelevant = (searchText) => { - for (const source of [ - sortedAntagonists.map(([_, antags]) => antags), - alive, - ghosts, - dead, - npcs, - misc, - ]) { - const member = source - .filter(searchFor(searchText)) - .sort(compareNumberedText)[0]; - if (member !== undefined) { - act('orbit', { ref: member.ref }); - break; - } - } - }; - - return ( - - -
- - - - - - setSearchText(value)} - onEnter={(_, value) => orbitMostRelevant(value)} - /> - - - - - -
- {antagonists.length > 0 && ( -
- {sortedAntagonists.map(([name, antags]) => ( -
- {antags - .filter(searchFor(searchText)) - .sort(compareNumberedText) - .map((antag) => ( - - ))} -
- ))} -
- )} - -
- {alive - .filter(searchFor(searchText)) - .sort(compareNumberedText) - .map((thing) => ( - - ))} -
- -
- {ghosts - .filter(searchFor(searchText)) - .sort(compareNumberedText) - .map((thing) => ( - - ))} -
- - - - - - -
-
- ); -}; diff --git a/tgui/packages/tgui/interfaces/Orbit/OrbitContent.tsx b/tgui/packages/tgui/interfaces/Orbit/OrbitContent.tsx new file mode 100644 index 0000000000000..f3c59a75e1897 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Orbit/OrbitContent.tsx @@ -0,0 +1,98 @@ +import { toTitleCase } from 'common/string'; + +import { useBackend } from '../../backend'; +import { NoticeBox, Section, Stack, Table, Tooltip } from '../../components'; + +import { getAntagCategories } from './helpers'; +import { AntagGroup, Observable, OrbitData } from './types'; +import { OrbitSection } from './OrbitSection'; + +type ContentSection = { + content: Observable[]; + title: string; + color?: string; +}; + +export const OrbitContent = (props, context) => { + const { act, data } = useBackend(context); + const { antagonists = [], critical = [] } = data; + const { searchText, autoObserve } = props; + + let antagGroups: AntagGroup[] = []; + if (antagonists.length) { + antagGroups = getAntagCategories(antagonists); + } + + const sections: readonly ContentSection[] = [ + { + content: data.alive, + title: 'Alive', + color: 'good', + }, + { + content: data.dead, + title: 'Dead', + }, + { + content: data.ghosts, + title: 'Ghosts', + }, + { + content: data.misc, + title: 'Misc', + }, + { + content: data.npcs, + title: 'NPCs', + }, + { + content: data.ships, + title: 'Ships', + }, + ]; + + return ( +
+ + {critical.map((crit) => ( + + act('orbit', { ref: crit.ref })} + > + + + {toTitleCase(crit.full_name)} + {crit.extra} + +
+
+
+ ))} + + {antagGroups.map(([title, members]) => ( + + ))} + + {sections.map((section) => ( + + ))} +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/Orbit/OrbitItem.tsx b/tgui/packages/tgui/interfaces/Orbit/OrbitItem.tsx new file mode 100644 index 0000000000000..957104afa8b91 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Orbit/OrbitItem.tsx @@ -0,0 +1,50 @@ +import { useBackend } from '../../backend'; +import { Stack, Button, Flex, Icon } from '../../components'; + +import { capitalizeFirst } from 'common/string'; + +import { getDisplayColor, getDisplayName } from './helpers'; +import { Antagonist, Observable, OrbitData } from './types'; + +type Props = { + item: Observable | Antagonist; + autoObserve: boolean; + color: string | undefined; +}; + +export const OrbitItem = (props: Props, context) => { + const { item, autoObserve, color } = props; + const { full_name, icon, job, name, orbiters, ref } = item; + + const { act, data } = useBackend(context); + const { orbiting } = data; + + const selected = ref === orbiting?.ref; + const validIcon = !!job && !!icon && icon !== 'hudunknown'; + + return ( + act('orbit', { auto_observe: autoObserve, ref })} + style={{ + display: 'flex', + }} + > + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/Orbit/OrbitSection.tsx b/tgui/packages/tgui/interfaces/Orbit/OrbitSection.tsx new file mode 100644 index 0000000000000..d27d9080e08dc --- /dev/null +++ b/tgui/packages/tgui/interfaces/Orbit/OrbitSection.tsx @@ -0,0 +1,65 @@ +import { Collapsible, Flex, Tooltip } from '../../components'; +import { isJobOrNameMatch } from './helpers'; +import { OrbitItem } from './OrbitItem'; +import { OrbitTooltip } from './OrbitTooltip'; +import { Observable } from './types'; + +type Props = { + color?: string; + section: Observable[]; + title: string; + searchQuery: string; + autoObserve: boolean; +}; + +/** + * Displays a collapsible with a map of observable items. + * Filters the results if there is a provided search query. + */ +export const OrbitSection = (props: Props) => { + const { color, section = [], title, searchQuery, autoObserve } = props; + + const filteredSection = section.filter((observable) => + isJobOrNameMatch(observable, searchQuery) + ); + + if (!filteredSection.length) { + return null; + } + + return ( + + + {filteredSection.map((item) => { + const content = ( + + ); + + if (!item.health && !item.extra) { + return content; + } + + return ( + } + key={item.ref} + position="bottom-start" + > + {content} + + ); + })} + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/Orbit/OrbitTooltip.tsx b/tgui/packages/tgui/interfaces/Orbit/OrbitTooltip.tsx new file mode 100644 index 0000000000000..0a941dcb0fb5f --- /dev/null +++ b/tgui/packages/tgui/interfaces/Orbit/OrbitTooltip.tsx @@ -0,0 +1,57 @@ +import { LabeledList, NoticeBox } from '../../components'; +import { Antagonist, Observable } from './types'; + +type Props = { + item: Observable | Antagonist; +}; + +/** Displays some info on the mob as a tooltip. */ +export const OrbitTooltip = (props: Props) => { + const { item } = props; + const { extra, name, full_name, health, job } = item; + + let antag; + if ('antag' in item) { + antag = item.antag; + } + + const extraInfo = extra?.split(':'); + const displayHealth = !!health && health >= 0 ? `${health}%` : 'Critical'; + const showAFK = 'client' in item && !item.client; + + return ( + <> + + Last Known Data + + + {extraInfo ? ( + + {extraInfo[1]} + + ) : ( + <> + {!!name && ( + {name} + )} + {!!full_name && ( + + {full_name} + + )} + {!!job && {job}} + {!!antag && ( + {antag} + )} + {!!health && ( + + {displayHealth} + + )} + + )} + {showAFK && Away} + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/Orbit/constants.ts b/tgui/packages/tgui/interfaces/Orbit/constants.ts new file mode 100644 index 0000000000000..1edadc9bfe45d --- /dev/null +++ b/tgui/packages/tgui/interfaces/Orbit/constants.ts @@ -0,0 +1,8 @@ +export const HEALTH = { + Good: 69, // nice + Average: 19, + Bad: 0, + Crit: -30, + Dead: -100, + Ruined: -200, +} as const; diff --git a/tgui/packages/tgui/interfaces/Orbit/helpers.ts b/tgui/packages/tgui/interfaces/Orbit/helpers.ts new file mode 100644 index 0000000000000..7046f784cd6cd --- /dev/null +++ b/tgui/packages/tgui/interfaces/Orbit/helpers.ts @@ -0,0 +1,119 @@ +import { createSearch } from '../../../common/string'; + +import { HEALTH } from './constants'; +import { AntagGroup, Antagonist, Observable } from './types'; + +const PATTERN_NUMBER = / \(([0-9]+)\)$/; + +/** Return a map of strings with each antag in its antag_category */ +export const getAntagCategories = (antagonists: Antagonist[]): AntagGroup[] => { + const categories = new Map(); + + for (const player of antagonists) { + const { antag_group } = player; + + if (!categories.has(antag_group)) { + categories.set(antag_group, []); + } + categories.get(antag_group)!.push(player); + } + + const sorted = Array.from(categories.entries()).sort((a, b) => { + const lowerA = a[0].toLowerCase(); + const lowerB = b[0].toLowerCase(); + + if (lowerA < lowerB) return -1; + if (lowerA > lowerB) return 1; + return 0; + }); + + return sorted; +}; + +/** Returns a disguised name in case the person is wearing someone else's ID */ +export const getDisplayName = ( + full_name: string, + nickname?: string +): string => { + if (!nickname) { + return full_name; + } + + return nickname; +}; + +/** Displays color for buttons based on the health or orbiter count. */ +export const getDisplayColor = ( + item: Observable, + override?: string +): string => { + const { job, health, orbiters } = item; + + // Things like blob camera, etc + if (typeof health !== 'number') { + return override ? 'good' : 'grey'; + } + + // Players that are AFK + if ('client' in item && !item.client) { + return 'grey'; + } + + return getHealthColor(health); +}; + +/** Returns the display color for certain health percentages */ +const getHealthColor = (health: number): string => { + switch (true) { + case health > HEALTH.Good: + return 'good'; + case health > HEALTH.Average: + return 'average'; + default: + return 'bad'; + } +}; + +/** Checks if a full name or job title matches the search. */ +export const isJobOrNameMatch = ( + observable: Observable, + searchQuery: string +): boolean => { + if (!searchQuery) return true; + + const { full_name, job } = observable; + + return ( + full_name?.toLowerCase().includes(searchQuery?.toLowerCase()) || + job?.toLowerCase().includes(searchQuery?.toLowerCase()) || + false + ); +}; + +export const searchFor = (searchText) => + createSearch(searchText, (thing: Observable) => thing.full_name); + +export const compareString = (a, b) => (a < b ? -1 : a > b); + +export const compareNumberedText = (a, b) => { + const aName = a.name; + const bName = b.name; + + // Check if aName and bName are the same except for a number at the end + // e.g. Medibot (2) and Medibot (3) + const aNumberMatch = aName.match(PATTERN_NUMBER); + const bNumberMatch = bName.match(PATTERN_NUMBER); + + if ( + aNumberMatch && + bNumberMatch && + aName.replace(PATTERN_NUMBER, '') === bName.replace(PATTERN_NUMBER, '') + ) { + const aNumber = parseInt(aNumberMatch[1], 10); + const bNumber = parseInt(bNumberMatch[1], 10); + + return aNumber - bNumber; + } + + return compareString(aName, bName); +}; diff --git a/tgui/packages/tgui/interfaces/Orbit/index.tsx b/tgui/packages/tgui/interfaces/Orbit/index.tsx new file mode 100644 index 0000000000000..f0854f7bfa690 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Orbit/index.tsx @@ -0,0 +1,86 @@ +import { multiline } from '../../../common/string'; +import { useBackend, useLocalState } from '../../backend'; +import { Button, Divider, Flex, Icon, Input, Section } from '../../components'; +import { Window } from '../../layouts'; + +import { searchFor } from './helpers'; +import { OrbitData } from './types'; +import { OrbitContent } from './OrbitContent'; + +export const Orbit = (props, context) => { + const { act, data } = useBackend(context); + + const [searchText, setSearchText] = useLocalState(context, 'searchText', ''); + const [autoObserve, setAutoObserve] = useLocalState( + context, + 'autoObserve', + false + ); + + const orbitMostRelevant = () => { + const mostRelevant = [ + data.antagonists, + data.alive, + data.ghosts, + data.dead, + data.npcs, + data.misc, + data.ships, + ] + .flat() + .filter(searchFor(searchText)) + .sort()[0]; + + if (mostRelevant !== undefined) { + act('orbit', { ref: mostRelevant.ref }); + } + }; + + return ( + + +
+ + + + + + setSearchText(value)} + onEnter={(_, value) => orbitMostRelevant()} + /> + + + + + +
+ +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/Orbit/types.ts b/tgui/packages/tgui/interfaces/Orbit/types.ts new file mode 100644 index 0000000000000..4912ae10db4c6 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Orbit/types.ts @@ -0,0 +1,38 @@ +import { BooleanLike } from '../../../common/react'; + +export type Antagonist = Observable & { antag: string; antag_group: string }; + +export type AntagGroup = [string, Antagonist[]]; + +export type OrbitData = { + alive: Observable[]; + antagonists: Antagonist[]; + critical: Critical[]; + dead: Observable[]; + ghosts: Observable[]; + misc: Observable[]; + npcs: Observable[]; + ships: Observable[]; + orbiting: Observable | null; + autoObserve: boolean; +}; + +export type Observable = { + full_name: string; + ref: string; + // Optionals +} & Partial<{ + client: BooleanLike; + extra: string; + health: number; + icon: string; + job: string; + name: string; + orbiters: number; +}>; + +type Critical = { + extra: string; + full_name: string; + ref: string; +};