From 0bd4b0820f63355bc942b5efdac2557b9f1d4587 Mon Sep 17 00:00:00 2001 From: EnterTheJake <102721711+EnterTheJake@users.noreply.github.com> Date: Tue, 9 Jun 2026 16:38:00 +0200 Subject: [PATCH] Adds TGMC Tactical maps to the game and to Nuclear Operatives! (#96068) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## About The Pull Request Brought to you by Team Powercrèpe.(same group of people that delivered the Heretic Overhaul) This PR ports the TGMC Tacmaps and grants em to our NukeOps. Code by Me, @Xander3359, @Arturlang, @Absolucy. Mapping by @RipGrayson Sprites by @KillerOrcaCora Writing bits by @necromanceranne Tacmaps are essentially dynamically generated minimaps, Tac map examples Tac-Maps Icons As you can see from the screenshots above, departments are classified by color, hovering your cursor over an area or a team mate, will display their name, the system does allow the user to switch between Multi-Z, and lastly you can draw and add labels to the map, although the last option is only available to the NukeOps Leader and OW agents. The functionality is tied to the Syndicate implants nukies start with, Cayenne, Syndie borgs and Mechs also have the ability to toggle the map. Likewise, the tacmaps will display the positioning of the following in real time! - Nuke ops agents - Syndie borgs and Mechs - Cayenne - Location of the nuclear fission device (and beer nuke) - Location of the Nuclear Authentication Disk. SkyBridge OFF SkyBridge ON Holo table done https://github.com/user-attachments/assets/caf38538-ef04-4330-992c-3137a67ea0d0 Lastly The tactiical map implant cannot be be used on the nuke ops base,If the team wishes to interact with the map they'll have to Interact with the "Reconnaisance Platform" (Sprite by Orcacora) in the briefing room, which has seen some mapping changes (Brought to you by TheLastGrayson). ## Why It's Good For The Game Originally this feature was planned for the Upcoming Contractor Rework our team is currently working on, but given the massive size of it all, we decided to atomize it. But without that consideration in mind, I think it makes sense for Nuclear operatives of all antagonists to have the means to Recon and plot an assault plan onto the station and actually be able to know the whereabouts of their teammates. Obviously this feature has a lot of other potential applications, we have wanted to have functional Maps for a very long time, if someone wants to give it a go once the feature is merged, by all means. ## Changelog :cl: add: Tactical Maps have been added to the game! add: Nuclear Operatives implants now grant the ability to open a Minimap, this map will display and show the names of various areas of the station, and the positioning of the Nukeops team,borgs,mechs,Cayenne and the nuke disk in real time! add: Nukie leaders and OW agents can also draw and apply labels to the map. add: the "Recoinassance Platform" has been added to the Nukie Base, it allows displaying of the Tactical maps while on the Syndicate Base Z level. map: The briefing room in the NukeOps base has been remapped to better accomodate the new Holographic table. map: Changed the front shutters on the Syndicate Infiltrator to the more fitting Syndicate Shutters. /:cl: --------- Co-authored-by: Xander3359 <66163761+Xander3359@users.noreply.github.com> Co-authored-by: Artur Lang <24881678+Arturlang@users.noreply.github.com> Co-authored-by: Lucy Co-authored-by: Copilot Co-authored-by: RipGrayson <49290523+RipGrayson@users.noreply.github.com> Co-authored-by: necromanceranne <40847847+necromanceranne@users.noreply.github.com> --- _maps/shuttles/infiltrator_basic.dmm | 19 +- _maps/templates/lazy_templates/nukie_base.dmm | 1289 +++++++++-------- code/__DEFINES/hud.dm | 13 + code/__DEFINES/layers.dm | 4 + code/__DEFINES/logging.dm | 1 + code/__DEFINES/minimap.dm | 62 + code/__DEFINES/traits/declarations.dm | 2 + code/__HELPERS/logging/game.dm | 4 + code/__HELPERS/type2type.dm | 9 + code/_globalvars/traits/_traits.dm | 1 + code/_onclick/click.dm | 7 + .../hud/screen_objects/screen_objects.dm | 2 +- .../configuration/entries/general.dm | 3 + .../proximity_monitor/proximity_monitor.dm | 5 +- code/game/area/areas.dm | 4 + code/game/area/areas/away_content.dm | 1 + code/game/area/areas/mining.dm | 1 + code/game/area/areas/misc.dm | 1 + code/game/area/areas/ruins/_ruins.dm | 1 + code/game/area/areas/station/cargo.dm | 1 + code/game/area/areas/station/command.dm | 1 + code/game/area/areas/station/common.dm | 1 + code/game/area/areas/station/engineering.dm | 2 + code/game/area/areas/station/hallway.dm | 1 + code/game/area/areas/station/maintenance.dm | 2 + code/game/area/areas/station/medical.dm | 2 + code/game/area/areas/station/science.dm | 2 + code/game/area/areas/station/security.dm | 1 + code/game/area/areas/station/service.dm | 8 + code/game/area/areas/station/solars.dm | 1 + code/game/area/areas/station/telecomm.dm | 1 + code/game/atom/_atom.dm | 7 + code/game/machinery/doors/door.dm | 2 + .../machinery/porta_turret/portable_turret.dm | 13 + .../objects/items/implants/implant_tacmap.dm | 120 ++ .../game/objects/items/storage/uplink_kits.dm | 2 + code/game/objects/structures/fence.dm | 1 + code/game/objects/structures/ladders.dm | 8 + code/game/objects/structures/stairs.dm | 48 + code/game/objects/structures/window.dm | 1 + code/game/turfs/closed/_closed.dm | 1 + code/game/turfs/open/asteroid.dm | 2 + code/game/turfs/open/floor/iron_floor.dm | 1 + code/game/turfs/open/floor/misc_floor.dm | 6 + code/game/turfs/open/ice.dm | 1 + code/game/turfs/open/space/space.dm | 1 + code/game/turfs/turf.dm | 3 + code/modules/antagonists/clown_ops/outfits.dm | 3 +- .../equipment/nuclear_authentication_disk.dm | 1 + .../equipment/nuclear_bomb/_nuclear_bomb.dm | 10 + .../equipment/nuclear_bomb/beer_nuke.dm | 1 + code/modules/antagonists/nukeop/outfits.dm | 21 + .../logging/categories/log_category_game.dm | 4 + code/modules/minimap/_minimap.dm | 45 + code/modules/minimap/hud/minimal_z_level.dm | 68 + code/modules/minimap/hud/minimap_dimmer.dm | 7 + code/modules/minimap/hud/minimap_display.dm | 585 ++++++++ code/modules/minimap/hud/minimap_drawing.dm | 59 + code/modules/minimap/hud/minimap_element.dm | 12 + code/modules/minimap/hud/minimap_label.dm | 6 + code/modules/minimap/hud/minimap_toolbar.dm | 198 +++ .../minimap/hud/minimap_tracking_blip.dm | 90 ++ code/modules/minimap/minimap.dm | 84 ++ code/modules/minimap/minimap_action.dm | 141 ++ code/modules/minimap/minimap_table.dm | 225 +++ .../mob/living/basic/bots/medbot/medbot.dm | 3 + .../mob/living/basic/space_fauna/carp/carp.dm | 2 + .../mob/living/silicon/robot/robot_model.dm | 17 + .../research/xenobiology/xenobiology.dm | 2 + code/modules/uplink/uplink_items/nukeops.dm | 2 +- code/modules/vehicles/mecha/combat/gygax.dm | 4 + code/modules/vehicles/mecha/combat/honker.dm | 4 + .../modules/vehicles/mecha/combat/marauder.dm | 4 + config/logging.txt | 3 + icons/hud/actions.dmi | Bin 10089 -> 9680 bytes icons/hud/implants.dmi | Bin 8488 -> 3879 bytes icons/obj/machines/minimap_table.dmi | Bin 0 -> 991 bytes icons/obj/machines/minimap_table_hologram.dmi | Bin 0 -> 18543 bytes icons/ui_icons/minimap/draw_tools.dmi | Bin 0 -> 603 bytes icons/ui_icons/minimap/map_blips.dmi | Bin 0 -> 886 bytes icons/ui_icons/minimap/map_blips_large.dmi | Bin 0 -> 818 bytes icons/ui_icons/minimap/minimap.dmi | Bin 0 -> 246 bytes icons/ui_icons/minimap/minimap_buttons.dmi | Bin 0 -> 793 bytes .../minimap/minimap_mouse/draw_blue.dmi | Bin 0 -> 253 bytes .../minimap/minimap_mouse/draw_erase.dmi | Bin 0 -> 250 bytes .../minimap/minimap_mouse/draw_purple.dmi | Bin 0 -> 271 bytes .../minimap/minimap_mouse/draw_red.dmi | Bin 0 -> 256 bytes .../minimap/minimap_mouse/draw_yellow.dmi | Bin 0 -> 252 bytes .../ui_icons/minimap/minimap_mouse/label.dmi | Bin 0 -> 243 bytes tgstation.dme | 14 + 90 files changed, 2673 insertions(+), 611 deletions(-) create mode 100644 code/__DEFINES/minimap.dm create mode 100644 code/game/objects/items/implants/implant_tacmap.dm create mode 100644 code/modules/minimap/_minimap.dm create mode 100644 code/modules/minimap/hud/minimal_z_level.dm create mode 100644 code/modules/minimap/hud/minimap_dimmer.dm create mode 100644 code/modules/minimap/hud/minimap_display.dm create mode 100644 code/modules/minimap/hud/minimap_drawing.dm create mode 100644 code/modules/minimap/hud/minimap_element.dm create mode 100644 code/modules/minimap/hud/minimap_label.dm create mode 100644 code/modules/minimap/hud/minimap_toolbar.dm create mode 100644 code/modules/minimap/hud/minimap_tracking_blip.dm create mode 100644 code/modules/minimap/minimap.dm create mode 100644 code/modules/minimap/minimap_action.dm create mode 100644 code/modules/minimap/minimap_table.dm create mode 100644 icons/obj/machines/minimap_table.dmi create mode 100644 icons/obj/machines/minimap_table_hologram.dmi create mode 100644 icons/ui_icons/minimap/draw_tools.dmi create mode 100644 icons/ui_icons/minimap/map_blips.dmi create mode 100644 icons/ui_icons/minimap/map_blips_large.dmi create mode 100644 icons/ui_icons/minimap/minimap.dmi create mode 100644 icons/ui_icons/minimap/minimap_buttons.dmi create mode 100644 icons/ui_icons/minimap/minimap_mouse/draw_blue.dmi create mode 100644 icons/ui_icons/minimap/minimap_mouse/draw_erase.dmi create mode 100644 icons/ui_icons/minimap/minimap_mouse/draw_purple.dmi create mode 100644 icons/ui_icons/minimap/minimap_mouse/draw_red.dmi create mode 100644 icons/ui_icons/minimap/minimap_mouse/draw_yellow.dmi create mode 100644 icons/ui_icons/minimap/minimap_mouse/label.dmi diff --git a/_maps/shuttles/infiltrator_basic.dmm b/_maps/shuttles/infiltrator_basic.dmm index 61f8ea231df..468a10b865b 100644 --- a/_maps/shuttles/infiltrator_basic.dmm +++ b/_maps/shuttles/infiltrator_basic.dmm @@ -19,9 +19,9 @@ /area/shuttle/syndicate/hallway) "ae" = ( /obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, -/obj/machinery/door/poddoor/shutters{ - id = "syndieshutters"; - name = "Blast Shutters" +/obj/machinery/door/poddoor/shutters/syndicate{ + name = "Blast Shutters"; + id = "syndieshutters" }, /turf/open/floor/plating, /area/shuttle/syndicate/bridge) @@ -191,10 +191,6 @@ }, /area/shuttle/syndicate/airlock) "aY" = ( -/obj/machinery/door/poddoor{ - id = "smindicate"; - name = "Outer Blast Door" - }, /obj/docking_port/mobile/infiltrator, /obj/structure/fans/tiny, /obj/machinery/button/door/directional/north{ @@ -205,6 +201,11 @@ /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 8 }, +/obj/machinery/door/poddoor/shutters/syndicate/indestructible{ + id = "smindicate"; + name = "Outer Blast Door"; + dir = 4 + }, /turf/open/floor/plating, /area/shuttle/syndicate/airlock) "aZ" = ( @@ -601,9 +602,7 @@ /obj/item/storage/box/zipties, /obj/machinery/computer/security/telescreen/entertainment/directional/west, /obj/structure/table/reinforced/plastitaniumglass, -/turf/open/floor/iron/dark/smooth_corner{ - dir = 2 - }, +/turf/open/floor/iron/dark/smooth_corner, /area/shuttle/syndicate/airlock) "iE" = ( /obj/structure/closet/syndicate/nuclear, diff --git a/_maps/templates/lazy_templates/nukie_base.dmm b/_maps/templates/lazy_templates/nukie_base.dmm index 707e8a251f3..c3c6268f400 100644 --- a/_maps/templates/lazy_templates/nukie_base.dmm +++ b/_maps/templates/lazy_templates/nukie_base.dmm @@ -7,14 +7,6 @@ "ae" = ( /turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/expansion_bombthreat) -"ah" = ( -/obj/effect/turf_decal/stripes/end{ - dir = 4 - }, -/obj/machinery/mech_bay_recharge_port, -/obj/machinery/light/cold/directional/south, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) "al" = ( /obj/effect/turf_decal/siding/wideplating/dark{ dir = 8 @@ -22,15 +14,6 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/wood/tile, /area/centcom/syndicate_mothership/control) -"as" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark, -/obj/structure/sign/poster/contraband/cybersun_six_hundred/directional/east, -/obj/item/kirbyplants/random, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) -"au" = ( -/turf/open/floor/circuit/red, -/area/centcom/syndicate_mothership/control) "ay" = ( /obj/structure/table/reinforced, /obj/item/papercutter, @@ -54,6 +37,13 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/centcom/syndicate_mothership/control) +"aS" = ( +/obj/effect/turf_decal/siding/red/corner, +/obj/item/folder/red, +/obj/item/pen/red, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "aX" = ( /obj/machinery/shower/directional/south, /turf/open/floor/iron/freezer, @@ -77,10 +67,6 @@ /obj/structure/mirror/directional/east, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) -"bp" = ( -/obj/machinery/light/cold/directional/north, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) "bB" = ( /obj/structure/railing{ dir = 4 @@ -123,6 +109,10 @@ }, /turf/open/floor/mineral/titanium/tiled/yellow, /area/centcom/syndicate_mothership/expansion_bombthreat) +"bS" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/turf/closed/indestructible/syndicate, +/area/centcom/syndicate_mothership/control) "bT" = ( /obj/structure/flora/rock/pile/style_random, /turf/open/misc/asteroid/snow/airless, @@ -162,6 +152,15 @@ /obj/structure/cable, /turf/open/floor/iron/smooth, /area/centcom/syndicate_mothership/control) +"cC" = ( +/obj/machinery/vending/cola, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/turf/open/floor/iron/white/textured_large{ + color = "#b51026" + }, +/area/centcom/syndicate_mothership/control) "cF" = ( /obj/effect/baseturf_helper/asteroid/snow, /turf/closed/indestructible/syndicate, @@ -219,6 +218,20 @@ /obj/structure/flora/grass/both/style_random, /turf/open/misc/asteroid/snow/icemoon, /area/centcom/syndicate_mothership/control) +"cW" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/machinery/light/red/dim/directional/north, +/turf/open/floor/iron/smooth_half, +/area/centcom/syndicate_mothership/control) +"cY" = ( +/obj/machinery/light/cold/directional/east, +/obj/machinery/vending/snack/teal, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, +/turf/open/floor/catwalk_floor/iron_dark, +/area/centcom/syndicate_mothership/control) "cZ" = ( /obj/structure/mop_bucket/janitorialcart{ dir = 4 @@ -233,15 +246,6 @@ /obj/machinery/shower/directional/south, /turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/control) -"dn" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 1 - }, -/obj/machinery/camera/autoname/directional/west{ - network = list("nukie") - }, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) "dq" = ( /obj/machinery/light/small/directional/north, /turf/open/floor/iron/smooth_half, @@ -252,22 +256,16 @@ }, /turf/open/misc/asteroid/snow/airless, /area/centcom/syndicate_mothership) -"du" = ( -/obj/structure/chair/stool/directional/north, -/obj/effect/landmark/start/nukeop_base, -/obj/structure/sign/poster/contraband/donk_co/directional/south, -/turf/open/floor/wood/tile, -/area/centcom/syndicate_mothership/control) -"dw" = ( -/obj/structure/table/reinforced, -/obj/machinery/recharger, -/turf/open/floor/carpet, -/area/centcom/syndicate_mothership/control) "dx" = ( /obj/machinery/shower/directional/east, /obj/effect/turf_decal/stripes/box, /turf/open/floor/mineral/titanium/tiled, /area/centcom/syndicate_mothership/expansion_chemicalwarfare) +"dB" = ( +/obj/machinery/recharger, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/carpet, +/area/centcom/syndicate_mothership/control) "dF" = ( /obj/machinery/light/cold/directional/west, /obj/structure/table/glass/plasmaglass, @@ -467,6 +465,12 @@ /obj/effect/mapping_helpers/airlock/access/all/syndicate/general, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) +"eM" = ( +/obj/effect/turf_decal/siding/red, +/obj/machinery/recharger, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "fa" = ( /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ @@ -478,15 +482,6 @@ }, /turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/control) -"fb" = ( -/obj/structure/chair/sofa/bench/left{ - dir = 4 - }, -/obj/machinery/camera/autoname/directional/north{ - network = list("nukie") - }, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) "fk" = ( /turf/open/floor/circuit/red/off, /area/centcom/syndicate_mothership/expansion_bioterrorism) @@ -497,6 +492,15 @@ /obj/machinery/portable_atmospherics/canister/plasma, /turf/open/floor/plating, /area/centcom/syndicate_mothership/expansion_bombthreat) +"fr" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 10 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/folder/white, +/obj/item/pen/red, +/turf/open/floor/iron/smooth_half, +/area/centcom/syndicate_mothership/control) "fu" = ( /obj/machinery/shower/directional/south, /obj/machinery/light/floor, @@ -546,6 +550,14 @@ /obj/machinery/hydroponics/constructable, /turf/open/floor/mineral/titanium/tiled, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"fP" = ( +/obj/effect/turf_decal/siding/red, +/obj/effect/turf_decal/tile/red/half{ + dir = 1 + }, +/obj/machinery/light/red/dim/directional/north, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "fR" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/heat_exchanging/junction, @@ -554,6 +566,11 @@ "fT" = ( /turf/open/floor/engine/bz, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"fU" = ( +/obj/structure/extinguisher_cabinet/directional/west, +/obj/effect/turf_decal/tile/red/half, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "fV" = ( /obj/structure/frame/computer{ dir = 1 @@ -579,36 +596,24 @@ /obj/machinery/atmospherics/pipe/heat_exchanging/junction/layer2, /turf/closed/indestructible/syndicate, /area/centcom/syndicate_mothership/expansion_bombthreat) -"go" = ( -/obj/machinery/light/cold/directional/east, -/obj/machinery/vending/snack/teal, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, -/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, -/turf/open/floor/catwalk_floor/titanium, -/area/centcom/syndicate_mothership/control) "gs" = ( /obj/structure/extinguisher_cabinet/directional/west, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) +"gu" = ( +/obj/structure/chair/sofa/bench/right{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, +/turf/open/floor/catwalk_floor/iron_dark, +/area/centcom/syndicate_mothership/control) "gw" = ( /obj/machinery/light/small/directional/west, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) -"gB" = ( -/obj/effect/turf_decal/siding/wideplating/dark{ - dir = 8 - }, -/obj/effect/turf_decal/siding/wideplating/dark{ - dir = 4 - }, -/obj/machinery/door/airlock/public/glass{ - name = "War Room" - }, -/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, -/turf/open/floor/iron/textured_large, -/area/centcom/syndicate_mothership/control) "gD" = ( /obj/structure/flora/tree/dead/style_random, /obj/structure/flora/grass/both/style_random, @@ -789,21 +794,13 @@ dir = 4 }, /area/centcom/syndicate_mothership/expansion_fridgerummage) -"ij" = ( -/obj/structure/chair/sofa/bench/left{ - dir = 8 +"ih" = ( +/obj/machinery/camera/autoname/directional/west{ + network = list("nukie") }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, -/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, -/turf/open/floor/catwalk_floor/titanium, -/area/centcom/syndicate_mothership/control) -"il" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark{ +/obj/effect/turf_decal/tile/red/half{ dir = 1 }, -/obj/effect/turf_decal/siding/red/corner, /turf/open/floor/iron/dark/textured_large, /area/centcom/syndicate_mothership/control) "is" = ( @@ -812,6 +809,13 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/centcom/syndicate_mothership/control) +"iz" = ( +/obj/effect/turf_decal/siding/red/corner{ + dir = 1 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "iA" = ( /obj/effect/turf_decal/siding/thinplating{ dir = 1 @@ -842,9 +846,11 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_chemicalwarfare) -"iV" = ( -/obj/structure/chair/stool/directional/north, -/turf/open/floor/iron/dark/textured_large, +"iU" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 6 + }, +/turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/control) "iX" = ( /obj/machinery/vending/dinnerware, @@ -856,6 +862,16 @@ /obj/machinery/light/cold/directional/west, /turf/open/floor/iron, /area/centcom/syndicate_mothership/control) +"jd" = ( +/obj/structure/chair/stool/directional/south, +/obj/structure/sign/map/left{ + desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown)."; + icon_state = "map-left-MS"; + pixel_y = 32 + }, +/obj/effect/landmark/start/nukeop_base, +/turf/open/floor/wood/tile, +/area/centcom/syndicate_mothership/control) "je" = ( /obj/effect/turf_decal/siding/wideplating{ dir = 8 @@ -917,6 +933,15 @@ /obj/structure/noticeboard/directional/north, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"kf" = ( +/obj/effect/turf_decal/siding/red/corner{ + dir = 8 + }, +/obj/item/folder/red, +/obj/item/pen/red, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "kg" = ( /turf/open/misc/ice/icemoon, /area/centcom/syndicate_mothership/control) @@ -1022,12 +1047,6 @@ }, /turf/open/lava/plasma/ice_moon, /area/centcom/syndicate_mothership/control) -"lc" = ( -/obj/effect/turf_decal/siding/red/corner{ - dir = 4 - }, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) "ld" = ( /turf/open/floor/iron/smooth_edge{ dir = 8 @@ -1047,13 +1066,6 @@ /obj/structure/flora/grass/both/style_random, /turf/open/misc/asteroid/snow/airless, /area/centcom/syndicate_mothership) -"lo" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark, -/obj/machinery/camera/autoname/directional/south{ - network = list("nukie") - }, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) "lt" = ( /obj/effect/turf_decal/siding/thinplating_new/dark, /turf/open/floor/mineral/plastitanium, @@ -1125,18 +1137,6 @@ /obj/machinery/chem_dispenser/mutagensaltpeter, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bioterrorism) -"my" = ( -/obj/effect/landmark/start/nukeop_base/leader, -/obj/effect/turf_decal/tile/bar/opposingcorners, -/turf/open/floor/iron, -/area/centcom/syndicate_mothership/control) -"mz" = ( -/obj/machinery/vending/cola, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 4 - }, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) "mA" = ( /obj/effect/turf_decal/stripes/line{ dir = 10 @@ -1152,6 +1152,10 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bombthreat) +"mC" = ( +/obj/effect/turf_decal/tile/red/half, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "mJ" = ( /obj/structure/sign/poster/contraband/free_key, /turf/closed/indestructible/syndicate, @@ -1176,19 +1180,6 @@ }, /turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/expansion_chemicalwarfare) -"ng" = ( -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 1 - }, -/obj/structure/fans/tiny, -/obj/machinery/door/poddoor/shutters/syndicate{ - id = "FBBZ1"; - name = "Security Shutters"; - dir = 1 - }, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) "nk" = ( /obj/structure/flora/tree/dead/style_random, /obj/structure/flora/grass/both/style_random, @@ -1217,14 +1208,14 @@ /obj/structure/flora/tree/pine/style_random, /turf/open/misc/asteroid/snow/airless, /area/centcom/syndicate_mothership) -"nD" = ( -/obj/effect/turf_decal/stripes/full, -/turf/open/floor/mineral/titanium/yellow, -/area/centcom/syndicate_mothership/control) "nF" = ( /obj/effect/turf_decal/syndicateemblem/top/middle, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/control) +"nG" = ( +/obj/machinery/vending/cigarette/syndicate, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "nH" = ( /obj/effect/turf_decal/siding/thinplating_new/dark, /obj/structure/closet/syndicate/personal, @@ -1234,6 +1225,10 @@ dir = 8 }, /area/centcom/syndicate_mothership/control) +"nI" = ( +/obj/machinery/minimap_table, +/turf/open/floor/circuit/red/no_power, +/area/centcom/syndicate_mothership/control) "nL" = ( /obj/structure/chair/office/light{ dir = 1 @@ -1255,6 +1250,12 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/centcom/syndicate_mothership/control) +"nV" = ( +/obj/structure/chair/stool/directional/north, +/obj/effect/landmark/start/nukeop_base, +/obj/structure/sign/poster/contraband/donk_co/directional/south, +/turf/open/floor/wood/tile, +/area/centcom/syndicate_mothership/control) "oc" = ( /obj/structure/fence{ dir = 4 @@ -1270,13 +1271,6 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bombthreat) -"oh" = ( -/obj/structure/table/reinforced, -/obj/item/syndicatedetonator{ - desc = "This gaudy button can be used to instantly detonate syndicate bombs that have been activated on the station. It is also fun to press." - }, -/turf/open/floor/carpet, -/area/centcom/syndicate_mothership/control) "oi" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 10 @@ -1288,16 +1282,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, /turf/open/floor/catwalk_floor/iron_dark, /area/centcom/syndicate_mothership/control) -"or" = ( -/obj/effect/turf_decal/siding/wideplating/dark{ - dir = 1 +"om" = ( +/obj/structure/chair/sofa/bench/left{ + dir = 4 }, -/obj/effect/turf_decal/siding/wideplating/dark, -/obj/machinery/door/airlock/hatch{ - name = "Gangway" - }, -/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, -/turf/open/floor/iron, +/obj/structure/sign/poster/contraband/smoke/directional/north, +/turf/open/floor/iron/dark/textured_large, /area/centcom/syndicate_mothership/control) "os" = ( /obj/effect/turf_decal/stripes/box, @@ -1314,10 +1304,19 @@ }, /turf/open/floor/engine/vacuum, /area/centcom/syndicate_mothership/expansion_bombthreat) -"oD" = ( +"oA" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 10 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/centcom/syndicate_mothership/control) +"oH" = ( /obj/effect/turf_decal/siding/red{ dir = 1 }, +/obj/item/folder/red, +/obj/item/pen/red, +/obj/structure/table/reinforced/plastitaniumglass, /turf/open/floor/iron/dark/textured_large, /area/centcom/syndicate_mothership/control) "oK" = ( @@ -1356,6 +1355,14 @@ }, /turf/open/floor/engine, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"oU" = ( +/obj/effect/turf_decal/siding/red{ + dir = 1 + }, +/obj/machinery/recharger, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "oW" = ( /obj/effect/turf_decal/siding/thinplating{ dir = 9 @@ -1402,11 +1409,11 @@ /obj/structure/flora/rock/icy/style_random, /turf/open/misc/asteroid/snow/airless, /area/centcom/syndicate_mothership) -"pr" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark{ +"pp" = ( +/obj/effect/turf_decal/siding/red, +/obj/effect/turf_decal/tile/red/half{ dir = 1 }, -/obj/effect/turf_decal/siding/red, /turf/open/floor/iron/dark/textured_large, /area/centcom/syndicate_mothership/control) "ps" = ( @@ -1438,13 +1445,6 @@ /obj/machinery/vending/tool, /turf/open/floor/mineral/titanium/yellow, /area/centcom/syndicate_mothership/control) -"pS" = ( -/obj/structure/chair/greyscale{ - dir = 4 - }, -/obj/effect/landmark/start/nukeop_base/overwatch, -/turf/open/floor/mineral/plastitanium, -/area/centcom/syndicate_mothership) "pU" = ( /obj/structure/chair/office/light{ dir = 8 @@ -1515,10 +1515,6 @@ }, /turf/open/floor/plastic, /area/centcom/syndicate_mothership/expansion_fridgerummage) -"qv" = ( -/obj/item/kirbyplants/random, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) "qw" = ( /turf/open/floor/plating, /area/centcom/syndicate_mothership/control) @@ -1583,6 +1579,19 @@ }, /turf/open/misc/asteroid/snow/airless, /area/centcom/syndicate_mothership) +"qR" = ( +/obj/effect/turf_decal/siding/wideplating{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wideplating, +/obj/machinery/door/poddoor/shutters/syndicate/indestructible{ + name = "Base Lift"; + dir = 1; + id_tag = "nukiespawnlift"; + id = "nukiespawnlift" + }, +/turf/open/floor/iron/dark/textured_half, +/area/centcom/syndicate_mothership/control) "qU" = ( /obj/structure/flora/rock/icy/style_random{ pixel_x = -7 @@ -1592,16 +1601,6 @@ "qX" = ( /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_chemicalwarfare) -"rb" = ( -/obj/effect/turf_decal/siding/red, -/obj/structure/table/reinforced, -/obj/machinery/recharger, -/obj/item/stack/spacecash/c10{ - pixel_x = -19; - pixel_y = 10 - }, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) "rf" = ( /turf/open/floor/iron/stairs/old, /area/centcom/syndicate_mothership/control) @@ -1623,25 +1622,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, /turf/open/floor/iron/smooth, /area/centcom/syndicate_mothership/control) -"ru" = ( -/obj/effect/turf_decal/siding/wideplating{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wideplating, -/obj/machinery/door/poddoor/shutters/syndicate/indestructible{ - name = "Base Lift"; - dir = 1; - id_tag = "nukiespawnlift"; - id = "nukiespawnlift" - }, -/turf/open/floor/iron/dark/textured_half, -/area/centcom/syndicate_mothership/control) -"rw" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 6 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/centcom/syndicate_mothership/control) "rA" = ( /obj/effect/turf_decal/siding/purple{ dir = 1 @@ -1681,6 +1661,14 @@ /obj/structure/fence/door/opened, /turf/open/misc/asteroid/snow/icemoon, /area/centcom/syndicate_mothership/control) +"rO" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/folder/red, +/turf/open/floor/iron/smooth_half, +/area/centcom/syndicate_mothership/control) "rS" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 5 @@ -1838,20 +1826,6 @@ }, /turf/open/floor/mineral/titanium/tiled/yellow, /area/centcom/syndicate_mothership/expansion_bombthreat) -"tu" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red/corner{ - dir = 1 - }, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) -"tv" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red/corner, -/obj/item/folder/red, -/obj/item/pen/red, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) "tz" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 8 @@ -1922,6 +1896,13 @@ /obj/structure/statue/uranium/nuke, /turf/open/misc/asteroid/snow/icemoon, /area/centcom/syndicate_mothership/control) +"ux" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, +/turf/open/floor/catwalk_floor/iron_dark, +/area/centcom/syndicate_mothership/control) "uK" = ( /obj/effect/turf_decal/siding/wideplating{ dir = 1 @@ -1954,6 +1935,14 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/centcom/syndicate_mothership/control) +"uY" = ( +/obj/effect/turf_decal/siding/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red/half, +/obj/machinery/light/red/dim/directional/south, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "ve" = ( /obj/effect/turf_decal/syndicateemblem/top/middle{ dir = 1 @@ -1974,26 +1963,17 @@ /obj/machinery/portable_atmospherics/canister/carbon_dioxide, /turf/open/floor/plating, /area/centcom/syndicate_mothership/expansion_bombthreat) -"vv" = ( -/obj/structure/table/reinforced, -/obj/item/paper/fluff/stations/centcom/disk_memo{ - pixel_x = -6; - pixel_y = -7 +"vn" = ( +/obj/effect/turf_decal/tile/red{ + dir = 1 }, -/obj/item/taperecorder{ - pixel_y = 15 - }, -/obj/item/stack/spacecash/c50, -/turf/open/floor/carpet, +/turf/open/floor/iron/dark/textured_large, /area/centcom/syndicate_mothership/control) -"vx" = ( -/obj/machinery/door/airlock/external/ruin, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 +"vB" = ( +/obj/effect/turf_decal/tile/red/anticorner{ + dir = 1 }, -/obj/structure/fans/tiny, -/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, -/turf/open/floor/plating, +/turf/open/floor/iron/dark/textured_large, /area/centcom/syndicate_mothership/control) "vI" = ( /obj/structure/railing, @@ -2038,16 +2018,6 @@ /obj/structure/filingcabinet/medical, /turf/open/floor/carpet, /area/centcom/syndicate_mothership/control) -"wc" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) -"we" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 5 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/centcom/syndicate_mothership/control) "wg" = ( /obj/structure/fence/corner{ dir = 6 @@ -2077,6 +2047,16 @@ }, /turf/open/misc/asteroid/snow/airless, /area/centcom/syndicate_mothership) +"ww" = ( +/obj/structure/chair/sofa/bench/left{ + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, +/turf/open/floor/catwalk_floor/iron_dark, +/area/centcom/syndicate_mothership/control) "wC" = ( /obj/structure/chair/sofa/bench/right{ dir = 4 @@ -2084,6 +2064,15 @@ /obj/structure/sign/poster/contraband/rebels_unite/directional/south, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) +"wD" = ( +/obj/structure/chair/sofa/bench/left{ + dir = 4 + }, +/obj/machinery/camera/autoname/directional/north{ + network = list("nukie") + }, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "wG" = ( /turf/open/floor/iron/smooth_half{ dir = 1 @@ -2112,10 +2101,6 @@ dir = 8 }, /area/centcom/syndicate_mothership/control) -"wS" = ( -/obj/effect/landmark/nukeop_elevator/exterior, -/turf/closed/indestructible/syndicate, -/area/centcom/syndicate_mothership/control) "wW" = ( /obj/structure/flora/rock/pile/style_random, /obj/effect/light_emitter{ @@ -2124,6 +2109,10 @@ }, /turf/open/misc/asteroid/snow/airless, /area/centcom/syndicate_mothership) +"wX" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner, +/turf/open/floor/iron/smooth_half, +/area/centcom/syndicate_mothership/control) "wY" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/monitored{ desc = "Has a valve and pump attached to it. Slightly more menacing than Nanotrasen's standard."; @@ -2150,11 +2139,18 @@ /obj/effect/turf_decal/siding/thinplating_new/dark/corner, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bioterrorism) -"xj" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, -/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, -/turf/open/floor/mineral/titanium, +"xt" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/fans/tiny, +/obj/effect/turf_decal/tile/bar/opposingcorners, +/obj/machinery/door/poddoor/shutters/syndicate{ + dir = 1 + }, +/turf/open/floor/iron, /area/centcom/syndicate_mothership/control) "xu" = ( /turf/closed/indestructible/syndicate, @@ -2177,6 +2173,12 @@ "ya" = ( /turf/open/floor/carpet, /area/centcom/syndicate_mothership/control) +"yb" = ( +/obj/effect/turf_decal/tile/red/half{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "ye" = ( /obj/effect/turf_decal/weather/snow/corner{ dir = 10 @@ -2260,6 +2262,10 @@ /obj/structure/chair/office, /turf/open/floor/mineral/titanium/tiled/yellow, /area/centcom/syndicate_mothership/expansion_chemicalwarfare) +"zl" = ( +/obj/machinery/light/small/red/directional/west, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "zo" = ( /obj/item/stack/sheet/mineral/sandbags, /turf/open/floor/catwalk_floor/iron_dark, @@ -2290,11 +2296,14 @@ }, /turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/control) -"zH" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark, -/obj/item/kirbyplants/random, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) +"zI" = ( +/obj/effect/light_emitter{ + set_cap = 1; + set_luminosity = 4 + }, +/obj/structure/flora/tree/dead/style_random, +/turf/closed/indestructible/rock/snow, +/area/centcom/syndicate_mothership) "zL" = ( /obj/structure/rack, /obj/item/restraints/handcuffs/cable/pink, @@ -2395,6 +2404,10 @@ }, /turf/open/floor/plating, /area/centcom/syndicate_mothership/expansion_bombthreat) +"AE" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/turf/open/floor/iron/smooth_half, +/area/centcom/syndicate_mothership/control) "AL" = ( /obj/machinery/light/cold/directional/south, /turf/open/floor/iron/smooth_half{ @@ -2404,29 +2417,6 @@ "AM" = ( /turf/closed/indestructible/iron, /area/centcom/syndicate_mothership/control) -"AN" = ( -/obj/structure/table/reinforced/plastitaniumglass, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 1 - }, -/obj/structure/fans/tiny, -/obj/effect/turf_decal/tile/bar/opposingcorners, -/obj/machinery/door/poddoor/shutters/syndicate{ - dir = 1 - }, -/turf/open/floor/iron, -/area/centcom/syndicate_mothership/control) -"AO" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red/corner{ - dir = 4 - }, -/obj/item/stack/spacecash/c1{ - pixel_y = 12 - }, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) "AR" = ( /obj/effect/baseturf_helper/asteroid/snow, /turf/closed/indestructible/syndicate, @@ -2436,16 +2426,6 @@ /obj/structure/flora/grass/both/style_random, /turf/open/misc/asteroid/snow/icemoon, /area/centcom/syndicate_mothership/control) -"AV" = ( -/obj/structure/chair/stool/directional/south, -/obj/structure/sign/map/left{ - desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown)."; - icon_state = "map-left-MS"; - pixel_y = 32 - }, -/obj/effect/landmark/start/nukeop_base, -/turf/open/floor/wood/tile, -/area/centcom/syndicate_mothership/control) "AW" = ( /obj/machinery/chem_master, /turf/open/floor/mineral/titanium/tiled/yellow, @@ -2577,6 +2557,17 @@ }, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) +"Cn" = ( +/obj/structure/chair/sofa/bench{ + dir = 4 + }, +/obj/machinery/light/cold/directional/west, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, +/turf/open/floor/catwalk_floor/iron_dark, +/area/centcom/syndicate_mothership/control) "Ct" = ( /obj/machinery/door/airlock/hatch{ name = "Closet" @@ -2631,6 +2622,15 @@ }, /turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/control) +"CW" = ( +/obj/effect/turf_decal/siding/red{ + dir = 4 + }, +/obj/item/paper_bin, +/obj/item/pen, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "CX" = ( /turf/open/floor/mineral/titanium/tiled/yellow, /area/centcom/syndicate_mothership) @@ -2648,6 +2648,16 @@ /obj/structure/sign/poster/contraband/gorlex_recruitment/directional/west, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) +"Dt" = ( +/obj/effect/turf_decal/siding/red/corner{ + dir = 4 + }, +/obj/item/stack/spacecash/c1{ + pixel_y = 12 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "Du" = ( /obj/docking_port/stationary{ area_type = /area/centcom/syndicate_mothership; @@ -2685,6 +2695,10 @@ }, /turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/control) +"DQ" = ( +/obj/effect/landmark/nukeop_elevator/exterior, +/turf/closed/indestructible/syndicate, +/area/centcom/syndicate_mothership/control) "DV" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 8 @@ -2729,13 +2743,6 @@ "DZ" = ( /turf/closed/indestructible/syndicate, /area/centcom/syndicate_mothership/control) -"Ed" = ( -/obj/structure/chair/sofa/bench/left{ - dir = 4 - }, -/obj/structure/sign/poster/contraband/smoke/directional/north, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) "Ef" = ( /obj/structure/fence, /turf/open/misc/asteroid/snow/airless, @@ -2799,23 +2806,16 @@ /obj/effect/turf_decal/siding/purple, /turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/expansion_chemicalwarfare) -"Fm" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red/corner{ - dir = 8 +"Fl" = ( +/obj/structure/chair/stool/directional/west, +/obj/effect/landmark/start/nukeop_base, +/turf/open/floor/wood/tile, +/area/centcom/syndicate_mothership/control) +"Fo" = ( +/obj/machinery/light/small/red/directional/north{ + allow_break_on_init = 0 }, -/obj/item/folder/red, -/obj/item/pen/red, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) -"Fp" = ( -/obj/machinery/vending/cigarette/syndicate, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) -"Fq" = ( -/obj/structure/table/reinforced, -/obj/item/flashlight/lamp, -/turf/open/floor/carpet, +/turf/open/floor/mineral/plastitanium, /area/centcom/syndicate_mothership/control) "FB" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ @@ -2826,6 +2826,25 @@ }, /turf/open/floor/mineral/titanium/tiled/yellow, /area/centcom/syndicate_mothership/expansion_bombthreat) +"FC" = ( +/obj/item/paper/fluff/stations/centcom/disk_memo{ + pixel_x = -6; + pixel_y = -7 + }, +/obj/item/taperecorder{ + pixel_y = 15 + }, +/obj/item/stack/spacecash/c50, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/carpet, +/area/centcom/syndicate_mothership/control) +"FE" = ( +/obj/item/syndicatedetonator{ + desc = "This gaudy button can be used to instantly detonate syndicate bombs that have been activated on the station. It is also fun to press." + }, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/carpet, +/area/centcom/syndicate_mothership/control) "FG" = ( /obj/effect/turf_decal/stripes/corner, /obj/effect/turf_decal/stripes/corner{ @@ -2847,6 +2866,12 @@ /obj/machinery/atmospherics/pipe/heat_exchanging/simple, /turf/closed/indestructible/syndicate, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"FQ" = ( +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "FR" = ( /obj/machinery/light/floor, /turf/open/floor/iron/dark/textured_half{ @@ -2991,17 +3016,6 @@ dir = 8 }, /area/centcom/syndicate_mothership/control) -"GI" = ( -/obj/structure/chair/sofa/bench{ - dir = 4 - }, -/obj/machinery/light/cold/directional/west, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, -/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, -/turf/open/floor/catwalk_floor/titanium, -/area/centcom/syndicate_mothership/control) "GL" = ( /obj/structure/lattice/catwalk, /obj/effect/turf_decal/stripes/line{ @@ -3057,10 +3071,6 @@ }, /turf/open/misc/ice/icemoon, /area/centcom/syndicate_mothership/control) -"Hs" = ( -/obj/machinery/shuttle_manipulator, -/turf/open/floor/circuit/red, -/area/centcom/syndicate_mothership/control) "Ht" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 8 @@ -3114,12 +3124,26 @@ /obj/item/stack/sheet/mineral/plasma, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"HE" = ( +/obj/effect/landmark/start/nukeop_base/leader, +/obj/effect/turf_decal/tile/bar/opposingcorners, +/turf/open/floor/iron, +/area/centcom/syndicate_mothership/control) "HJ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/centcom/syndicate_mothership/control) +"HN" = ( +/obj/machinery/vending/coffee, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/turf/open/floor/iron/white/textured_large{ + color = "#b51026" + }, +/area/centcom/syndicate_mothership/control) "HW" = ( /obj/effect/light_emitter{ set_cap = 1; @@ -3140,6 +3164,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, /turf/open/floor/catwalk_floor/iron_dark, /area/centcom/syndicate_mothership/control) +"Ic" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/structure/fans/tiny, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/door/airlock/hatch{ + name = "Security Checkpoint" + }, +/turf/open/floor/plating, +/area/centcom/syndicate_mothership/control) "Id" = ( /obj/structure/closet/crate/freezer{ name = "meat freezer" @@ -3204,6 +3239,11 @@ }, /turf/open/misc/asteroid/snow/icemoon, /area/centcom/syndicate_mothership/control) +"IA" = ( +/obj/item/flashlight/lamp, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/carpet, +/area/centcom/syndicate_mothership/control) "IC" = ( /obj/structure/chair/stool/bar/directional/west, /obj/effect/turf_decal/siding/thinplating/dark{ @@ -3212,41 +3252,12 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/centcom/syndicate_mothership/control) -"IL" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red, -/obj/item/toy/nuke{ - pixel_x = -5; - pixel_y = 1 - }, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) -"IM" = ( -/obj/structure/chair/sofa/bench/right{ - dir = 4 - }, -/obj/effect/turf_decal/siding/thinplating_new/dark, -/turf/open/floor/mineral/titanium, -/area/centcom/syndicate_mothership/control) "IQ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) -"IV" = ( -/obj/structure/chair/stool/directional/south, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 1 - }, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) -"Ja" = ( -/obj/machinery/light/small/red/directional/north{ - allow_break_on_init = 0 - }, -/turf/open/floor/mineral/plastitanium, -/area/centcom/syndicate_mothership/control) "Jc" = ( /obj/structure/table/wood, /obj/machinery/chem_dispenser/drinks/beer{ @@ -3282,6 +3293,10 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"Jr" = ( +/obj/effect/turf_decal/stripes/full, +/turf/open/floor/mineral/titanium, +/area/centcom/syndicate_mothership/control) "Js" = ( /obj/structure/table/wood, /obj/item/rag, @@ -3298,6 +3313,19 @@ }, /turf/open/floor/mineral/titanium/tiled/yellow, /area/centcom/syndicate_mothership/expansion_bombthreat) +"JE" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 9 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/centcom/syndicate_mothership/control) +"JG" = ( +/obj/structure/chair/comfy/black{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red/full, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "JJ" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 5 @@ -3341,6 +3369,13 @@ /obj/effect/turf_decal/syndicateemblem/top/left, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/control) +"JY" = ( +/obj/effect/turf_decal/siding/red/corner, +/obj/effect/turf_decal/tile/red/half{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "Ka" = ( /obj/structure/chair/sofa/bench/right{ dir = 4 @@ -3361,6 +3396,12 @@ /obj/structure/flora/grass/both/style_random, /turf/open/misc/asteroid/snow/icemoon, /area/centcom/syndicate_mothership/control) +"KB" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, +/turf/open/floor/iron/smooth_large, +/area/centcom/syndicate_mothership/control) "KD" = ( /obj/effect/turf_decal/trimline/red, /obj/effect/turf_decal/trimline/red, @@ -3410,6 +3451,14 @@ }, /turf/open/lava/plasma/ice_moon, /area/centcom/syndicate_mothership/control) +"KT" = ( +/obj/effect/turf_decal/stripes/end{ + dir = 4 + }, +/obj/machinery/mech_bay_recharge_port, +/obj/machinery/light/red/dim/directional/south, +/turf/open/floor/mineral/titanium, +/area/centcom/syndicate_mothership/control) "KU" = ( /obj/effect/light_emitter{ set_cap = 1; @@ -3426,18 +3475,24 @@ }, /turf/open/floor/iron/smooth_half, /area/centcom/syndicate_mothership/control) +"KX" = ( +/obj/effect/turf_decal/siding/red{ + dir = 8 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "Ld" = ( /obj/effect/turf_decal/siding/thinplating_new/dark, /obj/structure/closet/syndicate/personal, /obj/effect/turf_decal/tile/red/full, /turf/open/floor/iron/dark/textured_half, /area/centcom/syndicate_mothership/control) -"Lk" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red{ - dir = 8 +"Le" = ( +/obj/structure/chair/comfy/black{ + dir = 4 }, -/obj/item/storage/fancy/donut_box, +/obj/effect/turf_decal/tile/red/full, /turf/open/floor/iron/dark/textured_large, /area/centcom/syndicate_mothership/control) "Lu" = ( @@ -3473,15 +3528,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, /turf/open/floor/stone, /area/centcom/syndicate_mothership/control) -"LB" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red{ - dir = 1 - }, -/obj/item/folder/red, -/obj/item/pen/red, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) "LH" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/components/binary/pump/on, @@ -3530,13 +3576,6 @@ }, /turf/open/floor/plating/snowed/icemoon, /area/centcom/syndicate_mothership/control) -"Me" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, -/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, -/turf/open/floor/catwalk_floor/titanium, -/area/centcom/syndicate_mothership/control) "Mh" = ( /obj/structure/sign/poster/contraband/lamarr/directional/south, /turf/open/floor/iron/smooth_half{ @@ -3608,6 +3647,12 @@ /obj/effect/mapping_helpers/airlock/access/all/syndicate/general, /turf/open/floor/catwalk_floor/iron, /area/centcom/syndicate_mothership/control) +"MF" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "MH" = ( /obj/machinery/hydroponics/constructable, /obj/machinery/light/cold/directional/west, @@ -3632,14 +3677,6 @@ dir = 8 }, /area/centcom/syndicate_mothership/control) -"MU" = ( -/obj/effect/turf_decal/siding/wideplating/dark{ - dir = 8 - }, -/obj/structure/chair/stool/directional/east, -/obj/effect/landmark/start/nukeop_base, -/turf/open/floor/wood/tile, -/area/centcom/syndicate_mothership/control) "Nb" = ( /obj/structure/chair/sofa/right/brown{ dir = 4 @@ -3653,6 +3690,13 @@ name = "Tac-Com" }, /area/centcom/syndicate_mothership/control) +"Ne" = ( +/obj/effect/turf_decal/siding/red/corner{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red/half, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "Ni" = ( /obj/machinery/light/small/directional/north, /obj/machinery/computer/slot_machine/syndicate, @@ -3734,6 +3778,13 @@ /obj/item/melee/powerfist, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bombthreat) +"Og" = ( +/obj/structure/chair/sofa/bench/right{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "Oi" = ( /obj/structure/cable, /turf/closed/indestructible/syndicate, @@ -3858,6 +3909,24 @@ "Ph" = ( /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"Pp" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/turf/open/floor/iron/smooth_large, +/area/centcom/syndicate_mothership/control) +"Ps" = ( +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/fans/tiny, +/obj/machinery/door/poddoor/shutters/syndicate{ + id = "FBBZ1"; + name = "Security Shutters"; + dir = 1 + }, +/turf/open/floor/mineral/titanium, +/area/centcom/syndicate_mothership/control) "Pu" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -4057,6 +4126,13 @@ /obj/structure/cable, /turf/open/floor/catwalk_floor/iron, /area/centcom/syndicate_mothership/control) +"Re" = ( +/obj/effect/turf_decal/siding/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red/half, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "Rn" = ( /obj/item/circuitboard/computer/syndicate_shuttle{ pixel_x = 2; @@ -4132,6 +4208,14 @@ /obj/effect/baseturf_helper/asteroid/snow, /turf/closed/indestructible/syndicate, /area/centcom/syndicate_mothership/expansion_bioterrorism) +"RV" = ( +/obj/effect/turf_decal/siding/wideplating/dark{ + dir = 8 + }, +/obj/structure/chair/stool/directional/east, +/obj/effect/landmark/start/nukeop_base, +/turf/open/floor/wood/tile, +/area/centcom/syndicate_mothership/control) "Sc" = ( /obj/structure/railing, /turf/open/floor/iron/stairs/old{ @@ -4139,18 +4223,6 @@ initial_gas_mix = "TEMP=2.7" }, /area/centcom/syndicate_mothership) -"Se" = ( -/obj/machinery/door/airlock/external/ruin, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, -/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, -/turf/open/floor/plating, -/area/centcom/syndicate_mothership/control) "Sg" = ( /obj/machinery/camera/autoname/directional/east{ network = list("nukie") @@ -4210,6 +4282,11 @@ /obj/item/mop, /turf/open/floor/catwalk_floor/iron_smooth, /area/centcom/syndicate_mothership/control) +"Sz" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/sign/poster/contraband/cybersun_six_hundred/directional/east, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "SD" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 8 @@ -4217,6 +4294,12 @@ /obj/machinery/portable_atmospherics/pump, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/expansion_bombthreat) +"SH" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, +/turf/closed/indestructible/opsglass, +/area/centcom/syndicate_mothership/control) "SJ" = ( /obj/machinery/atmospherics/components/trinary/filter{ dir = 8 @@ -4242,6 +4325,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, /turf/closed/indestructible/opsglass, /area/centcom/syndicate_mothership/control) +"SN" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 6 + }, +/turf/open/floor/iron/smooth_half, +/area/centcom/syndicate_mothership/control) "SR" = ( /obj/structure/railing, /obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, @@ -4352,12 +4441,6 @@ }, /turf/open/floor/wood/tile, /area/centcom/syndicate_mothership/control) -"TH" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 10 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/centcom/syndicate_mothership/control) "TK" = ( /obj/structure/barricade/sandbags, /obj/effect/light_emitter{ @@ -4405,6 +4488,12 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/control) +"Uc" = ( +/obj/effect/turf_decal/tile/red/anticorner{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "Um" = ( /obj/machinery/button/door/directional/south{ id = "syn_ordmix_vent"; @@ -4457,10 +4546,28 @@ }, /turf/open/floor/plating/icemoon, /area/centcom/syndicate_mothership/control) +"UC" = ( +/obj/structure/chair/greyscale{ + dir = 4 + }, +/obj/effect/landmark/start/nukeop_base/overwatch, +/turf/open/floor/mineral/plastitanium, +/area/centcom/syndicate_mothership) "UE" = ( /obj/machinery/light/cold/directional/east, /turf/open/floor/plating, /area/centcom/syndicate_mothership/control) +"UH" = ( +/obj/effect/turf_decal/siding/wideplating/dark{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wideplating/dark, +/obj/machinery/door/airlock/hatch{ + name = "Gangway" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/mineral/plastitanium, +/area/centcom/syndicate_mothership/control) "Va" = ( /obj/effect/turf_decal/syndicateemblem/middle/left{ dir = 8 @@ -4481,6 +4588,13 @@ /obj/structure/flora/rock/pile/style_random, /turf/open/misc/asteroid/snow/icemoon, /area/centcom/syndicate_mothership/control) +"Vq" = ( +/obj/structure/chair/sofa/bench/right{ + dir = 8 + }, +/obj/structure/sign/poster/contraband/syndicate_pistol/directional/north, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "Vr" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 5 @@ -4545,12 +4659,15 @@ /obj/item/stack/sheet/mineral/silver/fifty, /turf/open/floor/mineral/titanium/tiled/yellow, /area/centcom/syndicate_mothership/expansion_chemicalwarfare) -"Wc" = ( -/obj/machinery/vending/coffee, +"Wb" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 4 }, -/turf/open/floor/mineral/titanium, +/turf/open/floor/catwalk_floor/iron_dark, /area/centcom/syndicate_mothership/control) "Wo" = ( /obj/effect/light_emitter{ @@ -4562,16 +4679,6 @@ "Wp" = ( /turf/open/floor/iron/smooth, /area/centcom/syndicate_mothership/control) -"Wr" = ( -/obj/structure/chair/sofa/bench/right{ - dir = 4 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, -/obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer5, -/turf/open/floor/catwalk_floor/titanium, -/area/centcom/syndicate_mothership/control) "Ws" = ( /obj/structure/flora/tree/pine/style_random, /obj/effect/light_emitter{ @@ -4580,9 +4687,16 @@ }, /turf/open/misc/asteroid/snow/airless, /area/centcom/syndicate_mothership) -"Wu" = ( -/obj/structure/extinguisher_cabinet/directional/west, -/turf/open/floor/iron/dark/textured_large, +"Wt" = ( +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/door/airlock/hatch{ + name = "Security Checkpoint" + }, +/turf/open/floor/plating, /area/centcom/syndicate_mothership/control) "Wz" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ @@ -4609,25 +4723,18 @@ }, /turf/open/misc/asteroid/snow/icemoon, /area/centcom/syndicate_mothership/control) -"WG" = ( -/obj/structure/chair/sofa/bench/right{ - dir = 8 +"WD" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 5 }, -/obj/structure/sign/poster/contraband/syndicate_pistol/directional/north, -/turf/open/floor/mineral/titanium, +/turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership/control) "WI" = ( /obj/structure/sign/poster/contraband/revolver/directional/south, /turf/open/floor/mineral/titanium, /area/centcom/syndicate_mothership/control) -"WR" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red{ - dir = 4 - }, -/obj/item/paper_bin, -/obj/item/pen, -/turf/open/floor/iron/dark/textured_large, +"WQ" = ( +/turf/open/floor/circuit/red/no_power, /area/centcom/syndicate_mothership/control) "WS" = ( /obj/structure/sign/poster/contraband/energy_swords/directional/north, @@ -4652,22 +4759,9 @@ /obj/structure/cable, /turf/open/floor/catwalk_floor/iron_dark, /area/centcom/syndicate_mothership/control) -"Xj" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/siding/red{ - dir = 1 - }, -/obj/machinery/recharger, -/turf/open/floor/iron/dark/textured_large, -/area/centcom/syndicate_mothership/control) "Xk" = ( /turf/open/floor/mineral/plastitanium/red, /area/centcom/syndicate_mothership) -"Xu" = ( -/obj/structure/chair/stool/directional/west, -/obj/effect/landmark/start/nukeop_base, -/turf/open/floor/wood/tile, -/area/centcom/syndicate_mothership/control) "Xv" = ( /obj/structure/table/reinforced/plastitaniumglass, /obj/effect/turf_decal/siding/thinplating_new/dark{ @@ -4748,12 +4842,6 @@ dir = 1 }, /area/centcom/syndicate_mothership/control) -"XZ" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 9 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/centcom/syndicate_mothership/control) "Yd" = ( /obj/machinery/camera/autoname/directional/south{ network = list("nukie") @@ -4795,6 +4883,15 @@ /obj/structure/cable, /turf/open/floor/catwalk_floor/iron_smooth, /area/centcom/syndicate_mothership/control) +"YM" = ( +/obj/effect/turf_decal/siding/red, +/obj/item/toy/nuke{ + pixel_x = -5; + pixel_y = 1 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/turf/open/floor/iron/dark/textured_large, +/area/centcom/syndicate_mothership/control) "YO" = ( /obj/effect/turf_decal/siding/wideplating/dark{ dir = 8 @@ -6512,7 +6609,7 @@ HW wW Kq sv -pS +UC fV Kq CX @@ -6939,7 +7036,7 @@ Pc ZZ DZ gE -my +HE uX Jc ek @@ -7552,7 +7649,7 @@ bF DZ al Gd -MU +RV YO DZ tL @@ -7652,7 +7749,7 @@ VK BD sO DZ -AV +jd mK er TS @@ -7757,7 +7854,7 @@ DZ OS TG jT -du +nV DZ Dy Wp @@ -7857,7 +7954,7 @@ VK GE DZ Ni -Xu +Fl mL BH DZ @@ -9382,16 +9479,16 @@ bW qw nw MP -ng +Ps DZ VK VK VK VK DZ -Ed -GI -IM +om +Cn +Og wG wG Te @@ -9484,16 +9581,16 @@ bW qw qw qw -ng +Ps hb TC FR TC TC hb -ZZ -Me -wc +qN +ux +ov wG AL DZ @@ -9586,20 +9683,20 @@ bW qw qw qw -ng +Ps qJ TC TC FR TC qJ -ZZ -Me -wc +qN +ux +ov wG wG DZ -Ja +Fo Ov DZ DZ @@ -9695,14 +9792,14 @@ Xv KE VK DZ -WG -ij -zH +Vq +ww +OF wG wG -ru -XZ -TH +qR +JE +oA Ov DZ Ox @@ -9797,14 +9894,14 @@ so uX zL DZ -fb -Wr -zH +wD +gu +OF wG wG -ru -we -rw +qR +WD +iU Ov DZ Ox @@ -9892,20 +9989,20 @@ bW qw qw qw -AN +xt uX uX uX uX uX RA -ZZ -Me -wc +qN +ux +ov wG lE DZ -Ja +Fo Ov DZ DZ @@ -9994,19 +10091,19 @@ bW qw qw qw -AN +xt LS Mn uX ZH LN DZ -Fp -go -as +nG +cY +Sz wG wG -wS +DQ DZ DZ DZ @@ -10106,12 +10203,11 @@ DZ DZ qp DZ -gB -gB -DZ -mz -Wc +NY +NY DZ +cC +HN DZ DZ DZ @@ -10119,6 +10215,7 @@ DZ DZ VK VK +VK Ov DZ XC @@ -10208,20 +10305,20 @@ DZ pK pg VK -ZZ -ZZ -dn +wX +SN +ih qN qN -qN -Wu -ov -or +zl +fU +UH zE sl Ov Ov Ov +Ov DZ Ox Ox @@ -10310,14 +10407,14 @@ DZ CM FN VK -ZZ -ZZ -IV -tv -WR -AO -iV -ov +AE +vB +vn +Le +Le +Le +mC +DZ DZ DZ DZ @@ -10412,14 +10509,13 @@ DZ DZ eg tL -bp -ZZ -IV -IL -Hs -Xj -iV -ov +cW +yb +qN +aS +CW +Dt +mC Cg DZ Ox @@ -10428,6 +10524,7 @@ Ox Ox Ox Ox +Ox sq Ox sU @@ -10511,20 +10608,20 @@ Ld ol zo VK -ZZ -ZZ -Me -ZZ -ZZ -IV -rb -au -LB -iV -ov -ah +qN +qN +ux +AE +yb +qN +YM +nI +oU +mC +KT DZ Ox +Ox sq sq Ox @@ -10613,18 +10710,17 @@ Tc Ib Ib en -xj -xj -Me -ZZ -ZZ -IV -Fm -Lk -tu -iV -ov -nD +Pp +Pp +KB +AE +yb +qN +eM +WQ +oH +mC +Jr DZ Ox Ox @@ -10633,6 +10729,7 @@ Ox Ox Ox Ox +Ox sU sU sU @@ -10715,21 +10812,21 @@ Ld XL RQ VK -ZZ -ZZ -Me -ZZ -ZZ -il -dV -dV -dV -lc -lo +MF +MF +Wb +AE +yb +qN +kf +KX +iz +mC ec DZ DZ Ox +Ox sU sU sU @@ -10817,21 +10914,21 @@ DZ DZ DZ DZ -DZ VK -Se -VK -ZZ -pr -oh -vv -Fq -oD -ov +Wt +SH +cW +Uc +FQ +JG +JG +JG +mC Nd gf DZ Ox +Ox sU sU sU @@ -10919,21 +11016,21 @@ DZ tJ HW HW -Zt VK qw VK -qv -pr -ya -PF -ya -oD -OF +rO +fr +JY +dV +dV +dV +Ne DZ DZ DZ Ox +Ox sU sU sU @@ -11021,21 +11118,21 @@ QM HW HW lj -HW VK qw VK DZ -VK -wb -wq -dw -VK -DZ +bS +fP +FE +FC +IA +uY DZ Ox Ox Ox +Ox sU sU sU @@ -11123,20 +11220,20 @@ HW HW HW HW -tJ VK Hv VK -Ho -VK -VK -VK -VK -VK -Zt -KU +uT +bS +pp +ya +PF +ya +Re +DZ Ye uT +Ox Ye sU sU @@ -11225,20 +11322,20 @@ nz Zt HW HW -HW VK qw VK -HW -QM -HW -Zt -HW -HW -lj -KU +uT +DZ +VK +wb +wq +dB +VK +DZ Ye uT +Ox Ye sU sU @@ -11327,18 +11424,18 @@ HW HW HW QM -Zt VK qw VK +uT Zt +VK +VK +VK +VK +VK HW -HW -HW -tJ -HW -HW -KU +zI KU Ye Ye @@ -11429,10 +11526,10 @@ uT uT uT uT -HW VK -vx +Ic VK +uT HW tJ HW @@ -11532,11 +11629,11 @@ uT uT uT uT -uT Du uT uT uT +uT HW QM HW diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index bed1a6b24ac..1b71b003872 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -169,6 +169,19 @@ #define HUD_XENOBIO_CONSOLE "xenobio_console" +#define HUD_TAC_MINIMAP "tac_minimap" +#define HUD_TAC_MINIMAP_DIMMER "tac_minimap_dimmer" +#define HUD_TAC_MINIMAP_Z_INDICATOR "tac_minimap_z_indicator" +#define HUD_TAC_MINIMAP_Z_INDICATOR_UP "tac_minimap_z_up" +#define HUD_TAC_MINIMAP_Z_INDICATOR_DOWN "tac_minimap_z_down" +#define HUD_TAC_MINIMAP_TOOL_RED "tac_minimap_tool_red" +#define HUD_TAC_MINIMAP_TOOL_YELLOW "tac_minimap_tool_yellow" +#define HUD_TAC_MINIMAP_TOOL_PURPLE "tac_minimap_tool_purple" +#define HUD_TAC_MINIMAP_TOOL_BLUE "tac_minimap_tool_blue" +#define HUD_TAC_MINIMAP_TOOL_ERASE "tac_minimap_tool_erase" +#define HUD_TAC_MINIMAP_TOOL_LABEL "tac_minimap_tool_label" +#define HUD_TAC_MINIMAP_TOOL_CLEAR "tac_minimap_tool_clear" + /* These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var. diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index 6bc5b96e0e0..4d7a26858a2 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -313,6 +313,10 @@ #define CURSE_LAYER 6 #define ECHO_LAYER 7 #define PARRY_LAYER 8 +#define MINIMAP_IMAGE_LAYER 9 +#define MINIMAP_BLIPS_LAYER 10 +#define MINIMAP_LOCATOR_LAYER 11 +#define MINIMAP_LABELS_LAYER 12 #define FOV_EFFECT_LAYER 100 diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm index 7feed196c75..449a0f7f5f4 100644 --- a/code/__DEFINES/logging.dm +++ b/code/__DEFINES/logging.dm @@ -144,6 +144,7 @@ #define LOG_CATEGORY_GAME_ACCESS "game-access" #define LOG_CATEGORY_GAME_BLOOD_WORM "game-blood-worm" #define LOG_CATEGORY_GAME_EMOTE "game-emote" +#define LOG_CATEGORY_GAME_MINIMAP_DRAWING "game-minimap-drawing" #define LOG_CATEGORY_GAME_INTERNET_REQUEST "game-internet-request" #define LOG_CATEGORY_GAME_OOC "game-ooc" #define LOG_CATEGORY_GAME_PRAYER "game-prayer" diff --git a/code/__DEFINES/minimap.dm b/code/__DEFINES/minimap.dm new file mode 100644 index 00000000000..05629ef5d0b --- /dev/null +++ b/code/__DEFINES/minimap.dm @@ -0,0 +1,62 @@ +///Converts the overworld x and y to minimap x and y values +#define MINIMAP_PIXEL_FROM_WORLD(val) (val*2-3) + +//actual size of a users screen in pixels +#define SCREEN_PIXEL_SIZE 480 + +//Drawing tool colors +#define TACMAP_DRAWING_RED "#ff0000" +#define TACMAP_DRAWING_YELLOW "#FFFF00" +#define TACMAP_DRAWING_PURPLE "#A020F0" +#define TACMAP_DRAWING_BLUE "#0000FF" + + +//Turf colours +#define TACMAP_BLACK "#111111d0" +#define TACMAP_SOLID "#ebe5e5ee" +#define TACMAP_DOOR "#451e5eee" +#define TACMAP_WINDOW "#525252d0" +#define TACMAP_FENCE "#8c2294ee" +#define TACMAP_LAVA "#db4206d0" +#define TACMAP_DIRT "#9c906dd0" +#define TACMAP_SHALE "#706955d0" +#define TACMAP_SNOW "#c4e3e9d0" +#define TACMAP_MARS_DIRT "#aa5f44d0" +#define TACMAP_ICE "#93cae0d0" +#define TACMAP_WATER "#94b0d59c" //lower opacity as its really bright + +//Area colours +//Departments +#define TACMAP_AREA_COMMAND COLOR_COMMAND_BLUE +#define TACMAP_AREA_CARGO COLOR_CARGO_BROWN +#define TACMAP_AREA_ENGINEERING COLOR_ENGINEERING_ORANGE +#define TACMAP_AREA_MEDICAL COLOR_MEDICAL_BLUE +#define TACMAP_AREA_SCIENCE COLOR_SCIENCE_PINK +#define TACMAP_AREA_SECURITY COLOR_SECURITY_RED +#define TACMAP_AREA_SERVICE COLOR_SERVICE_LIME +//General +#define TACMAP_AREA_MAINTENANCE COLOR_WEBSAFE_DARK_GRAY + +/// How much we multiply the drawn image by, and as a result the pixel coordinates +#define MINIMAP_PIXEL_MULTIPLIER 2 +/// Converts an icon pixel coordinate (from ICON_X/ICON_Y modifiers) to a world tile coordinate. +#define MINIMAP_ICON_TO_WORLD(icon_coord, minimap_min) ((minimap_min) + floor(((icon_coord) - 1) / MINIMAP_PIXEL_MULTIPLIER)) +/// Converts a world tile coordinate to a pixel_w/pixel_z offset for placing a blip on the minimap display. +#define MINIMAP_WORLD_TO_PIXEL(world_coord, minimap_min, half_size) (((world_coord) - (minimap_min)) * MINIMAP_PIXEL_MULTIPLIER + 1 - (half_size)) +#define COMSIG_MINIMAP_ADD(blip_tag) "minimap_add_" + blip_tag +#define COMSIG_MINIMAP_REMOVE(blip_tag) "minimap_remove_" + blip_tag +// sends a index of how much to change by +#define COMSIG_MINIMAP_CHANGE_Z_LEVEL "minimap_z_change" +#define COMSIG_MINIMAP_ACTION_TRIGGER "minimap_action_trigger" + #define COMSIG_MINIMAP_ACTION_TRIGGER_CANCEL (1<<0) + + +#define MINIMAP_BOMB_BLIP "nuke" +#define MINIMAP_NUKEDISK_BLIP "nuke_disk" +#define MINIMAP_NUKEOP_BLIP "nukeop" +#define MINIMAP_NUKEOP_BORG_BLIP "nukeop_borg" +#define MINIMAP_SYNDICATE_MECH_BLIP "syndicate_mech" +#define MINIMAP_SYNDIE_TURRET_BLIP "syndie_turret" +#define MINIMAP_LADDER_BLIP "ladder" +#define MINIMAP_STAIR_BLIP "stair" +#define MINIMAP_ANNOTATION_TAG_NUCLEAR "nuclear_ops" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 317b17c2d7e..59b12502d1c 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -501,6 +501,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_CLIFF_WALKER "cliff_walker" /// This means the user is currently holding/wearing a "tactical camouflage" item (like a potted plant). #define TRAIT_TACTICALLY_CAMOUFLAGED "tactically_camouflaged" +/// This means the user is allowed to draw on minimap holotables. +#define TRAIT_MINIMAP_TABLE_DRAW "minimap_table_draw" /// Gets double arcade prizes #define TRAIT_GAMERGOD "gamer-god" #define TRAIT_GIANT "giant" diff --git a/code/__HELPERS/logging/game.dm b/code/__HELPERS/logging/game.dm index 0affd00228b..52c1a2254f3 100644 --- a/code/__HELPERS/logging/game.dm +++ b/code/__HELPERS/logging/game.dm @@ -32,3 +32,7 @@ /proc/log_ghost_poll(text, list/data) logger.Log(LOG_CATEGORY_GAME_GHOST_POLLS, text, data) + +/// Logging for drawing on minimap +/proc/log_minimap_drawing(text, list/data) + logger.Log(LOG_CATEGORY_GAME_MINIMAP_DRAWING, text, data) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index ccb1945a924..fcd5753f613 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -320,6 +320,15 @@ GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH, if(var_source.vars.Find(A)) . += A +/// Converts a screen loc param to a x,y coordinate pixel on the screen. +/proc/params2screenpixel(scr_loc) + var/list/x_and_y = splittext(scr_loc, ",") + var/list/x_dirty = splittext(x_and_y[1], ":") + var/list/y_dirty = splittext(x_and_y[2], ":") + var/x = (text2num(x_dirty[1]) - 1) * ICON_SIZE_X + text2num(x_dirty[2]) + var/y = (text2num(y_dirty[1]) - 1) * ICON_SIZE_Y + text2num(y_dirty[2]) + return list(x, y) + //word of warning: using a matrix like this as a color value will simplify it back to a string after being set /proc/color_hex2color_matrix(string) var/length = length(string) diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 24127005b6e..61a0255dfaa 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -651,6 +651,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_XRAY_VISION" = TRAIT_XRAY_VISION, "TRAIT_NOGRAV_ALWAYS_DRIFT" = TRAIT_NOGRAV_ALWAYS_DRIFT, "TRAIT_SPEECH_BOOSTER" = TRAIT_SPEECH_BOOSTER, + "TRAIT_MINIMAP_TABLE_DRAW" = TRAIT_MINIMAP_TABLE_DRAW, "TRAIT_MINING_PARRYING" = TRAIT_MINING_PARRYING, "TRAIT_MINING_AOE_IMMUNE" = TRAIT_MINING_AOE_IMMUNE, "TRAIT_IGNORE_FIRE_PROTECTION" = TRAIT_IGNORE_FIRE_PROTECTION, diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index ee1aa3633d1..d25020206da 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -354,6 +354,13 @@ /mob/proc/RangedAttack(atom/A, modifiers) if(SEND_SIGNAL(src, COMSIG_MOB_ATTACK_RANGED, A, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN) return TRUE + A.RangedAttackOn(src, modifiers) + +/** + * Atom's version of RangedAttack, for when you want to do something when a mob clicks on this with more sanity than just Click() + */ +/atom/proc/RangedAttackOn(mob/attacker, list/modifiers) + return null /** * Ranged secondary attack diff --git a/code/_onclick/hud/screen_objects/screen_objects.dm b/code/_onclick/hud/screen_objects/screen_objects.dm index 11accd552f5..00341f67188 100644 --- a/code/_onclick/hud/screen_objects/screen_objects.dm +++ b/code/_onclick/hud/screen_objects/screen_objects.dm @@ -94,7 +94,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen) // I hate this place RegisterSignal(hud, COMSIG_QDELETING, PROC_REF(on_hud_delete)) /// Returns the mob this is being displayed to, if any -/atom/movable/screen/proc/get_mob() +/atom/movable/screen/proc/get_mob() as /mob return hud?.mymob /atom/movable/screen/proc/on_hud_delete(datum/source) diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index 114988a0f86..71516fdd24f 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -101,6 +101,9 @@ /// log game events /datum/config_entry/flag/log_game +/// log minimap drawing events +/datum/config_entry/flag/log_minimap_drawing + /// log mech data /datum/config_entry/flag/log_mecha diff --git a/code/datums/proximity_monitor/proximity_monitor.dm b/code/datums/proximity_monitor/proximity_monitor.dm index ec77ce2145a..f5e63733765 100644 --- a/code/datums/proximity_monitor/proximity_monitor.dm +++ b/code/datums/proximity_monitor/proximity_monitor.dm @@ -74,9 +74,10 @@ //Update the ignore_if_not_on_turf AddComponent(/datum/component/connect_range, host, loc_connections, current_range, ignore_if_not_on_turf) -/datum/proximity_monitor/proc/on_uncrossed() +/datum/proximity_monitor/proc/on_uncrossed(atom/source, atom/movable/gone, direction) //Used by the advanced subtype for effect fields. SIGNAL_HANDLER - return //Used by the advanced subtype for effect fields. + if(source != host) + hasprox_receiver?.OnProximityExit(gone) /datum/proximity_monitor/proc/on_entered(atom/source, atom/movable/arrived, turf/old_loc) SIGNAL_HANDLER diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 87104b8cd47..fd0f586b98d 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -12,6 +12,7 @@ plane = AREA_PLANE mouse_opacity = MOUSE_OPACITY_TRANSPARENT invisibility = INVISIBILITY_LIGHTING + tacmap_color = null /// List of all turfs currently inside this area as nested lists indexed by zlevel. /// Acts as a filtered version of area.contents For faster lookup @@ -137,6 +138,9 @@ /// Are shuttles allowed to dock in this area var/allow_shuttle_docking = FALSE + /// If TRUE, then this area will be skipped entirely by minimap rendering. + var/skip_minimap_rendering = FALSE + /** * A list of teleport locations * diff --git a/code/game/area/areas/away_content.dm b/code/game/area/areas/away_content.dm index 39d7ebce1db..7194a8494e4 100644 --- a/code/game/area/areas/away_content.dm +++ b/code/game/area/areas/away_content.dm @@ -11,6 +11,7 @@ Unused icons for new areas are "awaycontent1" ~ "awaycontent30" default_gravity = STANDARD_GRAVITY ambience_index = AMBIENCE_AWAY sound_environment = SOUND_ENVIRONMENT_ROOM + skip_minimap_rendering = TRUE /area/awaymission/museum name = "Nanotrasen Museum" diff --git a/code/game/area/areas/mining.dm b/code/game/area/areas/mining.dm index af047a00698..51f05402973 100644 --- a/code/game/area/areas/mining.dm +++ b/code/game/area/areas/mining.dm @@ -196,6 +196,7 @@ sound_environment = SOUND_AREA_ICEMOON ambient_buzz = 'sound/ambience/lavaland/magma.ogg' allow_shuttle_docking = TRUE + skip_minimap_rendering = TRUE /area/icemoon/surface name = "Icemoon" diff --git a/code/game/area/areas/misc.dm b/code/game/area/areas/misc.dm index ac66943d5d1..a922a1e147a 100644 --- a/code/game/area/areas/misc.dm +++ b/code/game/area/areas/misc.dm @@ -17,6 +17,7 @@ sound_environment = SOUND_AREA_SPACE ambient_buzz = null //Space is deafeningly quiet allow_shuttle_docking = TRUE + skip_minimap_rendering = TRUE /area/space/nearstation icon_state = "space_near" diff --git a/code/game/area/areas/ruins/_ruins.dm b/code/game/area/areas/ruins/_ruins.dm index 92fff19386d..f0adbe7eb6b 100644 --- a/code/game/area/areas/ruins/_ruins.dm +++ b/code/game/area/areas/ruins/_ruins.dm @@ -9,6 +9,7 @@ ambience_index = AMBIENCE_RUINS flags_1 = CAN_BE_DIRTY_1 sound_environment = SOUND_ENVIRONMENT_STONEROOM + skip_minimap_rendering = TRUE /area/ruin/unpowered always_unpowered = TRUE diff --git a/code/game/area/areas/station/cargo.dm b/code/game/area/areas/station/cargo.dm index 8e892efda95..430122cc769 100644 --- a/code/game/area/areas/station/cargo.dm +++ b/code/game/area/areas/station/cargo.dm @@ -3,6 +3,7 @@ icon_state = "quart" airlock_wires = /datum/wires/airlock/cargo sound_environment = SOUND_AREA_STANDARD_STATION + tacmap_color = COLOR_CARGO_BROWN /area/station/cargo/sorting name = "\improper Delivery Office" diff --git a/code/game/area/areas/station/command.dm b/code/game/area/areas/station/command.dm index 30f126dc42c..6cc80002aab 100644 --- a/code/game/area/areas/station/command.dm +++ b/code/game/area/areas/station/command.dm @@ -6,6 +6,7 @@ ) airlock_wires = /datum/wires/airlock/command sound_environment = SOUND_AREA_STANDARD_STATION + tacmap_color = TACMAP_AREA_COMMAND /area/station/command/bridge name = "\improper Bridge" diff --git a/code/game/area/areas/station/common.dm b/code/game/area/areas/station/common.dm index 1b6eba4dc25..641c43dfd41 100644 --- a/code/game/area/areas/station/common.dm +++ b/code/game/area/areas/station/common.dm @@ -87,6 +87,7 @@ mood_message = "I love being in the bar!" mood_trait = TRAIT_EXTROVERT sound_environment = SOUND_AREA_SMALL_SOFTFLOOR + tacmap_color = TACMAP_AREA_SERVICE /area/station/commons/fitness name = "\improper Fitness Room" diff --git a/code/game/area/areas/station/engineering.dm b/code/game/area/areas/station/engineering.dm index 3f046445385..04e27d738c4 100644 --- a/code/game/area/areas/station/engineering.dm +++ b/code/game/area/areas/station/engineering.dm @@ -3,6 +3,7 @@ ambience_index = AMBIENCE_ENGI airlock_wires = /datum/wires/airlock/engineering sound_environment = SOUND_AREA_LARGE_ENCLOSED + tacmap_color = TACMAP_AREA_ENGINEERING /area/station/engineering/circuit_workshop name = "\improper Circuit Workshop" @@ -150,6 +151,7 @@ icon_state = "construction" ambience_index = AMBIENCE_ENGI sound_environment = SOUND_AREA_STANDARD_STATION + tacmap_color = TACMAP_AREA_ENGINEERING /area/station/construction/mining/aux_base name = "Auxiliary Base Construction" diff --git a/code/game/area/areas/station/hallway.dm b/code/game/area/areas/station/hallway.dm index 12a5ba6816b..3c82c9b1bee 100644 --- a/code/game/area/areas/station/hallway.dm +++ b/code/game/area/areas/station/hallway.dm @@ -92,6 +92,7 @@ /area/station/hallway/secondary/service name = "\improper Service Hallway" icon_state = "hall_service" + tacmap_color = TACMAP_AREA_SERVICE /area/station/hallway/secondary/spacebridge name = "\improper Space Bridge" diff --git a/code/game/area/areas/station/maintenance.dm b/code/game/area/areas/station/maintenance.dm index a6fa76cd80e..84ce4032eb6 100644 --- a/code/game/area/areas/station/maintenance.dm +++ b/code/game/area/areas/station/maintenance.dm @@ -7,6 +7,7 @@ forced_ambience = TRUE ambient_buzz = 'sound/ambience/maintenance/source_corridor2.ogg' ambient_buzz_vol = 20 + tacmap_color = TACMAP_AREA_MAINTENANCE /* * Departmental Maintenance @@ -248,6 +249,7 @@ /area/station/maintenance/disposal/incinerator name = "\improper Incinerator" icon_state = "incinerator" + tacmap_color = TACMAP_AREA_ENGINEERING /area/station/maintenance/space_hut name = "\improper Space Hut" diff --git a/code/game/area/areas/station/medical.dm b/code/game/area/areas/station/medical.dm index 03bdc8eb5bf..a02e014a0c0 100644 --- a/code/game/area/areas/station/medical.dm +++ b/code/game/area/areas/station/medical.dm @@ -4,6 +4,7 @@ ambience_index = AMBIENCE_MEDICAL airlock_wires = /datum/wires/airlock/medbay sound_environment = SOUND_AREA_STANDARD_STATION + tacmap_color = TACMAP_AREA_MEDICAL /area/station/medical/abandoned name = "\improper Abandoned Medbay" @@ -12,6 +13,7 @@ 'sound/ambience/misc/signal.ogg', ) sound_environment = SOUND_AREA_SMALL_ENCLOSED + tacmap_color = TACMAP_AREA_MAINTENANCE /area/station/medical/medbay/central name = "Medbay Central" diff --git a/code/game/area/areas/station/science.dm b/code/game/area/areas/station/science.dm index b64e7efe75a..9954a500673 100644 --- a/code/game/area/areas/station/science.dm +++ b/code/game/area/areas/station/science.dm @@ -3,6 +3,7 @@ icon_state = "science" airlock_wires = /datum/wires/airlock/science sound_environment = SOUND_AREA_STANDARD_STATION + tacmap_color = TACMAP_AREA_SCIENCE /area/station/science/lobby name = "\improper Science Lobby" @@ -131,6 +132,7 @@ name = "\improper Ordnance Bomb Site" icon_state = "ord_boom" area_flags = BLOBS_ALLOWED | CULT_PERMITTED | NO_GRAVITY + skip_minimap_rendering = TRUE /area/station/science/ordnance/bomb/planet area_flags = /area/station/science/ordnance/bomb::area_flags & ~NO_GRAVITY diff --git a/code/game/area/areas/station/security.dm b/code/game/area/areas/station/security.dm index 3166f7733d9..22d3bb0de85 100644 --- a/code/game/area/areas/station/security.dm +++ b/code/game/area/areas/station/security.dm @@ -6,6 +6,7 @@ ambience_index = AMBIENCE_DANGER airlock_wires = /datum/wires/airlock/security sound_environment = SOUND_AREA_STANDARD_STATION + tacmap_color = TACMAP_AREA_SECURITY /area/station/security/office name = "\improper Security Office" diff --git a/code/game/area/areas/station/service.dm b/code/game/area/areas/station/service.dm index 35540656326..71e9421e3a5 100644 --- a/code/game/area/areas/station/service.dm +++ b/code/game/area/areas/station/service.dm @@ -1,5 +1,6 @@ /area/station/service airlock_wires = /datum/wires/airlock/service + tacmap_color = TACMAP_AREA_SERVICE /* * Bar/Kitchen Areas @@ -199,27 +200,34 @@ name = "\improper Abandoned Garden" icon_state = "abandoned_garden" sound_environment = SOUND_AREA_SMALL_ENCLOSED + tacmap_color = TACMAP_AREA_MAINTENANCE /area/station/service/kitchen/abandoned name = "\improper Abandoned Kitchen" icon_state = "abandoned_kitchen" + tacmap_color = TACMAP_AREA_MAINTENANCE /area/station/service/electronic_marketing_den name = "\improper Electronic Marketing Den" icon_state = "abandoned_marketing_den" + tacmap_color = TACMAP_AREA_MAINTENANCE /area/station/service/abandoned_gambling_den name = "\improper Abandoned Gambling Den" icon_state = "abandoned_gambling_den" + tacmap_color = TACMAP_AREA_MAINTENANCE /area/station/service/abandoned_gambling_den/gaming name = "\improper Abandoned Gaming Den" icon_state = "abandoned_gaming_den" + tacmap_color = TACMAP_AREA_MAINTENANCE /area/station/service/theater/abandoned name = "\improper Abandoned Theater" icon_state = "abandoned_theatre" + tacmap_color = TACMAP_AREA_MAINTENANCE /area/station/service/library/abandoned name = "\improper Abandoned Library" icon_state = "abandoned_library" + tacmap_color = TACMAP_AREA_MAINTENANCE diff --git a/code/game/area/areas/station/solars.dm b/code/game/area/areas/station/solars.dm index 569a7f0a169..d7765c6ee9b 100644 --- a/code/game/area/areas/station/solars.dm +++ b/code/game/area/areas/station/solars.dm @@ -77,6 +77,7 @@ /area/station/maintenance/solars name = "Solar Maintenance" icon_state = "yellow" + tacmap_color = TACMAP_AREA_ENGINEERING /area/station/maintenance/solars/port name = "Port Solar Maintenance" diff --git a/code/game/area/areas/station/telecomm.dm b/code/game/area/areas/station/telecomm.dm index adb4670b44b..46c644acfeb 100644 --- a/code/game/area/areas/station/telecomm.dm +++ b/code/game/area/areas/station/telecomm.dm @@ -15,6 +15,7 @@ 'sound/ambience/misc/ambimystery.ogg', ) airlock_wires = /datum/wires/airlock/engineering + tacmap_color = TACMAP_AREA_ENGINEERING /area/station/tcommsat/maints name = "\improper Telecomms Maintenance Room" diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index ad246f5ff82..d59f478a2db 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -147,6 +147,9 @@ /// Generally for niche objects, atoms blacklisted can spawn if enabled by spawner. var/spawn_blacklisted = FALSE + /// What color this shows up as on the tactical map + var/tacmap_color = TACMAP_SOLID + /** * Top level of the destroy chain for most atoms * @@ -438,6 +441,10 @@ /atom/proc/HasProximity(atom/movable/proximity_check_mob as mob|obj) return +/// has a previously nearby atom moved away +/atom/proc/OnProximityExit(atom/movable/proximity_check_mob as mob|obj) + return + /// Sets the wire datum of an atom /atom/proc/set_wires(datum/wires/new_wires) wires = new_wires diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 57dffa377e5..6bbab50fa79 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -28,6 +28,8 @@ idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.1 active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.2 + tacmap_color = TACMAP_DOOR + /// The animation we're currently playing, if any var/animation var/visible = TRUE diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 801ed06603c..f682219a06b 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -782,6 +782,19 @@ DEFINE_BITFIELD(turret_flags, list( . = ..() AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) AddElement(/datum/element/nav_computer_icon, 'icons/effects/nav_computer_indicators.dmi', "turret", FALSE) + add_minimap_blip(src, MINIMAP_SYNDIE_TURRET_BLIP, "sentry_passive") + +/obj/machinery/porta_turret/syndicate/proc/update_turret_minimap_icon(new_icon_state) + var/atom/movable/screen/minimap_element/blip/blip = get_minimap_blip(MINIMAP_SYNDIE_TURRET_BLIP, src) + if(isnull(blip)) + return + blip.icon_state = new_icon_state + +/obj/machinery/porta_turret/syndicate/shootAt(atom/movable/target) + . = ..() + if(raised && (obj_flags & EMAGGED || last_fired == world.time)) + update_turret_minimap_icon("sentry_firing") + addtimer(CALLBACK(src, PROC_REF(update_turret_minimap_icon), "sentry_passive"), shot_delay + 1 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) /obj/machinery/porta_turret/syndicate/setup() return diff --git a/code/game/objects/items/implants/implant_tacmap.dm b/code/game/objects/items/implants/implant_tacmap.dm new file mode 100644 index 00000000000..33ebbe88c08 --- /dev/null +++ b/code/game/objects/items/implants/implant_tacmap.dm @@ -0,0 +1,120 @@ +/obj/item/implant/tacmap + name = "tactical map implant" + desc = "provides you with a map" + actions_types = list(/datum/action/minimap) + var/wearer_icon_state = null + /// Optional z-trait that resolves to the first z-level and locks the minimap there. + var/minimap_fixed_z_trait + /// Whether this implant allows drawing/labeling on the personal minimap HUD. + var/can_draw_on_personal_minimap = FALSE + var/static/list/minimap_refresh_signals = list( + COMSIG_MOB_STATCHANGE, + COMSIG_LIVING_REVIVE, + COMSIG_MOB_GHOSTIZED, + ) + +/obj/item/implant/tacmap/implant(mob/living/target, mob/user, silent, force) + . = ..() + if(.) + configure_minimap_action() + RegisterSignals(target, minimap_refresh_signals, PROC_REF(refresh_minimap_icon)) + addtimer(CALLBACK(src, PROC_REF(update_minimap_icon), target), 0.1 SECONDS) // Mobs are spawned inside nullspace sometimes so this avoids that hijinks. + +/obj/item/implant/tacmap/removed(mob/living/source, silent, special) + UnregisterSignal(source, minimap_refresh_signals) + remove_minimap(source) + return ..() + +///Remove all action of type minimap from the wearer, and make him disappear from the minimap +/obj/item/implant/tacmap/proc/remove_minimap(mob/user) + remove_minimap_blip(MINIMAP_NUKEOP_BLIP, user) + +/obj/item/implant/tacmap/proc/refresh_minimap_icon() + SIGNAL_HANDLER + if(imp_in) + update_minimap_icon(imp_in) + +/obj/item/implant/tacmap/proc/resolve_fixed_minimap_z_level() + if(!isnull(minimap_fixed_z_trait)) + var/list/trait_levels = SSmapping.levels_by_trait(minimap_fixed_z_trait) + if(length(trait_levels)) + return trait_levels[1] + return null + +/obj/item/implant/tacmap/proc/configure_minimap_action() + var/datum/action/minimap/minimap_action = locate(/datum/action/minimap) in actions + if(isnull(minimap_action)) + return + minimap_action.fixed_z_level = resolve_fixed_minimap_z_level() + minimap_action.can_draw = can_draw_on_personal_minimap + +/obj/item/implant/tacmap/proc/get_minimap_icon_state(mob/living/wearer) + return wearer_icon_state + +///Updates the wearer's minimap icon +/obj/item/implant/tacmap/proc/update_minimap_icon(mob/wearer) + SIGNAL_HANDLER + remove_minimap_blip(MINIMAP_NUKEOP_BLIP, wearer) + add_minimap_blip(wearer, MINIMAP_NUKEOP_BLIP, get_minimap_icon_state(wearer)) + +/obj/item/implant/tacmap/nuclear // Nukie subtype, map shows you nuke disk, operatives, cayenne and the nuke + actions_types = list(/datum/action/minimap/nuclear) + wearer_icon_state = "syndicate" + +/obj/item/implant/tacmap/nuclear/implant(mob/living/target, mob/user, silent, force) + . = ..() + if(.) + RegisterSignal(target, COMSIG_MINIMAP_ACTION_TRIGGER, PROC_REF(deny_nukie_base_open)) + +/obj/item/implant/tacmap/nuclear/get_minimap_icon_state(mob/living/wearer) + if(wearer.stat != DEAD && istype(wearer, /mob/living/basic/carp/pet/cayenne)) + return "cayenne" + . = ..() + +/obj/item/implant/tacmap/nuclear/removed(mob/living/source, silent, special) + UnregisterSignal(source, COMSIG_MINIMAP_ACTION_TRIGGER) + return ..() + +/obj/item/implant/tacmap/nuclear/proc/deny_nukie_base_open(mob/living/user) + var/turf/user_turf = get_turf(user) + if(user_turf.onSyndieBase()) + user.balloon_alert(user, "can't use implant in the base, go to the holotable!") + return COMSIG_MINIMAP_ACTION_TRIGGER_CANCEL + +/obj/item/implant/tacmap/nuclear/cayenne // subtype used for cayenne and syndie sentience potions in general + wearer_icon_state = "cayenne" + +/obj/item/implant/tacmap/nuclear/leader // Leader subtype lets him draw on the map + actions_types = list(/datum/action/minimap/nuclear) + can_draw_on_personal_minimap = TRUE + wearer_icon_state = "syndicate_leader" + +/obj/item/implant/tacmap/nuclear/leader/implant(mob/living/target, mob/user, silent, force) + . = ..() + if(.) + ADD_TRAIT(target, TRAIT_MINIMAP_TABLE_DRAW, REF(src)) + +/obj/item/implant/tacmap/nuclear/leader/removed(mob/living/source, silent, special) + REMOVE_TRAIT(source, TRAIT_MINIMAP_TABLE_DRAW, REF(src)) + return ..() + +// Subtype that just lets them open it off-base. +/obj/item/implant/tacmap/nuclear/offbase + minimap_fixed_z_trait = ZTRAIT_STATION + can_draw_on_personal_minimap = TRUE + +/obj/item/implant/tacmap/nuclear/offbase/deny_nukie_base_open(mob/living/user) + return + +/obj/item/implanter/tacmap + name = "implanter (minimap)" + imp_type = /obj/item/implant/tacmap + +/obj/item/implanter/tacmap/nuclear + name = "implanter (operative minimap)" + imp_type = /obj/item/implant/tacmap/nuclear + +/obj/item/implantcase/tacmap + name = "implant case - 'Tactical Map'" + desc = "A glass case containing an implant with a virtual map." + imp_type = /obj/item/implant/tacmap diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index aff0ccc4e80..cd4baf7f1c9 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -764,6 +764,8 @@ new /obj/item/book/manual/nuclear(src) // Very important // The most important part of the kit, the implant that gives them the syndicate faction. new /obj/item/implanter/induction_implant(src) + // Tactical map implant so they can see the minimap with the rest of the team. + new /obj/item/implanter/tacmap/nuclear(src) // All in all, 6+3+3+2+5+2+4 = ~25 TC of 'miscellaneous' items. // This is a lot of value for 10 TC, but you have to keep in mind that you NEED someone to get this stuff station-side. // Pretty much all of it is a bad deal for reinforcements or yourself as they already have similar or good-enough alternatives. diff --git a/code/game/objects/structures/fence.dm b/code/game/objects/structures/fence.dm index 95c725868ca..f2f9d138df8 100644 --- a/code/game/objects/structures/fence.dm +++ b/code/game/objects/structures/fence.dm @@ -18,6 +18,7 @@ icon = 'icons/obj/fence.dmi' icon_state = "straight" + tacmap_color = TACMAP_FENCE var/cuttable = TRUE var/hole_size= NO_HOLE diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index 5d15c1af89f..88423eb182c 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -165,6 +165,7 @@ down.up = null down.update_appearance(UPDATE_ICON_STATE) + down.update_minimap_blip() down = null update_appearance(UPDATE_ICON_STATE) clear_base_transparency() @@ -188,6 +189,7 @@ up.down = null up.clear_base_transparency() up.update_appearance(UPDATE_ICON_STATE) + up.update_minimap_blip() up = null update_appearance(UPDATE_ICON_STATE) @@ -196,6 +198,11 @@ unlink_down() unlink_up() +/obj/structure/ladder/proc/update_minimap_blip() + remove_minimap_blip(MINIMAP_LADDER_BLIP, src) + if(up || down) + add_minimap_blip(src, MINIMAP_LADDER_BLIP, "ladder") + /obj/structure/ladder/LateInitialize() // By default, discover ladders above and below us vertically var/turf/base = get_turf(src) @@ -213,6 +220,7 @@ // Linking updates our icon, so if we failed both links we need a manual update if(isnull(down) && isnull(up)) update_appearance(UPDATE_ICON_STATE) + update_minimap_blip() /obj/structure/ladder/update_icon_state() icon_state = "[base_icon_state][!!up][!!down]" diff --git a/code/game/objects/structures/stairs.dm b/code/game/objects/structures/stairs.dm index 8d7e1fc84e1..0f037fec4d5 100644 --- a/code/game/objects/structures/stairs.dm +++ b/code/game/objects/structures/stairs.dm @@ -4,6 +4,8 @@ /// Range within which stair indicators will appear for approaching mobs #define STAIR_INDICATOR_RANGE 3 +/// Minimum tile spacing between stair minimap blips +#define STAIR_BLIP_MIN_DISTANCE 2 // dir determines the direction of travel to go upwards // stairs require /turf/open/openspace as the tile above them to work, unless your stairs have 'force_open_above' set to TRUE @@ -27,6 +29,8 @@ VAR_FINAL/turf/directly_above /// If TRUE, we have left/middle/right sprites. var/has_merged_sprites = TRUE + /// Current atoms used as this stair's minimap blip targets. + var/list/minimap_blip_targets /// Lazyassoc list of weakef to mob viewing stair indicators to their images VAR_PRIVATE/list/mob_to_image @@ -63,6 +67,7 @@ force_open_above() build_signal_listener() update_surrounding() + update_minimap_blip() var/static/list/exit_connections = list( COMSIG_ATOM_EXIT = PROC_REF(on_exit_stairs), @@ -78,6 +83,7 @@ /obj/structure/stairs/Destroy() + clear_minimap_blips() if(directly_above) UnregisterSignal(directly_above, COMSIG_TURF_MULTIZ_NEW) directly_above = null @@ -104,6 +110,47 @@ for(var/obj/structure/stairs/stair in get_step(src, turn(dir, -90))) stair.update_appearance() + update_minimap_blip() + +/obj/structure/stairs/proc/update_minimap_blip() + var/bottom_state = isTerminator() ? "stairs_up" : "stairs_down" + var/top_state = (bottom_state == "stairs_up") ? "stairs_down" : "stairs_up" + var/turf/current_turf = get_turf(src) + + clear_minimap_blips() + if(isnull(current_turf)) + return + + add_minimap_blip_if_valid(current_turf, bottom_state) + add_minimap_blip_if_valid(get_step_multiz(current_turf, UP), top_state) + +/obj/structure/stairs/proc/clear_minimap_blips() + if(!islist(minimap_blip_targets)) + return + for(var/atom/target as anything in minimap_blip_targets) + remove_minimap_blip(MINIMAP_STAIR_BLIP, target) + LAZYCLEARLIST(minimap_blip_targets) + +/obj/structure/stairs/proc/add_minimap_blip_if_valid(atom/target, state) + if(isnull(target)) + return + if(!should_place_minimap_blip(target)) + return + + var/atom/movable/screen/minimap_element/blip/blip = get_minimap_blip(MINIMAP_STAIR_BLIP, target) + if(!isnull(blip)) + blip.icon_state = state + else + add_minimap_blip(target, MINIMAP_STAIR_BLIP, state) + LAZYADD(minimap_blip_targets, target) + +/obj/structure/stairs/proc/should_place_minimap_blip(atom/target) + var/turf/target_turf = get_turf(target) + if(isnull(target_turf)) + return FALSE + if(length(get_minimap_blips_in_area(MINIMAP_STAIR_BLIP, target_turf, STAIR_BLIP_MIN_DISTANCE))) + return FALSE + return TRUE /obj/structure/stairs/update_icon_state() . = ..() @@ -420,3 +467,4 @@ #undef STAIR_TERMINATOR_YES #undef STAIR_INDICATOR_RANGE +#undef STAIR_BLIP_MIN_DISTANCE diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index cd54bd380f2..6ca6b22836c 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -18,6 +18,7 @@ flags_ricochet = RICOCHET_HARD receive_ricochet_chance_mod = 0.5 custom_materials = list(/datum/material/glass = SHEET_MATERIAL_AMOUNT) + tacmap_color = TACMAP_WINDOW var/state = WINDOW_OUT_OF_FRAME var/reinf = FALSE var/heat_resistance = 800 diff --git a/code/game/turfs/closed/_closed.dm b/code/game/turfs/closed/_closed.dm index c29772afc5b..09bd513be8e 100644 --- a/code/game/turfs/closed/_closed.dm +++ b/code/game/turfs/closed/_closed.dm @@ -9,6 +9,7 @@ init_air = FALSE rad_insulation = RAD_MEDIUM_INSULATION pass_flags_self = PASSCLOSEDTURF + tacmap_color = TACMAP_BLACK /turf/closed/AfterChange() . = ..() diff --git a/code/game/turfs/open/asteroid.dm b/code/game/turfs/open/asteroid.dm index c441871caa8..b8128820f8e 100644 --- a/code/game/turfs/open/asteroid.dm +++ b/code/game/turfs/open/asteroid.dm @@ -182,6 +182,7 @@ GLOBAL_LIST_EMPTY(dug_up_basalt) initial_gas_mix = LAVALAND_DEFAULT_ATMOS planetary_atmos = TRUE baseturfs = /turf/open/lava/smooth/lava_land_surface + skip_minimap_rendering = TRUE /// Used for the lavaland icemoon ruin. /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins @@ -393,6 +394,7 @@ GLOBAL_LIST_EMPTY(dug_up_basalt) baseturfs = /turf/open/openspace/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS slowdown = 0 + skip_minimap_rendering = TRUE /// Exact subtype as parent, just used in ruins to prevent other ruins/chasms from spawning on top of it. /turf/open/misc/asteroid/snow/icemoon/do_not_chasm diff --git a/code/game/turfs/open/floor/iron_floor.dm b/code/game/turfs/open/floor/iron_floor.dm index 6f0489acea5..7f7a5fa28c9 100644 --- a/code/game/turfs/open/floor/iron_floor.dm +++ b/code/game/turfs/open/floor/iron_floor.dm @@ -414,6 +414,7 @@ icon_state = "solarpanel" base_icon_state = "solarpanel" floor_tile = /obj/item/stack/tile/iron/solarpanel + skip_minimap_rendering = TRUE /turf/open/floor/iron/solarpanel/airless initial_gas_mix = AIRLESS_ATMOS diff --git a/code/game/turfs/open/floor/misc_floor.dm b/code/game/turfs/open/floor/misc_floor.dm index 61f2c76bc79..ae5ae6c3e9d 100644 --- a/code/game/turfs/open/floor/misc_floor.dm +++ b/code/game/turfs/open/floor/misc_floor.dm @@ -75,6 +75,9 @@ icon_state = "bcircuitoff" always_off = TRUE +/turf/open/floor/circuit/no_light + always_off = TRUE + /turf/open/floor/circuit/airless initial_gas_mix = AIRLESS_ATMOS @@ -120,6 +123,9 @@ icon_state = "rcircuitoff" always_off = TRUE +/turf/open/floor/circuit/red/no_power + always_off = TRUE + /turf/open/floor/circuit/red/anim icon_state = "rcircuitanim" floor_tile = /obj/item/stack/tile/circuit/red/anim diff --git a/code/game/turfs/open/ice.dm b/code/game/turfs/open/ice.dm index a966e8e4d7e..1a227d2a034 100644 --- a/code/game/turfs/open/ice.dm +++ b/code/game/turfs/open/ice.dm @@ -82,6 +82,7 @@ baseturfs = /turf/open/openspace/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS slowdown = 0 + skip_minimap_rendering = TRUE /turf/open/misc/ice/icemoon/no_planet_atmos planetary_atmos = FALSE diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index dcc735819f3..e4c447008da 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -71,6 +71,7 @@ GLOBAL_LIST_EMPTY(starlight) vis_flags = VIS_INHERIT_ID //when this be added to vis_contents of something it be associated with something on clicking, important for visualisation of turf in openspace and interraction with openspace that show you turf. force_no_gravity = TRUE + skip_minimap_rendering = TRUE /turf/open/space/basic icon_state = MAP_SWITCH("space", "space_basic_map") diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index b6a0b8c3867..4a98f911a04 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -113,6 +113,9 @@ GLOBAL_LIST_EMPTY(station_turfs) ///The typepath we use for lazy fishing on turfs, to save on world init time. var/fish_source + /// If TRUE, then this turf will be skipped entirely by minimap rendering. + var/skip_minimap_rendering = FALSE + /turf/vv_edit_var(var_name, new_value) var/static/list/banned_edits = list(NAMEOF_STATIC(src, x), NAMEOF_STATIC(src, y), NAMEOF_STATIC(src, z)) diff --git a/code/modules/antagonists/clown_ops/outfits.dm b/code/modules/antagonists/clown_ops/outfits.dm index 18016da7c4a..b66b2212445 100644 --- a/code/modules/antagonists/clown_ops/outfits.dm +++ b/code/modules/antagonists/clown_ops/outfits.dm @@ -18,7 +18,7 @@ /obj/item/mod/skin_applier/honkerative = 1, ) box = /obj/item/storage/box/survival/syndie - implants = list(/obj/item/implant/sad_trombone) + implants = list(/obj/item/implant/sad_trombone, /obj/item/implant/tacmap/nuclear) uplink_type = /obj/item/uplink/clownop @@ -33,3 +33,4 @@ command_radio = TRUE id_trim = /datum/id_trim/chameleon/operative/clown_leader + implants = list(/obj/item/implant/sad_trombone, /obj/item/implant/tacmap/nuclear/leader) diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm b/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm index 7e9aa464142..06a95d809d0 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm @@ -25,6 +25,7 @@ AddComponent(/datum/component/stationloving, !fake) AddComponent(/datum/component/keep_me_secure, CALLBACK(src, PROC_REF(secured_process)), CALLBACK(src, PROC_REF(unsecured_process)), 10) SSpoints_of_interest.make_point_of_interest(src) + add_minimap_blip(src, MINIMAP_NUKEDISK_BLIP, "green_disk_off", 'icons/ui_icons/minimap/map_blips_large.dmi', TRUE) else // Ensure fake disks still have examine text, but dont actually do anything AddComponent(/datum/component/keep_me_secure) diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm index 807f0e6e690..a00956e7c80 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm @@ -53,6 +53,8 @@ GLOBAL_VAR(station_nuke_source) var/proper_bomb = TRUE //Please /// A reference to the countdown that goes up over the nuke var/obj/effect/countdown/nuclearbomb/countdown + /// is this nuke on the MINIMAP_BOMB_BLIP tag minimap? + var/is_on_minimap = TRUE /obj/machinery/nuclearbomb/Initialize(mapload) . = ..() @@ -62,6 +64,7 @@ GLOBAL_VAR(station_nuke_source) update_appearance() SSpoints_of_interest.make_point_of_interest(src) previous_level = SSsecurity_level.get_current_level_as_text() + update_minimap_blip() /obj/machinery/nuclearbomb/Destroy() safety = FALSE @@ -523,6 +526,7 @@ GLOBAL_VAR(station_nuke_source) arm_nuke(usr) else disarm_nuke(usr) + update_minimap_blip() /// Arms the nuke, making it active and triggering all pinpointers to start counting down (+delta alert) /obj/machinery/nuclearbomb/proc/arm_nuke(mob/armer) @@ -565,6 +569,12 @@ GLOBAL_VAR(station_nuke_source) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NUKE_DEVICE_DISARMED, src) update_appearance() +/obj/machinery/nuclearbomb/proc/update_minimap_blip() + if(!is_on_minimap) + return + var/blip_icon = 'icons/ui_icons/minimap/map_blips_large.dmi' + add_minimap_blip(src, MINIMAP_BOMB_BLIP, "nuke_[timing ? "on" : "off"]", blip_icon, TRUE) + /// If the nuke is active, gets how much time is left until it detonates, in seconds. /// If the nuke is not active, gets how much time the nuke is set for, in seconds. /obj/machinery/nuclearbomb/proc/get_time_left() diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/beer_nuke.dm b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/beer_nuke.dm index 66798ae798c..7bef615c806 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/beer_nuke.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/beer_nuke.dm @@ -3,6 +3,7 @@ name = "\improper Nanotrasen-brand nuclear fission explosive" desc = "One of the more successful achievements of the Nanotrasen Corporate Warfare Division, their nuclear fission explosives are renowned for being cheap to produce and devastatingly effective. Signs explain that though this particular device has been decommissioned, every Nanotrasen station is equipped with an equivalent one, just in case. All Captains carefully guard the disk needed to detonate them - at least, the sign says they do. There seems to be a tap on the back." proper_bomb = FALSE + is_on_minimap = FALSE /// The keg located within the beer nuke. var/obj/structure/reagent_dispensers/beerkeg/keg /// Reagent that is produced once the nuke detonates. diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm index 74402a2cd06..ce7cadba7a5 100644 --- a/code/modules/antagonists/nukeop/outfits.dm +++ b/code/modules/antagonists/nukeop/outfits.dm @@ -13,6 +13,11 @@ skillchips = list(/obj/item/skillchip/disk_verifier) box = /obj/item/storage/box/survival/syndie + implants = list( + /obj/item/implant/weapons_auth, + /obj/item/implant/explosive, + /obj/item/implant/tacmap/nuclear, + ) /// Amount of TC to automatically store in this outfit's uplink. var/tc = 25 /// Enables big voice on this outfit's headset, used for nukie leaders. @@ -33,6 +38,12 @@ name = "Syndicate Leader - Basic" command_radio = TRUE + implants = list( + /obj/item/implant/weapons_auth, + /obj/item/implant/explosive, + /obj/item/implant/tacmap/nuclear/leader, + ) + id_trim = /datum/id_trim/chameleon/operative/nuke_leader /datum/outfit/syndicate/leader/plasmaman @@ -84,6 +95,11 @@ /datum/outfit/syndicate/full/loneop name = "Syndicate Operative - Full Kit (Loneop)" uplink_type = /obj/item/uplink/loneop + implants = list( + /obj/item/implant/weapons_auth, + /obj/item/implant/explosive, + /obj/item/implant/tacmap/nuclear/leader, + ) /datum/outfit/syndicate/full/plasmaman name = "Syndicate Operative - Full Kit (Plasmaman)" @@ -213,3 +229,8 @@ command_radio = TRUE tc = 0 uplink_type = null + implants = list( + /obj/item/implant/weapons_auth, + /obj/item/implant/explosive, + /obj/item/implant/tacmap/nuclear/offbase, + ) diff --git a/code/modules/logging/categories/log_category_game.dm b/code/modules/logging/categories/log_category_game.dm index fced988c1fc..a5be914e6d2 100644 --- a/code/modules/logging/categories/log_category_game.dm +++ b/code/modules/logging/categories/log_category_game.dm @@ -66,3 +66,7 @@ category = LOG_CATEGORY_GAME_BLOOD_WORM config_flag = /datum/config_entry/flag/log_blood_worm master_category = /datum/log_category/game + +/datum/log_category/minimap_drawing + category = LOG_CATEGORY_GAME_MINIMAP_DRAWING + master_category = /datum/log_category/game diff --git a/code/modules/minimap/_minimap.dm b/code/modules/minimap/_minimap.dm new file mode 100644 index 00000000000..e864b080f56 --- /dev/null +++ b/code/modules/minimap/_minimap.dm @@ -0,0 +1,45 @@ +GLOBAL_ALIST_EMPTY(minimap_blip_tags) +GLOBAL_ALIST_EMPTY(minimap_annotations) +GLOBAL_LIST_EMPTY(minimap_annotation_viewers) + +/// Create a minimap blip on the z-level in question, object is optional, and will tie the blip to the object in question, and will clean up itself if the object in question is deleted +/proc/add_minimap_blip(atom/object, tag, icon_state, icon = 'icons/ui_icons/minimap/map_blips.dmi', large = FALSE, layer = 12) + if(!istype(object) || !tag || !icon_state) + CRASH("Invalid params passed in to add_minimap_blip") + var/atom/movable/screen/minimap_element/blip/new_blip = new(null, null, object, icon_state, icon, large, tag) + new_blip.layer = layer + LAZYADD(GLOB.minimap_blip_tags[tag], new_blip) + SEND_GLOBAL_SIGNAL(COMSIG_MINIMAP_ADD(tag), new_blip) + +/proc/get_minimap_blip(tag, atom/object) + if(!tag || !istype(object)) + return + for(var/atom/movable/screen/minimap_element/blip/blip as anything in GLOB.minimap_blip_tags[tag]) + if(blip.track_target == object) + return blip + +/proc/remove_minimap_blip(tag, atom/object) + var/atom/movable/screen/minimap_element/blip/blip = get_minimap_blip(tag, object) + if(isnull(blip)) + return + SEND_GLOBAL_SIGNAL(COMSIG_MINIMAP_REMOVE(tag), blip) + LAZYREMOVE(GLOB.minimap_blip_tags[tag], blip) + qdel(blip) + +/// Returns minimap blips matching a tag that are within `distance` tiles of `target_turf` on the same z-level. +/proc/get_minimap_blips_in_area(tag, turf/target_turf, distance) + if(!tag || isnull(target_turf) || !isnum(distance) || !islist(GLOB.minimap_blip_tags[tag])) + return list() + + var/list/nearby_blips = list() + for(var/atom/movable/screen/minimap_element/blip/blip as anything in GLOB.minimap_blip_tags[tag]) + var/turf/blip_turf = get_turf(blip.track_target) + if(isnull(blip_turf)) + continue + if(blip_turf.z != target_turf.z) + continue + if(get_dist(blip_turf, target_turf) > distance) + continue + nearby_blips += blip + + return nearby_blips diff --git a/code/modules/minimap/hud/minimal_z_level.dm b/code/modules/minimap/hud/minimal_z_level.dm new file mode 100644 index 00000000000..af6071b49dc --- /dev/null +++ b/code/modules/minimap/hud/minimal_z_level.dm @@ -0,0 +1,68 @@ +/atom/movable/screen/minimap_z_indicator + icon = 'icons/hud/screen_ai.dmi' + icon_state = "zindicator" + screen_loc = "BOTTOM+4,RIGHT" + +/atom/movable/screen/minimap_z_indicator/Initialize(mapload, datum/hud/hud_owner) + . = ..() + if(!isnull(hud_owner.mymob)) + RegisterSignal(hud_owner.mymob, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_z_level_change)) + RegisterSignal(hud_owner.mymob, COMSIG_MINIMAP_CHANGE_Z_LEVEL, PROC_REF(on_minimap_change_request)) + var/current_turf = get_turf(hud_owner.mymob) + on_z_level_change(null, current_turf, FALSE) + +///sets the currently indicated relative floor +/atom/movable/screen/minimap_z_indicator/proc/on_z_level_change(turf/old_turf, turf/new_turf, same_z_layer) + SIGNAL_HANDLER + var/used_z = get_displayed_z_level(new_turf) + set_floor_text(used_z) + +/atom/movable/screen/minimap_z_indicator/proc/on_minimap_change_request(mob/hud_owner, new_z_change) + SIGNAL_HANDLER + var/atom/movable/screen/minimap_display/current_display = hud?.screen_objects[HUD_TAC_MINIMAP] + if(isnull(current_display)) + var/current_turf = get_turf(hud_owner) + on_z_level_change(null, current_turf, FALSE) + return + var/current_z = current_display.get_viewed_z_level() + if(isnull(current_z)) + return + var/requested_z = current_display.get_clamped_connected_z(current_z + new_z_change, current_z) + set_floor_text(requested_z) + +/atom/movable/screen/minimap_z_indicator/proc/get_displayed_z_level(turf/current_turf) + var/atom/movable/screen/minimap_display/current_display = hud?.screen_objects[HUD_TAC_MINIMAP] + if(!isnull(current_display?.fixed_z_level)) + return current_display.minimap?.z + return current_turf?.z + +/atom/movable/screen/minimap_z_indicator/proc/set_floor_text(used_z) + if(isnull(used_z)) + return + var/bottom_z = used_z + while(SSmapping.multiz_levels?[bottom_z]?[Z_LEVEL_DOWN]) // just keep going down + bottom_z-- + var/text = "Floor
[(used_z - bottom_z) + 1]" + maptext = MAPTEXT_TINY_UNICODE("
[text]
") + +/atom/movable/screen/minimap_z_up + name = "go up" + icon = 'icons/hud/screen_ai.dmi' + icon_state = "up" + mouse_over_pointer = MOUSE_HAND_POINTER + screen_loc = "BOTTOM+4,RIGHT-1" + +/atom/movable/screen/minimap_z_up/Click(location, control, params) + flick("uppressed", src) + SEND_SIGNAL(hud.mymob, COMSIG_MINIMAP_CHANGE_Z_LEVEL, 1) // +1 z level + +/atom/movable/screen/minimap_z_down + name = "go down" + icon = 'icons/hud/screen_ai.dmi' + icon_state = "down" + mouse_over_pointer = MOUSE_HAND_POINTER + screen_loc = "BOTTOM+4,RIGHT-1" + +/atom/movable/screen/minimap_z_down/Click(location, control, params) + flick("downpressed", src) + SEND_SIGNAL(hud.mymob, COMSIG_MINIMAP_CHANGE_Z_LEVEL, -1) // -1 z level diff --git a/code/modules/minimap/hud/minimap_dimmer.dm b/code/modules/minimap/hud/minimap_dimmer.dm new file mode 100644 index 00000000000..bdd759d86cc --- /dev/null +++ b/code/modules/minimap/hud/minimap_dimmer.dm @@ -0,0 +1,7 @@ +/// Fullscreen dimmer used while the tactical minimap is open. +/// Rendered below HUD planes so minimap and normal HUD icons remain undimmed. +/atom/movable/screen/fullscreen/dimmer/minimap + alpha = 180 + plane = FULLSCREEN_PLANE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + clear_with_screen = TRUE diff --git a/code/modules/minimap/hud/minimap_display.dm b/code/modules/minimap/hud/minimap_display.dm new file mode 100644 index 00000000000..611bb51f30f --- /dev/null +++ b/code/modules/minimap/hud/minimap_display.dm @@ -0,0 +1,585 @@ +#define MINIMAP_LABEL_REMOVE_PIXEL_RANGE 5 + +/// Screen object that renders a [/datum/minimap] base map icon on the HUD. +/atom/movable/screen/minimap_display + name = "Minimap" + icon_state = "" + layer = MINIMAP_IMAGE_LAYER + screen_loc = "1,1" + var/list/origin_px + var/atom/movable/screen/minimap_element/drawing/drawing + /// Optional group tag. Displays with the same tag share drawings and labels. + var/annotation_share_tag + /// Unified list of currently visible minimap elements (drawings, labels, blips, screentip). + var/list/atom/movable/screen/minimap_element/visible_minimap_elements = list() + /// A reference to the minimap used for this display. + var/datum/minimap/minimap + /// Screentext in vis_contents used for the maptext. + var/atom/movable/screen/minimap_element/label/screentip + /// Named blips indexed by name (added via add_blip()). Tagged blips are rebuilt from globals on z-level change. + var/list/atom/movable/screen/minimap_element/blip/blips = list() + /// The list of minimap blip tags we're going to read from the globalist and listen for additions to + var/list/valid_minimap_blip_tags = list() + /// fixed z-level to stay on + var/fixed_z_level + /// Y-axis offset for drawing to account for mouse cursor icon positioning. + var/draw_offset_y = -3 + /// Whether this minimap instance allows drawing and labels. + var/can_draw = TRUE + /// list of signals we want to keep tied on the hud owner mob + var/list/hud_signals = list( + COMSIG_MOVABLE_Z_CHANGED = PROC_REF(on_z_level_change), + COMSIG_MINIMAP_CHANGE_Z_LEVEL = PROC_REF(z_change_request) + ) + /// Maps HUD key → button type path. Used to create/remove toolbar buttons via [/datum/hud]. + var/static/list/toolbar_button_types = list( + HUD_TAC_MINIMAP_TOOL_RED = /atom/movable/screen/minimap_toolbar_button/draw/red, + HUD_TAC_MINIMAP_TOOL_YELLOW = /atom/movable/screen/minimap_toolbar_button/draw/yellow, + HUD_TAC_MINIMAP_TOOL_PURPLE = /atom/movable/screen/minimap_toolbar_button/draw/purple, + HUD_TAC_MINIMAP_TOOL_BLUE = /atom/movable/screen/minimap_toolbar_button/draw/blue, + HUD_TAC_MINIMAP_TOOL_ERASE = /atom/movable/screen/minimap_toolbar_button/erase, + HUD_TAC_MINIMAP_TOOL_LABEL = /atom/movable/screen/minimap_toolbar_button/label, + HUD_TAC_MINIMAP_TOOL_CLEAR = /atom/movable/screen/minimap_toolbar_button/clear, + ) + /// Currently active toolbar button (the active tool). + var/atom/movable/screen/minimap_toolbar_button/active_button = null + /// string for the locator blip's tag + var/locator_blip_tag = "locator" + +/atom/movable/screen/minimap_display/Initialize(mapload, datum/hud/hud_owner, datum/minimap/minimap, list/minimap_blip_tags, initial_fixed_z_level, annotation_share_tag, can_draw = TRUE) + src.can_draw = can_draw + . = ..() + if(isnull(minimap)) + CRASH("[type] created without a minimap reference!") + src.annotation_share_tag = isnull(annotation_share_tag) ? "[type]" : annotation_share_tag + LAZYOR(GLOB.minimap_annotation_viewers[src.annotation_share_tag], src) + if(!isnull(initial_fixed_z_level)) + fixed_z_level = initial_fixed_z_level + INVOKE_ASYNC(src, PROC_REF(apply_fixed_z_minimap), initial_fixed_z_level) + if(length(minimap_blip_tags)) + valid_minimap_blip_tags = minimap_blip_tags.Copy() + set_minimap(minimap) + screentip = new + show_minimap_element(screentip) + if(length(valid_minimap_blip_tags)) + for(var/blip_tag in valid_minimap_blip_tags) + RegisterSignal(SSdcs, COMSIG_MINIMAP_ADD(blip_tag), PROC_REF(on_tagged_blip_add)) + RegisterSignal(SSdcs, COMSIG_MINIMAP_REMOVE(blip_tag), PROC_REF(on_tagged_blip_remove)) + on_z_level_change(hud_owner.mymob) + show_tagged_blips() + +/atom/movable/screen/minimap_display/proc/apply_fixed_z_minimap(target_z) + if(QDELETED(src) || isnull(target_z) || fixed_z_level != target_z) + return + var/datum/minimap/fixed_minimap = get_minimap_for_z(target_z) + if(QDELETED(src) || isnull(fixed_minimap) || fixed_z_level != target_z) + return + set_minimap(fixed_minimap) + +/atom/movable/screen/minimap_display/Destroy() + set_cursor_icon(null) + if(active_button) + active_button.on_deactivate() + active_button = null + var/mob/owner = get_mob() + if(hud) + for(var/key in toolbar_button_types) + hud.remove_screen_object(key, update = FALSE) + if(owner) + for(var/signal in hud_signals) + UnregisterSignal(owner, signal, hud_signals[signal]) + if(owner?.client) + UnregisterSignal(owner.client, COMSIG_CLIENT_MOUSEUP) + if(length(GLOB.minimap_annotation_viewers[annotation_share_tag])) + GLOB.minimap_annotation_viewers[annotation_share_tag] -= src + minimap = null + drawing = null + visible_minimap_elements.Cut() + annotation_share_tag = null + QDEL_NULL(screentip) + if(length(valid_minimap_blip_tags)) + for(var/blip_tag in valid_minimap_blip_tags) + UnregisterSignal(SSdcs, COMSIG_MINIMAP_ADD(blip_tag)) + UnregisterSignal(SSdcs, COMSIG_MINIMAP_REMOVE(blip_tag)) + remove_all_blips() + + return ..() + +/atom/movable/screen/minimap_display/set_new_hud(datum/hud/hud_owner) + var/mob/old_owner = get_mob() + if(hud) + for(var/key in toolbar_button_types) + hud.remove_screen_object(key, update = FALSE) + if(old_owner) + for(var/signal in hud_signals) + UnregisterSignal(old_owner, signal, hud_signals[signal]) + if(old_owner?.client) + UnregisterSignal(old_owner.client, COMSIG_CLIENT_MOUSEUP) + . = ..() + var/mob/new_owner = get_mob() + if(new_owner) + for(var/signal in hud_signals) + RegisterSignal(new_owner, signal, hud_signals[signal]) + if(new_owner?.client) + RegisterSignal(new_owner.client, COMSIG_CLIENT_MOUSEUP, PROC_REF(on_client_mouseup)) + if(can_draw) + for(var/hud_key, hud_type in toolbar_button_types) + var/atom/movable/screen/minimap_toolbar_button/button = new hud_type(null, hud_owner, src) + button.tool_key = hud_key + hud_owner.add_screen_object(button, hud_key, HUD_GROUP_STATIC, update_screen = FALSE) + reposition_toolbar_buttons() + hud_owner.show_hud(hud_owner.hud_version) + +/atom/movable/screen/minimap_display/Click(location, control, params) + if(..() || usr != get_mob()) + return + var/list/modifiers = params2list(params) + var/icon_x = text2num(LAZYACCESS(modifiers, ICON_X)) + var/icon_y = text2num(LAZYACCESS(modifiers, ICON_Y)) + var/right_click = LAZYACCESS(modifiers, RIGHT_CLICK) + + if(active_button && active_button.on_click(icon_x, icon_y, right_click)) + return + +/atom/movable/screen/minimap_display/proc/remove_nearest_label(icon_x, icon_y, mob/user) + var/list/labels_for_z = get_or_create_annotation_list(/atom/movable/screen/minimap_element/label, minimap.z) + if(!length(labels_for_z)) + return + var/atom/movable/screen/minimap_element/label/nearest + var/nearest_dist_sq + for(var/atom/movable/screen/minimap_element/label/label as anything in labels_for_z) + var/dx = label.pixel_w - icon_x + var/dy = label.pixel_z - icon_y + var/dist_sq = (dx * dx) + (dy * dy) + if(dist_sq > (MINIMAP_LABEL_REMOVE_PIXEL_RANGE * MINIMAP_LABEL_REMOVE_PIXEL_RANGE)) + continue + if(isnull(nearest_dist_sq) || dist_sq < nearest_dist_sq) + nearest_dist_sq = dist_sq + nearest = label + if(isnull(nearest)) + return + labels_for_z -= nearest + hide_minimap_element(nearest) + qdel(nearest) + sync_visible_objects(minimap?.z) + log_minimap_drawing("[key_name(user)] removed a minimap label") + +/atom/movable/screen/minimap_display/MouseEntered(location, control, params) + MouseMove(location, control, params) + +/atom/movable/screen/minimap_display/MouseDrag(over_object, src_location, over_location, src_control, over_control, params) + if(usr != get_mob()) + return + if(!active_button) + return + var/list/modifiers = params2list(params) + var/list/mouse_px = params2screenpixel(LAZYACCESS(modifiers, SCREEN_LOC)) + if(length(mouse_px) != 2) + return + var/x = mouse_px[1] - origin_px[1] + 1 + var/y = mouse_px[2] - origin_px[2] + 1 + active_button.on_mouse_drag(x, y) + +/atom/movable/screen/minimap_display/proc/on_client_mouseup(client/source) + SIGNAL_HANDLER + if(active_button) + active_button.on_mouse_up() + +/atom/movable/screen/minimap_display/MouseMove(location, control, params) + if(usr != get_mob()) + return + var/list/modifiers = params2list(params) + var/icon_x = text2num(LAZYACCESS(modifiers, ICON_X)) + var/icon_y = text2num(LAZYACCESS(modifiers, ICON_Y)) + + var/x = clamp(MINIMAP_ICON_TO_WORLD(icon_x, minimap.min_x), 1, world.maxx) + var/y = clamp(MINIMAP_ICON_TO_WORLD(icon_y, minimap.min_y), 1, world.maxy) + var/hover_text = get_hover_text(x, y) + screentip.maptext = MAPTEXT_TINY_UNICODE("[hover_text]") + screentip.pixel_w = icon_x + screentip.pixel_z = icon_y + +/atom/movable/screen/minimap_display/proc/get_hover_text(x, y) + var/closest_blip_name + var/closest_blip_distance + for(var/atom/movable/screen/minimap_element/blip/blip in visible_minimap_elements) + if(isnull(blip.track_target) || blip.track_target.z != minimap.z) + continue + if(!length(blip.name)) + continue + var/hover_range = blip.large ? 2 : 1 + var/x_distance = abs(blip.track_target.x - x) + var/y_distance = abs(blip.track_target.y - y) + if(x_distance > hover_range || y_distance > hover_range) + continue + var/distance = x_distance + y_distance + if(isnull(closest_blip_distance) || distance < closest_blip_distance) + closest_blip_distance = distance + closest_blip_name = blip.name + + if(!isnull(closest_blip_name)) + return closest_blip_name + + var/area_name = minimap.map_position_to_name["[x]:[y]"] + if(isnull(area_name)) + var/turf/hovered_loc = locate(x, y, minimap.z) + area_name = "[hovered_loc?.loc?.name]" + minimap.map_position_to_name["[x]:[y]"] = area_name + return area_name + +/atom/movable/screen/minimap_display/MouseExited(location, control, params) + if(usr != get_mob()) + return + screentip.maptext = "" + if(active_button) + active_button.on_mouse_up() + +/atom/movable/screen/minimap_display/proc/on_z_level_change(mob/source) + SIGNAL_HANDLER + var/turf/mob_loc = get_turf(source) + if(!mob_loc || mob_loc.z != minimap.z) + if(isnull(fixed_z_level)) + INVOKE_ASYNC(src, PROC_REF(resolve_and_change_z_level), mob_loc.z) + return + remove_blip(locator_blip_tag) + return + add_blip(locator_blip_tag, "locator", mob_loc.x, mob_loc.y, layer = 15) + + +/atom/movable/screen/minimap_display/proc/resolve_and_change_z_level(new_z) + if(isnull(new_z)) + return + var/datum/minimap/new_minimap = get_minimap_for_z(new_z) + if(QDELETED(src) || isnull(new_minimap)) + return + change_z_level(new_z, new_minimap) + +/atom/movable/screen/minimap_display/proc/change_z_level(new_z, datum/minimap/new_minimap) + if(isnull(new_minimap)) + return + if(!isnull(fixed_z_level)) + fixed_z_level = new_z + set_minimap(new_minimap) + +/atom/movable/screen/minimap_display/proc/set_fixed_z_level(new_fixed_z, apply_immediately = FALSE) + fixed_z_level = new_fixed_z + if(apply_immediately) + INVOKE_ASYNC(src, PROC_REF(resolve_and_change_z_level), new_fixed_z) + +/atom/movable/screen/minimap_display/proc/show_tagged_blips() + if(!length(valid_minimap_blip_tags)) + return + for(var/blip_flag in valid_minimap_blip_tags) + var/blip_list = GLOB.minimap_blip_tags[blip_flag] + if(!blip_list) + continue + for(var/atom/movable/screen/minimap_element/blip/blip as anything in blip_list) + on_tagged_blip_add(null, blip) + +/atom/movable/screen/minimap_display/proc/on_tagged_blip_add(datum/source, atom/movable/screen/minimap_element/blip/blip) + SIGNAL_HANDLER + if(isnull(blip) || QDELETED(blip) || isnull(minimap)) + return + if(!(blip.blip_tag in valid_minimap_blip_tags)) + return + if(isnull(blip.track_target)) + return + var/turf/blip_turf = get_turf(blip.track_target) + if(blip_turf?.z != minimap.z) + return + blip.start_tracking_target() + show_minimap_element(blip) + +/atom/movable/screen/minimap_display/proc/on_tagged_blip_remove(datum/source, atom/movable/screen/minimap_element/blip/blip) + SIGNAL_HANDLER + if(isnull(blip)) + return + hide_minimap_element(blip) + +/atom/movable/screen/minimap_display/proc/set_minimap(datum/minimap/minimap) + if(isnull(minimap)) + return + icon = minimap.base_map + var/map_w = minimap.base_map.Width() + var/map_h = minimap.base_map.Height() + var/screen_size = get_screen_pixel_size() + var/map_offset_y = 32 + screen_loc = "1:[screen_size / 2 - map_w / 2],1:[screen_size / 2 - map_h / 2 - map_offset_y]" + origin_px = params2screenpixel(screen_loc) + src.minimap = minimap + refresh_visible_annotations() + screentip?.maptext = "" + clear_tagged_blips() + show_tagged_blips() + reposition_toolbar_buttons() + +/// adds a local blip that's not added to the global list +/atom/movable/screen/minimap_display/proc/add_blip(name, icon_state, x, y, large = FALSE, layer = 12) + if(blips[name]) + return + var/atom/movable/screen/minimap_element/blip/new_blip = new(null, null, get_mob(), icon_state, large) + new_blip.layer = layer + new_blip.start_tracking_target() + blips[name] = new_blip + show_minimap_element(new_blip) + +/atom/movable/screen/minimap_display/proc/update_blip(name, x, y) + var/atom/movable/screen/minimap_element/blip/blip = blips[name] + if(!blip) + return + var/half_size = blip.large ? 5 : 3 + blip.pixel_w = MINIMAP_WORLD_TO_PIXEL(x, minimap.min_x, half_size) + blip.pixel_z = MINIMAP_WORLD_TO_PIXEL(y, minimap.min_y, half_size) + +/atom/movable/screen/minimap_display/proc/remove_blip(name) + var/atom/movable/screen/minimap_element/blip/blip = blips[name] + if(!blip) + return + blips -= name + hide_minimap_element(blip) + qdel(blip) + +/atom/movable/screen/minimap_display/proc/remove_all_blips() + for(var/blip_name in blips) + var/atom/movable/screen/minimap_element/blip/blip = blips[blip_name] + hide_minimap_element(blip) + qdel(blip) + blips.Cut() + hide_visible_elements_by_type(/atom/movable/screen/minimap_element/blip) + +/atom/movable/screen/minimap_display/proc/z_change_request(mob/hud_owner, new_z_change) + SIGNAL_HANDLER + var/current_z = get_viewed_z_level() + var/new_z = get_clamped_connected_z(current_z + new_z_change, current_z) + INVOKE_ASYNC(src, PROC_REF(resolve_and_change_z_level), new_z) + +/atom/movable/screen/minimap_display/proc/get_viewed_z_level() + if(!isnull(fixed_z_level)) + return fixed_z_level + return minimap?.z + +/atom/movable/screen/minimap_display/proc/get_clamped_connected_z(requested_z, source_z) + if(isnull(source_z)) + return requested_z + var/list/connected_levels = SSmapping.get_connected_levels(source_z) + if(!length(connected_levels)) + return requested_z + if(requested_z in connected_levels) + return requested_z + var/closest_z = connected_levels[1] + var/closest_distance = abs(closest_z - requested_z) + for(var/connected_z in connected_levels) + var/current_distance = abs(connected_z - requested_z) + if(current_distance < closest_distance) + closest_z = connected_z + closest_distance = current_distance + return closest_z + +/// Activates a toolbar button as the active tool. +/atom/movable/screen/minimap_display/proc/activate_button(atom/movable/screen/minimap_toolbar_button/button) + if(!button) + return + + // Deselect if clicking the same button + if(active_button == button) + deactivate_button() + return + + deactivate_button() + + active_button = button + button.on_activate() + update_toolbar_button_states() + +/// Deactivates the current tool button. +/atom/movable/screen/minimap_display/proc/deactivate_button() + if(active_button) + active_button.on_deactivate() + active_button = null + update_toolbar_button_states() + +/// Sets the mouse cursor icon for the HUD client. Pass null to reset to default. +/atom/movable/screen/minimap_display/proc/set_cursor_icon(icon/cursor_icon) + var/mob/owner = get_mob() + if(owner?.client) + owner.client.mouse_pointer_icon = cursor_icon + +/// Calculates the actual screen pixel size based on the client's view +/atom/movable/screen/minimap_display/proc/get_screen_pixel_size() + var/mob/owner = get_mob() + if(!owner?.client) + return SCREEN_PIXEL_SIZE // fallback to constant if no client + var/list/view_pixels = view_to_pixels(owner.client.view_size.getView()) + // Return the maximum dimension (typically square, but handle non-square views) + return max(view_pixels[1], view_pixels[2]) + +/atom/movable/screen/minimap_display/proc/update_toolbar_button_states() + if(!hud) + return + for(var/hud_key in toolbar_button_types) + var/atom/movable/screen/minimap_toolbar_button/button = hud.screen_objects[hud_key] + if(button) + button.update_active_state() + +/atom/movable/screen/minimap_display/proc/reposition_toolbar_buttons() + if(!hud || !minimap) + return + // origin_px[1] is the minimap's left edge; place toolbar one icon-width to its left. + var/btn_x = origin_px[1] - ICON_SIZE_X - 4 + if(btn_x < 0) + btn_x = origin_px[1] + minimap.base_map.Width() + 4 // fall back to right side + // Toolbar is vertically centered relative to the minimap's current position. + var/screen_size = get_screen_pixel_size() + var/toolbar_h = length(toolbar_button_types) * ICON_SIZE_Y + var/map_center_y = origin_px[2] + minimap.base_map.Height() / 2 + var/btn_top_y = clamp(map_center_y + toolbar_h / 2, toolbar_h, screen_size) + for(var/key in toolbar_button_types) + var/atom/movable/screen/minimap_toolbar_button/button = hud.screen_objects[key] + if(button) + button.screen_loc = "1:[btn_x],1:[btn_top_y - ICON_SIZE_Y - button.button_slot * ICON_SIZE_Y]" + +/atom/movable/screen/minimap_display/proc/clear_canvas(mob/user) + if(!can_draw) + return + drawing.clear_canvas(minimap?.base_map) + log_minimap_drawing("[key_name(user)] cleared the minimap canvas on z-level [minimap?.z]") + to_chat(user, span_warning("Cleared all minimap drawings.")) + +/atom/movable/screen/minimap_display/proc/clear_all_annotations(mob/user, annotation_type = /atom/movable/screen/minimap_element/label, annotation_type_name = "label") + var/alist/annotation_store = GLOB.minimap_annotations[annotation_share_tag] + var/alist/items_by_z = annotation_store?[annotation_type] + if(isnull(items_by_z)) + return + var/current_z = get_viewed_z_level() + var/list/items = items_by_z[current_z] + if(!length(items)) + return + QDEL_LIST(items) + items_by_z[current_z] = list() + refresh_visible_annotations() + sync_visible_objects(current_z) + var/user_name = user ? key_name(user) : "System" + to_chat(user, span_warning("Cleared all [annotation_type_name] annotations on z-level [current_z].")) + log_minimap_drawing("[user_name] has cleared all [annotation_type_name] annotations on z-level [current_z]") + +/atom/movable/screen/minimap_display/proc/async_place_label(mob/user, icon_x, icon_y) + var/x = clamp(MINIMAP_ICON_TO_WORLD(icon_x, minimap.min_x), 1, world.maxx) + var/y = clamp(MINIMAP_ICON_TO_WORLD(icon_y, minimap.min_y), 1, world.maxy) + var/area_name = minimap.map_position_to_name["[x]:[y]"] + if(isnull(area_name)) + var/turf/hovered_loc = locate(x, y, minimap.z) + area_name = "[hovered_loc?.loc?.name]" + minimap.map_position_to_name["[x]:[y]"] = area_name + var/label_text = tgui_input_text(user, "What would you like the label at [area_name] to say?", "Add Label", max_length = 25) + if(!label_text || QDELETED(src)) + return + var/list/filter_result = is_ic_filtered(label_text) + if(filter_result) + to_chat(user, span_warning("That label contained a word prohibited in IC chat! Consider reviewing the server rules.\n\"[label_text]\"")) + SSblackbox.record_feedback("tally", "ic_blocked_words", 1, LOWER_TEXT(config.ic_filter_regex.match)) + REPORT_CHAT_FILTER_TO_USER(src, filter_result) + log_filter("IC", label_text, filter_result) + return + var/atom/movable/screen/minimap_element/label/new_label = new + new_label.icon = 'icons/ui_icons/minimap/map_blips.dmi' + new_label.icon_state = "label" + new_label.maptext_x = 5 + new_label.maptext_y = 5 + new_label.maptext_width = 64 + new_label.maptext = MAPTEXT_TINY_UNICODE("[label_text]") + var/icon/label_icon = icon(new_label.icon, new_label.icon_state) + var/half_width = round(label_icon.Width() / 2) + var/half_height = round(label_icon.Height() / 2) + new_label.pixel_w = MINIMAP_WORLD_TO_PIXEL(x, minimap.min_x, half_width) + new_label.pixel_z = MINIMAP_WORLD_TO_PIXEL(y, minimap.min_y, half_height) + var/list/labels_for_z = get_or_create_annotation_list(/atom/movable/screen/minimap_element/label, minimap.z) + labels_for_z += new_label + sync_visible_objects(minimap?.z) + log_minimap_drawing("[key_name(user)] placed label '[label_text]' at [area_name]") + +/atom/movable/screen/minimap_display/proc/get_or_create_annotation_list(annotation_type, z_level) + var/alist/annotation_store = GLOB.minimap_annotations[annotation_share_tag] + if(isnull(annotation_store)) + annotation_store = alist() + GLOB.minimap_annotations[annotation_share_tag] = annotation_store + var/alist/by_z = annotation_store[annotation_type] + if(isnull(by_z)) + by_z = alist() + annotation_store[annotation_type] = by_z + var/list/items = by_z[z_level] + if(isnull(items)) + items = list() + by_z[z_level] = items + return items + +/atom/movable/screen/minimap_display/proc/refresh_visible_annotations() + if(isnull(minimap)) + return + var/list/drawings = get_or_create_annotation_list(/atom/movable/screen/minimap_element/drawing, minimap.z) + var/atom/movable/screen/minimap_element/drawing/target_drawing = length(drawings) ? drawings[1] : null + if(isnull(target_drawing)) + target_drawing = new + target_drawing.clear_canvas(minimap.base_map) + drawings += target_drawing + if(drawing != target_drawing) + if(!isnull(drawing)) + hide_minimap_element(drawing) + drawing = target_drawing + show_minimap_element(drawing) + + hide_visible_elements_by_type(/atom/movable/screen/minimap_element/label) + var/list/labels_for_z = get_or_create_annotation_list(/atom/movable/screen/minimap_element/label, minimap.z) + if(length(labels_for_z)) + show_minimap_elements(labels_for_z) + show_minimap_element(screentip) + +/atom/movable/screen/minimap_display/proc/sync_visible_objects(z_level) + if(isnull(z_level)) + return + var/list/displays_for_tag = GLOB.minimap_annotation_viewers[annotation_share_tag] + if(!length(displays_for_tag)) + return + for(var/atom/movable/screen/minimap_display/display as anything in displays_for_tag) + if(QDELETED(display) || display.minimap?.z != z_level) + continue + display.refresh_visible_annotations() + +/atom/movable/screen/minimap_display/proc/show_minimap_element(atom/movable/screen/minimap_element/element) + if(isnull(element)) + return + if(!(element in visible_minimap_elements)) + visible_minimap_elements += element + vis_contents |= element + +/atom/movable/screen/minimap_display/proc/hide_minimap_element(atom/movable/screen/minimap_element/element) + if(isnull(element)) + return + visible_minimap_elements -= element + vis_contents -= element + +/atom/movable/screen/minimap_display/proc/show_minimap_elements(list/elements) + for(var/atom/movable/screen/minimap_element/element as anything in elements) + show_minimap_element(element) + +/atom/movable/screen/minimap_display/proc/hide_minimap_elements(list/elements) + for(var/atom/movable/screen/minimap_element/element as anything in elements) + hide_minimap_element(element) + +/atom/movable/screen/minimap_display/proc/hide_visible_elements_by_type(element_type) + if(isnull(element_type)) + return + for(var/atom/movable/screen/minimap_element/element as anything in visible_minimap_elements.Copy()) + if(istype(element, element_type)) + hide_minimap_element(element) + +/atom/movable/screen/minimap_display/proc/clear_tagged_blips() + for(var/atom/movable/screen/minimap_element/blip/blip as anything in visible_minimap_elements.Copy()) + if(!length(blip.blip_tag)) + continue + hide_minimap_element(blip) + +/atom/movable/screen/minimap_display/nuclear + annotation_share_tag = MINIMAP_ANNOTATION_TAG_NUCLEAR + valid_minimap_blip_tags = list(MINIMAP_BOMB_BLIP, MINIMAP_NUKEDISK_BLIP, MINIMAP_NUKEOP_BLIP, MINIMAP_NUKEOP_BORG_BLIP, MINIMAP_SYNDICATE_MECH_BLIP, MINIMAP_SYNDIE_TURRET_BLIP, MINIMAP_LADDER_BLIP, MINIMAP_STAIR_BLIP) + +#undef MINIMAP_LABEL_REMOVE_PIXEL_RANGE diff --git a/code/modules/minimap/hud/minimap_drawing.dm b/code/modules/minimap/hud/minimap_drawing.dm new file mode 100644 index 00000000000..11c81089c85 --- /dev/null +++ b/code/modules/minimap/hud/minimap_drawing.dm @@ -0,0 +1,59 @@ + +/atom/movable/screen/minimap_element/drawing + icon = 'icons/ui_icons/minimap/minimap.dmi' + +/atom/movable/screen/minimap_element/drawing/proc/clear_canvas(icon/base_map) + var/icon/new_icon = icon('icons/ui_icons/minimap/minimap.dmi') + if(base_map) + new_icon.Scale(base_map.Width(), base_map.Height()) + icon = new_icon + +/atom/movable/screen/minimap_element/drawing/proc/draw_box(box_color, start_x, start_y, end_x, end_y, erase_pixel_range = 0, erase_padding_multiplier = 0) + var/icon/new_icon = icon(src.icon) + if(!isnull(box_color) || !erase_padding_multiplier) + new_icon.DrawBox(box_color, start_x, start_y, end_x, end_y) + else + var/padding = erase_pixel_range * erase_padding_multiplier + new_icon.DrawBox(box_color, start_x - padding, start_y - padding, end_x + padding, end_y + padding) + icon = new_icon + +// Unapologetically yoinked from /proc/get_line() +/atom/movable/screen/minimap_element/drawing/proc/draw_line(line_color, x0, y0, x1, y1, erase_pixel_range = 0, erase_padding_multiplier = 0) + var/icon/canvas = icon(src.icon) + var/current_x = x0 + var/current_y = y0 + + var/x_distance = x1 - current_x + var/y_distance = y1 - current_y + + var/abs_x_distance = abs(x_distance) + var/abs_y_distance = abs(y_distance) + + var/x_distance_sign = sign(x_distance) + var/y_distance_sign = sign(y_distance) + + var/cx = abs_x_distance >> 1 + var/cy = abs_y_distance >> 1 + + // draw the start pixel + var/padding = isnull(line_color) && erase_padding_multiplier ? erase_pixel_range * erase_padding_multiplier : 0 + canvas.DrawBox(line_color, current_x - padding, current_y - padding, current_x + 1 + padding, current_y + 1 + padding) + + if(abs_x_distance >= abs_y_distance) + for(var/i in 0 to (abs_x_distance - 1)) + cy += abs_y_distance + if(cy >= abs_x_distance) + cy -= abs_x_distance + current_y += y_distance_sign + current_x += x_distance_sign + canvas.DrawBox(line_color, current_x - padding, current_y - padding, current_x + 1 + padding, current_y + 1 + padding) + else + for(var/i in 0 to (abs_y_distance - 1)) + cx += abs_x_distance + if(cx >= abs_y_distance) + cx -= abs_y_distance + current_x += x_distance_sign + current_y += y_distance_sign + canvas.DrawBox(line_color, current_x - padding, current_y - padding, current_x + 1 + padding, current_y + 1 + padding) + + src.icon = canvas diff --git a/code/modules/minimap/hud/minimap_element.dm b/code/modules/minimap/hud/minimap_element.dm new file mode 100644 index 00000000000..f146f61bf34 --- /dev/null +++ b/code/modules/minimap/hud/minimap_element.dm @@ -0,0 +1,12 @@ +/atom/movable/screen/minimap_element + name = "unknown" + layer = MINIMAP_LABELS_LAYER + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + vis_flags = VIS_INHERIT_PLANE + /// the tag this blip is associated via in it's stored globalist + var/blip_tag = "" + +/atom/movable/screen/minimap_element/Destroy() + if(blip_tag) + LAZYREMOVE(GLOB.minimap_blip_tags[blip_tag], src) + return ..() diff --git a/code/modules/minimap/hud/minimap_label.dm b/code/modules/minimap/hud/minimap_label.dm new file mode 100644 index 00000000000..e7515ab0c88 --- /dev/null +++ b/code/modules/minimap/hud/minimap_label.dm @@ -0,0 +1,6 @@ + +/atom/movable/screen/minimap_element/label + name = "label" + maptext = "" + maptext_width = 96 + maptext_height = 96 diff --git a/code/modules/minimap/hud/minimap_toolbar.dm b/code/modules/minimap/hud/minimap_toolbar.dm new file mode 100644 index 00000000000..c32ecb3979c --- /dev/null +++ b/code/modules/minimap/hud/minimap_toolbar.dm @@ -0,0 +1,198 @@ +#define MINIMAP_TOOLBAR_ERASE_RANGE 5 + +/atom/movable/screen/minimap_toolbar_button + icon = 'icons/ui_icons/minimap/minimap_buttons.dmi' + icon_state = "draw" + mouse_over_pointer = MOUSE_HAND_POINTER + /// The minimap display this button controls. + var/atom/movable/screen/minimap_display/display + /// Vertical slot index (0 = topmost). Used by reposition_toolbar_buttons to calculate screen_loc. + var/button_slot = 0 + /// Mouse cursor icon set when this button's tool is active. null = default cursor. + var/icon/mouse_icon = null + /// Draw color this button represents. null = erase mode. + var/draw_color = null + /// HUD key for this tool button. Used to track selection state. + var/tool_key = null + /// Coordinates of the last drag position during drawing. + var/last_drag_x + var/last_drag_y + +/atom/movable/screen/minimap_toolbar_button/Initialize(mapload, datum/hud/hud_owner, atom/movable/screen/minimap_display/minimap_display) + . = ..() + display = minimap_display + +/atom/movable/screen/minimap_toolbar_button/Destroy() + display = null + return ..() + +/atom/movable/screen/minimap_toolbar_button/MouseEntered(location, control, params) + add_filter("mouseover", 1, outline_filter(1, COLOR_LIME)) + if(desc) + openToolTip(usr, tip_src = display || src, params = params, title = name, content = desc) + +/atom/movable/screen/minimap_toolbar_button/MouseExited(location, control, params) + remove_filter("mouseover") + if(desc) + closeToolTip(usr) + +/// Returns TRUE if this button should be shown as active. +/atom/movable/screen/minimap_toolbar_button/proc/is_active() + return display && display.active_button == src + +/// Updates the button's visual state to show if it's active. +/atom/movable/screen/minimap_toolbar_button/proc/update_active_state() + if(is_active()) + add_filter("active", 1, outline_filter(2, COLOR_YELLOW)) + else + remove_filter("active") + +/// Called when this button is activated as the active tool. +/atom/movable/screen/minimap_toolbar_button/proc/on_activate() + display?.set_cursor_icon(mouse_icon) + +/// Called when this button is deactivated. +/atom/movable/screen/minimap_toolbar_button/proc/on_deactivate() + display?.set_cursor_icon(null) + last_drag_x = null + last_drag_y = null + +/// Called during mouse drag on the map. Override to implement tool behavior. +/atom/movable/screen/minimap_toolbar_button/proc/on_mouse_drag(x, y) + return FALSE + +/// Called on mouse up. Override to clean up tool state. +/atom/movable/screen/minimap_toolbar_button/proc/on_mouse_up() + last_drag_x = null + last_drag_y = null + +/// Called on click. Override to implement click behavior like label placement. +/atom/movable/screen/minimap_toolbar_button/proc/on_click(icon_x, icon_y, right_click) + return FALSE + +/atom/movable/screen/minimap_toolbar_button/draw + desc = "Left-drag on the map to draw." + +/atom/movable/screen/minimap_toolbar_button/draw/on_mouse_drag(x, y) + if(isnull(display) || isnull(display.drawing)) + return FALSE + var/icon_width = display.minimap?.base_map?.Width() + var/icon_height = display.minimap?.base_map?.Height() + if(isnull(icon_width) || isnull(icon_height)) + return FALSE + if(!ISINRANGE(x, 1, icon_width) || !ISINRANGE(y, 1, icon_height)) + last_drag_x = null + last_drag_y = null + return FALSE + + if(last_drag_x && last_drag_y) + display.drawing.draw_line(draw_color, last_drag_x, last_drag_y + display.draw_offset_y, x, y + display.draw_offset_y, 0, 1) + last_drag_x = x + last_drag_y = y + else + display.drawing.draw_box(draw_color, x, y + display.draw_offset_y, x + 1, y + 1 + display.draw_offset_y, 0, 1) + last_drag_x = x + last_drag_y = y + return TRUE + +/atom/movable/screen/minimap_toolbar_button/draw/Click(location, control, params) + if(usr == get_mob()) + display?.activate_button(src) + +/atom/movable/screen/minimap_toolbar_button/draw/red + button_slot = 0 + color = TACMAP_DRAWING_RED + draw_color = TACMAP_DRAWING_RED + mouse_icon = 'icons/ui_icons/minimap/minimap_mouse/draw_red.dmi' + +/atom/movable/screen/minimap_toolbar_button/draw/yellow + button_slot = 1 + color = TACMAP_DRAWING_YELLOW + draw_color = TACMAP_DRAWING_YELLOW + mouse_icon = 'icons/ui_icons/minimap/minimap_mouse/draw_yellow.dmi' + +/atom/movable/screen/minimap_toolbar_button/draw/purple + button_slot = 2 + color = TACMAP_DRAWING_PURPLE + draw_color = TACMAP_DRAWING_PURPLE + mouse_icon = 'icons/ui_icons/minimap/minimap_mouse/draw_purple.dmi' + +/atom/movable/screen/minimap_toolbar_button/draw/blue + button_slot = 3 + color = TACMAP_DRAWING_BLUE + draw_color = TACMAP_DRAWING_BLUE + mouse_icon = 'icons/ui_icons/minimap/minimap_mouse/draw_blue.dmi' + +/// Erase tool — left-drag on the map to erase a line. +/atom/movable/screen/minimap_toolbar_button/erase + icon_state = "erase" + button_slot = 4 + desc = "Left-drag on the map to erase." + mouse_icon = 'icons/ui_icons/minimap/minimap_mouse/draw_erase.dmi' + +/atom/movable/screen/minimap_toolbar_button/erase/on_mouse_drag(x, y) + if(isnull(display) || isnull(display.drawing)) + return FALSE + var/icon_width = display.minimap?.base_map?.Width() + var/icon_height = display.minimap?.base_map?.Height() + if(isnull(icon_width) || isnull(icon_height)) + return FALSE + if(!ISINRANGE(x, 1, icon_width) || !ISINRANGE(y, 1, icon_height)) + last_drag_x = null + last_drag_y = null + return FALSE + + if(last_drag_x && last_drag_y) + display.drawing.draw_line(null, last_drag_x, last_drag_y + display.draw_offset_y, x, y + display.draw_offset_y, MINIMAP_TOOLBAR_ERASE_RANGE, 1) + last_drag_x = x + last_drag_y = y + else + display.drawing.draw_box(null, x, y + display.draw_offset_y, x + 1, y + 1 + display.draw_offset_y, MINIMAP_TOOLBAR_ERASE_RANGE, 1) + last_drag_x = x + last_drag_y = y + return TRUE + +/atom/movable/screen/minimap_toolbar_button/erase/Click(location, control, params) + if(usr == get_mob()) + display?.activate_button(src) + +/// Clear tool — removes all drawings and labels. +/atom/movable/screen/minimap_toolbar_button/clear + icon_state = "clear" + button_slot = 5 + desc = "Clear all drawings." + +/atom/movable/screen/minimap_toolbar_button/clear/is_active() + return FALSE + +/atom/movable/screen/minimap_toolbar_button/clear/Click(location, control, params) + if(usr == get_mob()) + display?.clear_canvas(usr) + +/// Label tool — click the map to place labels, right-click a label to remove it, right-click this button to clear all labels. +/atom/movable/screen/minimap_toolbar_button/label + icon_state = "label" + button_slot = 6 + desc = "Toggle label mode. Click the map to place a label. Right-click a nearby label on the map to remove it. Right-click this button to clear all labels." + mouse_icon = 'icons/ui_icons/minimap/minimap_mouse/label.dmi' + +/atom/movable/screen/minimap_toolbar_button/label/on_click(icon_x, icon_y, right_click) + if(isnull(display)) + return FALSE + if(right_click) + display.remove_nearest_label(icon_x, icon_y, usr) + return TRUE + // Place label asynchronously + INVOKE_ASYNC(display, /atom/movable/screen/minimap_display/proc/async_place_label, usr, icon_x, icon_y) + return TRUE + +/atom/movable/screen/minimap_toolbar_button/label/Click(location, control, params) + if(usr != get_mob()) + return + var/list/modifiers = params2list(params) + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + display.clear_all_annotations(usr, /atom/movable/screen/minimap_element/label) + else + display?.activate_button(src) + +#undef MINIMAP_TOOLBAR_ERASE_RANGE diff --git a/code/modules/minimap/hud/minimap_tracking_blip.dm b/code/modules/minimap/hud/minimap_tracking_blip.dm new file mode 100644 index 00000000000..d7c2d19433c --- /dev/null +++ b/code/modules/minimap/hud/minimap_tracking_blip.dm @@ -0,0 +1,90 @@ +/atom/movable/screen/minimap_element/blip + icon = 'icons/ui_icons/minimap/map_blips.dmi' + /// Is this a large blip? causes different pixel offsets to be applied + var/large = FALSE + /// Minimap datum for the current z-level this blip is on + var/datum/minimap/minimap + /// If we are tracking our target or not, to ensure we do not re-register multiple times + var/tracking = FALSE + /// what target we're essentially owned by, and will cause this blip to cleanup if it gets deleted + var/atom/track_target + /// Weak reference to connect_containers so container movement updates this blip. + var/datum/weakref/connect_ref + +/atom/movable/screen/minimap_element/blip/Initialize(mapload, datum/hud/hud_owner, atom/track_target, icon_state, icon, large = FALSE, blip_tag) + . = ..() + src.icon_state = icon_state + src.large = large + if(icon) + src.icon = icon + if(track_target) + register_target(track_target) + if(blip_tag) + src.blip_tag = blip_tag + +/atom/movable/screen/minimap_element/blip/Destroy() + clear_tracking_signals() + return ..() + +/atom/movable/screen/minimap_element/blip/proc/register_target(atom/target) + if(!isnull(track_target)) + CRASH("[type] attempted to register [target] while already tracking [track_target].") + if(isnull(target)) + CRASH("[type] attempted to register a null track target.") + RegisterSignal(target, COMSIG_QDELETING, TYPE_PROC_REF(/datum, selfdelete), override = TRUE) + track_target = target + name = target.name + +/atom/movable/screen/minimap_element/blip/proc/clear_tracking_signals() + tracking = FALSE + if(track_target) + UnregisterSignal(track_target, list(COMSIG_QDELETING, COMSIG_MOVABLE_Z_CHANGED, COMSIG_MOVABLE_MOVED)) + track_target.maptext = null + track_target = null + QDEL_NULL(connect_ref) + +/atom/movable/screen/minimap_element/blip/proc/start_tracking_target() + if(tracking) + return + if(isnull(track_target)) + CRASH("[type] cannot start tracking without a registered target.") + RegisterSignal(track_target, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_target_z_changed)) + RegisterSignal(track_target, COMSIG_MOVABLE_MOVED, PROC_REF(on_tracked_or_container_moved)) + if(ismovable(track_target)) + var/static/list/container_connections = list( + COMSIG_MOVABLE_MOVED = PROC_REF(on_tracked_or_container_moved), + COMSIG_MOVABLE_Z_CHANGED = PROC_REF(on_target_z_changed), + ) + connect_ref = WEAKREF(AddComponent(/datum/component/connect_containers, track_target, container_connections)) + tracking = TRUE + INVOKE_ASYNC(src, PROC_REF(update_minimap)) + +/atom/movable/screen/minimap_element/blip/proc/update_minimap() + var/turf/target_turf = get_turf(track_target) + minimap = get_minimap_for_z(target_turf.z) + update_blip() + +/atom/movable/screen/minimap_element/blip/proc/on_target_z_changed(atom/movable/source, turf/old_turf, turf/new_turf, same_z_layer) + SIGNAL_HANDLER + if(isnull(track_target)) + return + var/turf/target_turf = get_turf(track_target) + if(isnull(minimap) || minimap.z != target_turf?.z) + INVOKE_ASYNC(src, PROC_REF(update_minimap)) + else + update_blip() + +/atom/movable/screen/minimap_element/blip/proc/on_tracked_or_container_moved(atom/movable/source, atom/old_loc) + SIGNAL_HANDLER + update_blip() + +/atom/movable/screen/minimap_element/blip/proc/update_blip() + SIGNAL_HANDLER + if(isnull(track_target) || isnull(minimap)) + return + name = track_target.name + var/turf/target_turf = get_turf(track_target) + var/half_size = large ? 5 : 3 + pixel_w = MINIMAP_WORLD_TO_PIXEL(target_turf.x, minimap.min_x, half_size) + pixel_z = MINIMAP_WORLD_TO_PIXEL(target_turf.y, minimap.min_y, half_size) + diff --git a/code/modules/minimap/minimap.dm b/code/modules/minimap/minimap.dm new file mode 100644 index 00000000000..a893ae13d38 --- /dev/null +++ b/code/modules/minimap/minimap.dm @@ -0,0 +1,84 @@ +/// Assoc list of z-levels to `/datum/minimap` instances. +GLOBAL_ALIST_EMPTY(minimaps) + +/// Represents a minimap for a single Z-level. +/datum/minimap + /// The Z-level this minimap was made for. + VAR_FINAL/z + /// The icon of the base map itself. + var/icon/base_map + /// Mapping of x/y coords to area names. + var/alist/map_position_to_name = alist() + /// Minimum world X coordinate included in the cropped map icon. + var/min_x = 1 + /// Minimum world Y coordinate included in the cropped map icon. + var/min_y = 1 + +/datum/minimap/proc/load_z(z) + . = FALSE + if(!isnum(z) || z > length(SSmapping.z_list)) + CRASH("Tried to create minimap for invalid Z-level ([z])") + + base_map = icon('icons/ui_icons/minimap/minimap.dmi') + src.z = z + + var/min_x = world.maxx + var/min_y = world.maxy + var/max_x = 1 + var/max_y = 1 + + map_position_to_name.Cut() + for(var/turf/location as anything in Z_TURFS(z)) + if(location.skip_minimap_rendering || isshuttleturf(location)) + continue + var/area/arealoc = location.loc + if(arealoc.skip_minimap_rendering) + continue + var/x = location.x + var/y = location.y + min_x = min(min_x, x) + min_y = min(min_y, y) + max_x = max(max_x, x) + max_y = max(max_y, y) + if(location.density) + base_map.DrawBox(location.tacmap_color, x, y) + continue + var/atom/movable/alttarget = (locate(/obj/machinery/door) in location) || (locate(/obj/structure/window) in location) || (locate(/obj/structure/fence) in location) + if(alttarget) + base_map.DrawBox(alttarget.tacmap_color, x, y) + continue + if(arealoc.tacmap_color) + base_map.DrawBox(BlendRGB(location.tacmap_color, arealoc.tacmap_color, 0.5), x, y) + continue + if(istype(location, /turf/open/floor/engine/hull)) + var/turf/turf_below = GET_TURF_BELOW(location) + var/area/below_area = turf_below?.loc + // we'll draw the below area's color but transparent + if(below_area?.tacmap_color) + var/list/below_color = rgb2num(below_area.tacmap_color) + base_map.DrawBox(rgb(below_color[1], below_color[2], below_color[3], 64), x, y) + continue + base_map.DrawBox(location.tacmap_color, x, y) + + src.min_x = min_x + src.min_y = min_y + + base_map.Crop(min_x, min_y, max_x, max_y) + base_map.Scale(base_map.Width() * MINIMAP_PIXEL_MULTIPLIER, base_map.Height() * MINIMAP_PIXEL_MULTIPLIER) + + return TRUE + +/// Gets the `/datum/minimap` for a Z-level - generating it if it hasn't been yet. +/proc/get_minimap_for_z(z) as /datum/minimap + var/static/generating_minimap = FALSE + UNTIL(!generating_minimap) + + if(GLOB.minimaps[z]) + return GLOB.minimaps[z] + + generating_minimap = TRUE + var/datum/minimap/minimap = new + if(minimap.load_z(z)) + GLOB.minimaps[z] = minimap + . = minimap + generating_minimap = FALSE diff --git a/code/modules/minimap/minimap_action.dm b/code/modules/minimap/minimap_action.dm new file mode 100644 index 00000000000..9c25d7bc553 --- /dev/null +++ b/code/modules/minimap/minimap_action.dm @@ -0,0 +1,141 @@ + +/datum/action/minimap + name = "Toggle Minimap" + button_icon = 'icons/hud/implants.dmi' + button_icon_state = "minimap" + /// Mob currently bound to z-change signal handling for auto-hide behavior. + var/mob/tracked_owner + /// Optional fixed z-level that anchors this action's minimap stack and permission checks. + var/fixed_z_level + /// Optional minimap blip tags to render on the rewrite minimap display. + var/list/minimap_blip_tags = list() + /// Optional annotation sharing tag for minimap drawings/labels. + var/annotation_share_tag + /// Whether this action's minimap display should allow drawing tools. + var/can_draw = FALSE + /// list of hud elements we add and remove and check for when this action is triggered + var/list/huds = list( + HUD_TAC_MINIMAP_DIMMER = /atom/movable/screen/fullscreen/dimmer/minimap, + HUD_TAC_MINIMAP = /atom/movable/screen/minimap_display, + HUD_TAC_MINIMAP_Z_INDICATOR = /atom/movable/screen/minimap_z_indicator, + HUD_TAC_MINIMAP_Z_INDICATOR_UP = /atom/movable/screen/minimap_z_up, + HUD_TAC_MINIMAP_Z_INDICATOR_DOWN = /atom/movable/screen/minimap_z_down + ) + +/datum/action/minimap/Trigger(mob/clicker, trigger_flags) + . = ..() + var/datum/hud/hud = clicker.hud_used + // Toggle off if already visible. + if(has_minimap_huds(hud)) + remove_huds(hud) + to_chat(clicker, span_notice("Minimap hidden.")) + return + + if(SEND_SIGNAL(clicker, COMSIG_MINIMAP_ACTION_TRIGGER) & COMSIG_MINIMAP_ACTION_TRIGGER_CANCEL) + return + + var/anchor_z = get_anchor_z_level(clicker?.z) + if(is_forbidden_minimap_z(anchor_z)) + to_chat(clicker, span_warning("The minimap cannot be used on this z-level.")) + clicker.balloon_alert(clicker, "invalid z-level!") + return + var/display_z = get_opening_display_z_level(anchor_z, clicker?.z) + + var/datum/minimap/minimap = get_minimap_for_z(display_z) + if(isnull(minimap)) + clicker.balloon_alert(clicker, "no minimap generated") + return + add_huds(hud, minimap, isnull(fixed_z_level) ? null : display_z) + to_chat(clicker, span_notice("Minimap shown.")) + +/datum/action/minimap/Grant(mob/grant_to) + . = ..() + set_tracked_owner(grant_to) + +/datum/action/minimap/Remove(mob/remove_from) + set_tracked_owner(null) + return ..() + +/datum/action/minimap/proc/has_minimap_huds(datum/hud/hud) + for(var/element in huds) + if(hud.screen_objects[element]) + return TRUE + return FALSE + +/datum/action/minimap/proc/get_open_minimap_display(datum/hud/hud) + if(isnull(hud) || !has_minimap_huds(hud)) + return null + return hud.screen_objects[HUD_TAC_MINIMAP] + +/datum/action/minimap/proc/add_huds(datum/hud/hud, datum/minimap/minimap, initial_display_z_level) + for(var/element in huds) + var/hud_element_type = huds[element] + var/instanced = new hud_element_type(null, hud, minimap, minimap_blip_tags, initial_display_z_level, annotation_share_tag, can_draw) + hud.add_screen_object(instanced, element, HUD_GROUP_STATIC, update_screen = TRUE) + +/datum/action/minimap/proc/set_tracked_owner(mob/new_owner) + if(tracked_owner == new_owner) + return + if(!isnull(tracked_owner)) + UnregisterSignal(tracked_owner, COMSIG_MOVABLE_Z_CHANGED) + tracked_owner = new_owner + if(!isnull(tracked_owner)) + RegisterSignal(tracked_owner, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_owner_z_changed)) + +/datum/action/minimap/proc/get_anchor_z_level(current_z_level) + return isnull(fixed_z_level) ? current_z_level : fixed_z_level + + +/datum/action/minimap/proc/get_opening_display_z_level(anchor_z_level, current_z_level) + var/list/connected_levels = SSmapping.get_connected_levels(anchor_z_level) + if(length(connected_levels) && connected_levels.Find(current_z_level)) + return current_z_level + return (length(connected_levels) ? connected_levels[1] : anchor_z_level) + +/datum/action/minimap/proc/is_forbidden_minimap_z(z_level) + if(isnull(z_level)) + return FALSE + return is_centcom_level(z_level) || is_reserved_level(z_level) + +/datum/action/minimap/proc/on_owner_z_changed(atom/movable/source, turf/old_turf, turf/new_turf, same_z_layer) + SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(handle_owner_z_changed), source, new_turf?.z) + +/datum/action/minimap/proc/handle_owner_z_changed(mob/owner_mob, new_z_level) + var/datum/hud/owner_hud = owner_mob?.hud_used + if(isnull(get_open_minimap_display(owner_hud))) + return + + var/anchor_z = get_anchor_z_level(new_z_level) + if(is_forbidden_minimap_z(anchor_z)) + remove_huds(owner_hud) + to_chat(owner_mob, span_warning("The minimap closes on this z-level.")) + return + if(isnull(fixed_z_level)) + return + + var/display_z = get_opening_display_z_level(anchor_z, new_z_level) + var/atom/movable/screen/minimap_display/display = get_open_minimap_display(owner_hud) + if(isnull(display) || display.get_viewed_z_level() == display_z) + return + var/datum/minimap/minimap = get_minimap_for_z(display_z) + if(QDELETED(src) || isnull(minimap)) + return + display = get_open_minimap_display(owner_hud) + if(isnull(display) || display.get_viewed_z_level() == display_z) + return + display.change_z_level(display_z, minimap) + +/datum/action/minimap/nuclear + annotation_share_tag = MINIMAP_ANNOTATION_TAG_NUCLEAR + huds = list( + HUD_TAC_MINIMAP_DIMMER = /atom/movable/screen/fullscreen/dimmer/minimap, + HUD_TAC_MINIMAP = /atom/movable/screen/minimap_display/nuclear, + HUD_TAC_MINIMAP_Z_INDICATOR = /atom/movable/screen/minimap_z_indicator, + HUD_TAC_MINIMAP_Z_INDICATOR_UP = /atom/movable/screen/minimap_z_up, + HUD_TAC_MINIMAP_Z_INDICATOR_DOWN = /atom/movable/screen/minimap_z_down + ) + +/datum/action/minimap/proc/remove_huds(datum/hud/hud) + for(var/element in huds) + hud.remove_screen_object(element) diff --git a/code/modules/minimap/minimap_table.dm b/code/modules/minimap/minimap_table.dm new file mode 100644 index 00000000000..3af72ea76c4 --- /dev/null +++ b/code/modules/minimap/minimap_table.dm @@ -0,0 +1,225 @@ + +/obj/machinery/minimap_table + name = "reconnaissance platform" + desc = "This holographic projector displays a constant stream of tactical information, enabling cinematic planning and strategizing. \ + Currently, it appears to be monitoring a nearby station and tracking key targets for a clandestine operation." + icon = 'icons/obj/machines/minimap_table.dmi' + icon_state = "off" + processing_flags = START_PROCESSING_MANUALLY + light_range = 4 + light_power = 2 + light_color = LIGHT_COLOR_INTENSE_RED + light_system = OVERLAY_LIGHT + density = TRUE + bound_width = 64 + SET_BASE_PIXEL(0, 2) + /// Hologram icon sheet used for startup/idle/closing projection effects. + var/hologram_icon_file = 'icons/obj/machines/minimap_table_hologram.dmi' + /// Z-trait used to resolve the minimap level this table displays. + var/target_z_trait = ZTRAIT_STATION + /// Cached minimap datum currently displayed by this table. + var/datum/minimap/minimap + /// Users currently viewing the table-projected minimap HUD. + var/list/mob/viewers = list() + /// Whether the table is currently active and projecting. + var/active = FALSE + /// Whether startup animation/state is currently in progress. + var/startup = FALSE + /// Pixel X offset for projected hologram overlays. + var/animation_x = -15 + /// Pixel Y offset for projected hologram overlays. + var/animation_y = 18 + /// Startup/closing animation duration. + var/animation_duration = 5.1 SECONDS + /// Max distance at which users can interact with the table. + var/interactivity_range = 3 + /// Proximity monitor used to close viewers leaving interaction range. + var/datum/proximity_monitor/proximity + /// Light helper used for pulsing hologram illumination. + var/datum/light_middleman/middleman + /// Lowest alpha value used by the pulsing light animation. + var/flicker_min_alpha = 150 + /// HUD elements used by the holotable minimap view. + var/list/table_huds = list( + HUD_TAC_MINIMAP_DIMMER = /atom/movable/screen/fullscreen/dimmer/minimap, + HUD_TAC_MINIMAP = /atom/movable/screen/minimap_display/nuclear, + HUD_TAC_MINIMAP_Z_INDICATOR = /atom/movable/screen/minimap_z_indicator, + HUD_TAC_MINIMAP_Z_INDICATOR_UP = /atom/movable/screen/minimap_z_up, + HUD_TAC_MINIMAP_Z_INDICATOR_DOWN = /atom/movable/screen/minimap_z_down, + ) + +/obj/machinery/minimap_table/Initialize(mapload) + . = ..() + proximity = new(src, interactivity_range) + + if(IS_OVERLAY_LIGHT_SYSTEM(light_system)) + middleman = new(src, "holotable") + RegisterSignal(middleman, COMSIG_LIGHT_MIDDLEMAN_UPDATED, PROC_REF(light_pulsate)) + middleman.being_overriding_light() + +/obj/machinery/minimap_table/Destroy(force) + for(var/mob/viewer as anything in viewers) + remove_table_huds(viewer.hud_used) + viewers = null + QDEL_NULL(proximity) + QDEL_NULL(middleman) + minimap = null + return ..() + +/obj/machinery/minimap_table/post_machine_initialize() + . = ..() + INVOKE_ASYNC(src, PROC_REF(set_minimap)) + +/obj/machinery/minimap_table/RangedAttackOn(mob/attacker, list/modifiers) + if(get_dist(src, attacker) > interactivity_range) + return + interact(attacker) + +/obj/machinery/minimap_table/interact(mob/user) + . = ..() + if(!is_operational || isnull(minimap) || isnull(user.hud_used)) + return FALSE + if(!isnull(user.hud_used.screen_objects[HUD_TAC_MINIMAP])) + hide_minimap(user) + return TRUE + if(active) + show_minimap(user) + return TRUE + + addtimer(CALLBACK(src, PROC_REF(activate), user), animation_duration, TIMER_UNIQUE | TIMER_CLIENT_TIME) + + startup = TRUE + play_animation("startup") + return TRUE + +/obj/machinery/minimap_table/proc/play_animation(icon_state = "startup", duration = animation_duration) + var/image/img = image(hologram_icon_file, src, icon_state, ABOVE_MOB_LAYER, dir, animation_x, animation_y) + var/image/emissive_img = image(hologram_icon_file, src, icon_state, ABOVE_MOB_LAYER, dir, animation_x, animation_y) + emissive_img.plane = EMISSIVE_PLANE + emissive_img.color = _EMISSIVE_COLOR_NO_BLOOM(1) + + flick_overlay_global(img, GLOB.clients, duration) + flick_overlay_global(emissive_img, GLOB.clients, duration) + +/obj/machinery/minimap_table/proc/activate(mob/activator) + if(active || !is_operational) + return + startup = FALSE + active = TRUE + if(activator && get_dist(src, activator) <= interactivity_range) + show_minimap(activator) + update_appearance(UPDATE_OVERLAYS) + light_pulsate() + +/obj/machinery/minimap_table/proc/deactivate() + if(!active) + return + active = FALSE + update_appearance(UPDATE_OVERLAYS) + var/obj/effect/abstract/main_light = middleman.primary_intercept + animate(main_light, time = 1 SECONDS) + play_animation("closing") + +/obj/machinery/minimap_table/proc/light_pulsate() + SIGNAL_HANDLER + var/obj/effect/abstract/main_light = middleman.primary_intercept + var/matrix/center = matrix() + // center it since we're a 2x2 machine + center.Translate(16, 0) + main_light.transform = center + if(!active) + return + + + var/matrix/bigTransform = matrix() + var/matrix/smallTransform = matrix() + smallTransform.Add(center) + bigTransform.Add(center) + + bigTransform.Scale(1.25) + smallTransform.Scale(0.75) + + animate(main_light, alpha = flicker_min_alpha, time = 2 SECONDS, loop = -1, easing = SINE_EASING) + animate(alpha = 255, time = 2 SECONDS) + animate(transform = bigTransform, time = 3 SECONDS, loop = -1, flags = ANIMATION_PARALLEL, easing = SINE_EASING) + animate(transform = smallTransform, time = 3 SECONDS) + +/obj/machinery/minimap_table/proc/deactive_without_viewers() + if(!length(viewers)) + deactivate() + +/obj/machinery/minimap_table/proc/show_minimap(mob/user) + add_table_huds(user.hud_used) + viewers |= user + +/obj/machinery/minimap_table/proc/hide_minimap(mob/user) + remove_table_huds(user.hud_used) + viewers -= user + if(!length(viewers)) + addtimer(CALLBACK(src, PROC_REF(deactive_without_viewers)), 10 SECONDS, TIMER_OVERRIDE | TIMER_UNIQUE) + +/obj/machinery/minimap_table/proc/add_table_huds(datum/hud/hud) + var/target_z = resolve_target_z() + var/allow_draw = can_user_draw(hud?.mymob) + for(var/element in table_huds) + var/hud_element_type = table_huds[element] + var/instanced = new hud_element_type(null, hud, minimap, null, target_z, MINIMAP_ANNOTATION_TAG_NUCLEAR, allow_draw) + hud.add_screen_object(instanced, element, HUD_GROUP_STATIC, update_screen = TRUE) + +/obj/machinery/minimap_table/proc/can_user_draw(mob/user) + return HAS_TRAIT(user, TRAIT_MINIMAP_TABLE_DRAW) + +/obj/machinery/minimap_table/proc/remove_table_huds(datum/hud/hud) + for(var/element in table_huds) + hud.remove_screen_object(element) + +/obj/machinery/minimap_table/proc/resolve_target_z() + if(isnull(target_z_trait)) + return null + var/list/trait_levels = SSmapping.levels_by_trait(target_z_trait) + if(length(trait_levels)) + var/top_level + for(var/level in trait_levels) + if(isnull(top_level) || level > top_level) + top_level = level + return top_level + return null + +/obj/machinery/minimap_table/proc/set_minimap() + var/target_z = resolve_target_z() + minimap = get_minimap_for_z(target_z) + +/obj/machinery/minimap_table/on_set_is_operational() + update_appearance() + set_light_on(is_operational) + + if(!is_operational) + deactivate() + +/obj/machinery/minimap_table/update_overlays() + . = ..() + if(!is_operational) + return + . += mutable_appearance(icon, "idle") + . += emissive_appearance(icon, "idle", src) + if(active) + var/holo_state = "idle" + var/mutable_appearance/idle = mutable_appearance(hologram_icon_file, holo_state, ABOVE_MOB_LAYER) + idle.pixel_x = animation_x + idle.pixel_y = animation_y + . += idle + + var/mutable_appearance/emissive = emissive_appearance(hologram_icon_file, holo_state, src, ABOVE_MOB_LAYER, effect_type = EMISSIVE_NO_BLOOM) + emissive.pixel_x = animation_x + emissive.pixel_y = animation_y + . += emissive + +/obj/machinery/minimap_table/OnProximityExit(atom/movable/gone) + if(!active || !ismob(gone)) + return + var/mob/mob_gone = gone + var/list/adjacent = orange(interactivity_range, src) + if(mob_gone in adjacent) + return + if(mob_gone in viewers) + hide_minimap(gone) diff --git a/code/modules/mob/living/basic/bots/medbot/medbot.dm b/code/modules/mob/living/basic/bots/medbot/medbot.dm index 3e6a22b0c6d..7e2bd3d8574 100644 --- a/code/modules/mob/living/basic/bots/medbot/medbot.dm +++ b/code/modules/mob/living/basic/bots/medbot/medbot.dm @@ -468,6 +468,9 @@ /mob/living/basic/bot/medbot/nukie/Initialize(mapload, new_skin) . = ..() + var/datum/action/minimap/nuclear/tacmap_action = new + tacmap_action.Grant(src) + add_minimap_blip(src, MINIMAP_NUKEOP_BLIP, "mediborg") RegisterSignal(SSdcs, COMSIG_GLOB_NUKE_DEVICE_DISARMED, PROC_REF(nuke_disarm)) RegisterSignal(SSdcs, COMSIG_GLOB_NUKE_DEVICE_ARMED, PROC_REF(nuke_arm)) RegisterSignal(SSdcs, COMSIG_GLOB_NUKE_DEVICE_DETONATING, PROC_REF(nuke_detonate)) diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm index d114b6d42a1..f04fa3aea99 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -252,6 +252,8 @@ var/datum/callback/got_disk = CALLBACK(src, PROC_REF(got_disk)) var/datum/callback/display_disk = CALLBACK(src, PROC_REF(display_disk)) AddComponent(/datum/component/nuclear_bomb_operator, got_disk, display_disk) + var/obj/item/implant/implanter = SSwardrobe.provide_type(/obj/item/implant/tacmap/nuclear/cayenne, src) + implanter.implant(src, null, TRUE) /mob/living/basic/carp/pet/cayenne/apply_colour() if (prob(RARE_CAYENNE_CHANCE)) diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index af9b1e6d49f..1c755a02078 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -920,6 +920,9 @@ ..() var/mob/living/silicon/robot/cyborg = loc cyborg.remove_faction(FACTION_SILICON) //ai turrets + add_minimap_blip(cyborg, MINIMAP_NUKEOP_BORG_BLIP, "combatborg") + var/datum/action/minimap/nuclear/tacmap_action = new + tacmap_action.Grant(cyborg) /obj/item/robot_model/syndicate/remove_module(obj/item/removed_module) ..() @@ -952,6 +955,13 @@ model_traits = list(TRAIT_PUSHIMMUNE) hat_offset = list("north" = list(0, 3), "south" = list(0, 3), "east" = list(-1, 3), "west" = list(1, 3)) +/obj/item/robot_model/syndicate_medical/rebuild_modules() + ..() + var/mob/living/silicon/robot/cyborg = loc + add_minimap_blip(cyborg, MINIMAP_NUKEOP_BORG_BLIP, "mediborg") + var/datum/action/minimap/nuclear/tacmap_action = new + tacmap_action.Grant(cyborg) + /obj/item/robot_model/saboteur name = "Syndicate Saboteur" basic_modules = list( @@ -982,6 +992,13 @@ canDispose = TRUE var/datum/weakref/thermal_vision_ref +/obj/item/robot_model/saboteur/rebuild_modules() + ..() + var/mob/living/silicon/robot/cyborg = loc + add_minimap_blip(cyborg, MINIMAP_NUKEOP_BORG_BLIP, "engiborg") + var/datum/action/minimap/nuclear/tacmap_action = new + tacmap_action.Grant(cyborg) + /datum/action/cooldown/borg_thermal name = "Toggle Thermal Night Vision" button_icon = 'icons/mob/actions/actions_mecha.dmi' diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 594094deefd..79a47f4d244 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -822,6 +822,8 @@ GLOBAL_LIST_INIT(slime_extract_auto_activate_reactions, init_slime_auto_activate var/obj/item/implant/radio/syndicate/imp = new(src) imp.implant(smart_mob, user) smart_mob.AddComponent(/datum/component/simple_access, list(ACCESS_SYNDICATE, ACCESS_MAINT_TUNNELS)) + var/obj/item/implant/implanter = SSwardrobe.provide_type(/obj/item/implant/tacmap/nuclear/cayenne, src) + implanter.implant(src, null, TRUE) /obj/item/slimepotion/sentience/nuclear/dangerous_horse name = "dangerous pony potion" diff --git a/code/modules/uplink/uplink_items/nukeops.dm b/code/modules/uplink/uplink_items/nukeops.dm index 265c43dce65..e008dbca98d 100644 --- a/code/modules/uplink/uplink_items/nukeops.dm +++ b/code/modules/uplink/uplink_items/nukeops.dm @@ -654,7 +654,7 @@ operative team's body-cams. They can also pilot the shuttle remotely and view the station's camera net. \ If you're a meathead who's just here to kill people and don't care about strategising or intel, you'll still have someone to bear witness to your murder-spree!" item = /obj/item/antag_spawner/nuke_ops/overwatch - cost = 12 + cost = 10 purchasable_from = UPLINK_FIREBASE_OPS // ~~ Disposable Sentry Gun ~~ diff --git a/code/modules/vehicles/mecha/combat/gygax.dm b/code/modules/vehicles/mecha/combat/gygax.dm index 974ec17818a..951035fdaa9 100644 --- a/code/modules/vehicles/mecha/combat/gygax.dm +++ b/code/modules/vehicles/mecha/combat/gygax.dm @@ -73,6 +73,10 @@ fire = 100 acid = 100 +/obj/vehicle/sealed/mecha/gygax/dark/Initialize(mapload) + . = ..() + add_minimap_blip(src, MINIMAP_SYNDICATE_MECH_BLIP, "syndiemech") + /obj/vehicle/sealed/mecha/gygax/dark/loaded/Initialize(mapload) . = ..() max_ammo() diff --git a/code/modules/vehicles/mecha/combat/honker.dm b/code/modules/vehicles/mecha/combat/honker.dm index f5ad579cda1..9c63dc71898 100644 --- a/code/modules/vehicles/mecha/combat/honker.dm +++ b/code/modules/vehicles/mecha/combat/honker.dm @@ -60,6 +60,10 @@ MECHA_ARMOR = 2, ) +/obj/vehicle/sealed/mecha/honker/dark/Initialize(mapload, built_manually) + . = ..() + add_minimap_blip(src, MINIMAP_SYNDICATE_MECH_BLIP, "syndiemech") + /obj/vehicle/sealed/mecha/honker/dark/loaded equip_by_category = list( MECHA_L_ARM = /obj/item/mecha_parts/mecha_equipment/weapon/honker, diff --git a/code/modules/vehicles/mecha/combat/marauder.dm b/code/modules/vehicles/mecha/combat/marauder.dm index e0e214242aa..e316de70bf7 100644 --- a/code/modules/vehicles/mecha/combat/marauder.dm +++ b/code/modules/vehicles/mecha/combat/marauder.dm @@ -161,6 +161,10 @@ fire = 100 acid = 100 +/obj/vehicle/sealed/mecha/marauder/mauler/Initialize(mapload) + . = ..() + add_minimap_blip(src, MINIMAP_SYNDICATE_MECH_BLIP, "syndiemech") + /obj/vehicle/sealed/mecha/marauder/mauler/loaded equip_by_category = list( MECHA_L_ARM = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg, diff --git a/config/logging.txt b/config/logging.txt index cd9b38b6203..c116110bd46 100644 --- a/config/logging.txt +++ b/config/logging.txt @@ -50,6 +50,9 @@ LOG_MECHA ## log OOC channel LOG_OOC +## log minimap drawing +LOG_MINIMAP_DRAWING + ## log pda messages LOG_PDA diff --git a/icons/hud/actions.dmi b/icons/hud/actions.dmi index 6d51cc55534a12316c3e5a034267a772707c2de3..e8385331596b16edd2d981b021ef408451dabb71 100644 GIT binary patch literal 9680 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�@Qe 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 De1`lY diff --git a/icons/hud/implants.dmi b/icons/hud/implants.dmi index b85ab4573ff2ae02a4b2b1265f03121d59433d42..64ba66dc406829ec5cf618cefeb24a8d2726baa9 100644 GIT binary patch literal 3879 zcmV+?57_XDP)V=-0C=38k-=)iFbsyz_EU)VDva$VBRlvqQbrE#D-@5Yj#&~1+qB!;?@-zl zmQWZv7{jOUm#r?FX)cb~?DJCCAFi;4|*~PcH0|PIbvyQy$^7WFk%>)KEr%2R> zVZ&MLV*&$;vs1JKB`}~0&RXj24;WAq)xD%BQHl}^)VG?I^gZ<<`7^CZ)hyNWu9Bic zg-U2tqC_Ps)Yl-+x{%WpG8j;=SfZMvB3VacPAf?>Xxm7m?VoZqOv}vM!q62;p%>0_ z_VwO%*^ln{8T$M*J>?LsTlu&0VHdYWJhTqs>tBt7AN^ogUj3Ilw$Wbv=+^ix><%^5 z`-cAloTRV-j@OF70001lP)t-s00014ZQxmL;8|_p|NsC0>}0*<`^?hU`@$z~`BRs| z@^$ATrmeJZ+aD_O0&<|~+=UHbyBz@JF=dD7B+UYLe~2x!6IpHG0I4KQS-z`E4N_KI zNKBp>c?C;LOCx11LqkIdYY72g6*xLRPAO7*6B8Ui4GcO16)giD9UlfA0ssI2F)|}d z00004bW%=J02?z&Sc|p~000d#NklPw(rDOME zQz+vaLhFDJ30&zViq2|L1V>4dBuSDa7pEF-;)VRX;U`|lH={H0B3@b}qSnMuJnPwe zKJfmbo+fEzG+p1I%Y;nN`oeq9<%nm$KEt2eA5H63rOt?c3tV{XdFRXCmt&sypU?2Y z{vwZ{>m9%g8hqhL&*iY+t`8r4{&`PLtBG1|eiq*ojo{0pFW&Q`XXnH9X@Z~Vm?!5A z^J_w5_45vloiFgE=NX>8kJq2zC+Fu`c;rLCjYmMEiD9G81crqcO5ZarF#Lh_6<(e9 z|H$E+m~&JtK+Pb-PhiMp$;ZF*w0d$r9Qzw!9tn{jcc9Tx7?&PP!tyJRmAe{&F#^c{ zcn9b#{RD*%d%*Sx2=Ze*0^4AIcS({YNs=TTba2eTi%u#fw}i~G1Aytt41 z!OQ!oUmNPr_JeW%824+Vec1oS{bAfcqF(a_+gTs zxZji->@N(^*KvOr_kZUZA8>qs7bjHOq0*cVUf}dUqBTFW8w4-#I=`ePNs=TsyZqke(!ES>wZ8xLN$4_}bW(M$v zfPH;KJ{QoA(4O_4Wb3Qi^NVWCKdiYBP`=RlqC@@;k-#nhnLpXFdmYDN7zn^_gs^bI zhSij;{QfU^;*Y~bk`M3(hrW8O8Y6(HNm-a!jVINNAGk zHj@r{^lX)zeQVw~S^}NeS|ci70TDnVj`S_6SGewooJJjdwTA5l3&6e)fIB@k>)R6O zLi1&vmlAr&l150?0w8%s)B*;ko6fsaH)Zds-QAv=^^-4Yrpj!=tccn8uuz2Y3RJ}W zkTKo6&w&xR4_AU(-|ZWj(0>1d*t-}Y_0{A9v-^}i2INU;2Jy72886Wr=c7(iasE~5~(Hu%8g z!c*s4M)qpJ!g-Qdz!X;IIqq@BY>~Ou`(T2%Y;12r(M~v6OlQ?hdqTX6~ucRlhR@ z5sMqh+zCV*&mbFs$rDa6L(e)`A&dZOo2VfG0v75-Z$AKbU-eTBn2;`k+?oSv0-BHk zK4UvAV2{pE8GQmxCPvJN`!>1%cd-4v-$6vUIG{uTn~x_T*omjm7sv6e^@yN+hxrO< z!Xiq{QEmV~>uZES`gjDAk)9`wsc#Ah)Ei9r-hd$iPFL=iK>y77yeDH3_sl*qfOSDI zAN556gI&nr8L&n;1#%DYY45T|_Ms6d(0WIUw>DK2P%%WE`lLYqE3kxQMl%eRh#KMq zGGM++K1KCR4su%yuhEZ({lJS?vCn&cX6^(=urQqGzWFg4-=Tfupf<3`#Um!Zru_R} zBqnt6>m++bUpLIexWTr+EFw60>%Qmd|NbZZn{U4P)6N-awT%N&^z0TATD&zuOxndI zrKFIh`Tzgh8B6BHno)!{^@)@9BXw+^J)WCUEK5FR(r*;;i_V%ayrAADojji@!phkI zl2@8b%+uut8nsKs5d7l<&gX}sj<-m}!V{7rrm+jfOHYi{tW)Jf@c^js9Lq$cfsymi z7w>~8XwTDwd5X`uPb@~%Fvlt?=(-shntKtESwA#T&G%_GySSLmJ}E+?n2Bf@Ks&jP z?($LqFD^Ppqkf3NTZ-?Z6$n8?_>}zHz*i&;bD|o&LzJ3!0p;bkRQW*vGt0PF0T|W`{@_@vWWs-~rDkcDLEWiqYs9z5((?o$02uTATNSJ#(2f~{eu=0Em zt}jZNiwxoRnm`F+zztVIh^jXMknsIeg!yhFuo?G7IWRh~9|Ym^a}3xtjrILgg!zsh z)$8MB0f>HU6@!`}`z{8ACAVsXCpM^fJZGb!(X zNNQ+5m)~K4&bVc?Zi0^018`x{#qS6pzxBTOzBL6t6vMq6uy!qxEFl*G0$^t&15B3BmV@0C$g%0b}1e z`04lnjPtVq`xB?SAME?OqlXWIq5X7zCLpH1Z9w=oAbcb+te?*hfbqkN7%=u@z}QCu z!}|IB0Eov=HXwW(5IzzZ*3aa3{($G-M9=>sbN<~#zN61~q`D(-^Qm-{+?I=_-z zH4(d=p91XsT8#$$?Pu~QTI!yTP~6e;*< zlR?h=9iTeg7tH(l_|m=%)vlm|Mg#yN`B>hM>jO+wFzx5#Gs~ZLen*}cb%W1~p8dq{ zG^syn(xgelKOfY8&)}>9Z!RxS6tK1dHQ!Ydun8K0Uk(Vq`(*g}ydtXR^QJkvU*1IX zeBr-+$iI0rCf^?Lw(n(p5?LfG%_#irltl?&CE{gRX~y7ZC!KP9(7K{Ei-`PtwH||? zoi;4uYntzk1aE#e4bE_UKR@xS`7|KMC;Co*H_bEsBx?82Hs9B+el~oD^?3X|pbgnG zUn^<&>u;>Jd>yJ+ct`S!ny7}niU2u&wf^>HR)6`nt{S3V0`TjMKReK`XYdOyG7+S4 zMSbP?Rm10J0$HP1(`S3O&!1&{w(A1FpqtP=qB;Tj6G(z&B|rke1W6wsK-$k7&o=y$ zj$ZQ_fJ9E3pd(TVz@P2+XE^@A_+__hnokinR1rBA@k;YLCSTZU^JY8AX97z1Lw?!3 zj>fl#OMyAbmm*{#{*nFi0WbJ$z^0*Ayz)90|L_q#^!8VVd1VZKIUxAbjH1!_<$zb< zJFj_B+^9{{aIKNIG~nmEG~lDCEIW-SO8J=`I(rxJda>9D z;O6#ras3Z(EyCM103*IT0Os?DiR@OzJ0Si(K!qOwHV@0?!{+Jf_SUMPuHWX)`$g%s z9(K^a+984exX%|;1OD2uer>mmh-)eU72np^@WskMm7llL4Xkr)K&1b+-1qs2y8<8+ zvbG{Fq5`z|Uc4XW4?;8l0N^pT-#U1+>K|+rQGY&NEB1s6VDa?y^{ekS0BG}RK%a!i zGyy{veyQ@u4*pH?!IwpP2Q(4@a1-@_(oTJ^0YH;a1BP>i6|04%tBmyQ9Z>%?AUcvroJfxcH=^yS0%AC^U1UZRrwNFT;Vc1xbe@0#>DqW( pz&CX=Q`;}57K@xeJ@z;Q{R{q4XZ8wgy2=0m002ovPDHLkV1kU`Wy}Bo literal 8488 zcma)icQ~8j_jf{-DpISqXi=>_LaS70jZ$jwmKZIHqSVf?H*M`1HDcB-YEx>}jJ=f_ zRa-<5e(CqU-s}D6`@639k33JV`^k0g^W5j0&pGFF5~1^4jh3378UO&$sy|iMBi)z& zeW|Tn|BVb9u6*V0RZoe#82&!-+69?4xKVR@nhEIXxwb? z|5UX)+|u#ulf!K-Yn{!V79zJsdLZqq)S#37A?SgeqxT|mOs$Ykx)~Ne7zfK<3jE|U znMX(C#Kh0lQ2T81nWoGwR+CIJ>yr#4M@|%QkJB z*Yk9zX`shkwJ-Yb0ZSxjuWUA|wo9Tb#Q*hYXR_E@WYKpk-?HgP5e>G1B?1LmMBhoz z-k9z6hfTDjFR}HZ#LB=wI#{T4d)Mk`u%ssd0Pa&)Rx>o-|Y73Mo+4YWWG0|E_0mkPpzi)l=VHY0P&S#_X9cdj;Y#3o>wq_z)~ktshsOZ zU9aL$t7MGINW2ITCZpGIR?={NOzrv2;C6&8`nl(}oXy`7v0uslC*Im)($0zTyQ_LG zms5VnS(%yhnW;pH-MDq$=D=Amua@e=K`-=l>U3sDs+1kdidAmTR*sxTf2ab;_T#pb zVrV55#|JCnj;pq;QU7J>=SSzc!%qF!dgtA0Z59uP=bx@_RU?`=SUQXB{j$9Krg7fd zJneAk-|>e)EW`wj+frY&QCTa}s`F(iWYO`s*vAZi~kbbd> zbEGgsU|Nv|>~7tv&O;>^ufFWE?LFx=yhU9p!kKuBKGi4%(LLHFe$L%_d^h5>I&n9x zQb9W48v?nMrDSaBNhkOlZGg6D(meV;I!qwO|LHH}gD*Z<>KdU>L8>|OR6f#{|NRr~ zwmX78f9lKIfS)e7u7*6|1)zE$;>!IWHt~2o%flqmt1sb|2mB-5koQNMmFhUHekd)R zo*B+Io(B#oQb3(GhM%@r41aZ;e2By)e$nA>Wq43ORRvh^g#+lo2#G2d``Oy=3`3Ad z2xh-OIrhp-x8P|x==ggeg_q!_<+lT%{IIEp;U$5ba#`&D`L|COQ1q$s$=ZF-ykeKe z^ZgbT6)+%=+0+f?m-o6E#K8W8}vCNY86F)a=oVZ>1uP@buqEH;*fx+jC`ktuB|h z>~zijtcjD)@jkQhG{NPji(m5MX38^nuoL>dLut7A0QoC4;cWDEMHeRydGwx6V{m4a zW6LrgK^Z?;&iqCfES+<--&lil=F}FuqAm((UYyS@)z%76Nz-kj>JbI#ksC=`4`Kdz zIsEC@d^%v>y`_7 zR@R9t)2PrfUkclU0I-^5FnjDkcgp`3FaITk{{NQtPEn;pr#EpvaK#Bbc+_c=0?$@; ziwfKV`~hdWn4?e*>NzcS(QW-TNofn8D1SwawEXv^H3^r$MXvhs_|(4C(&w~xa=ipX z6rSu(h$RoDuTz*`{w{XY6<#9@BmO-a%8=F1c3j=|`E^gN)E;vxxOLcj)CKoAdetp3 zVr+`0$GO2(P1$o=hEP#6GxRLK%L+X74l0GnA1C3 zhY_btc)z6Z}xISVE zG)5m3Mmrt4tYTWJ?Mvi@taoUlF=$tC>k4j8J_PZ!L&X9 zZHfM<`Be4wkQZ46uq0IPjD9;3_AWX)sXgY$CZFuhX_DS<>#P(ScGI28k^(+IVwWG?O&kwD_OsNQbzNQh((m8s7{&F*}mZ9+E*!k zDObnxDWzg}{C-B^3c*K_R%2T&ab%m@ zi1upHyMZT1^{CbQ4mwNr212xR=%gLyY-}7_mQm~pY0rL=r-=!=Z~~nGQDB8Z#!VZb|f9z==oM`xOL^WS>-Dw7{{93;>8oX zG)Ykq6GRi=Fs|_`>~hzlu3;GehlB3XbEhQsMRJ*e#(BJrrbTPgR`W+%V*3!?O^u~A zVa>%D19K@XWs3A|3mO36;i6YvFHI7kplb7t;;$uC0DukoD*)g@)v_=kgMw9lGm)0P z?3HUS*8MHx-#^ilFREK+{e(DU?%FF%&(KK@N2@>d@c60r?ZHE`inm{rucqlbCEa-w znAPffZP2nlfiFUNYPeuPrx-m>G&N}$^RH@MiH*zgoBz|1Q|q}QTX)Sj868aWt5{az zu>T42JbbD0(YlOEOT1xl%Lr|Z2kv{N$>9jR6H~N9u_W2MoA) zTDQ|CkMAePE+CSTGfPBE$nuopbfLh}S1kOa)}SG%r(aPS^7+l7)SDBYpTX8~_H#F` zD3X!iba56;fM$8@U1By3;#+1D+=Y&E`BAw<5D?Ioo6iUkw~3~&i%1Ejr-aIxv|(Nq zas6{=iaNq(xj#fO*J{(N!DnBPjxBO86*Pwf&D{}bOBue;pH@L~tCRf#ZNbGSBgqWB ztm6hTYD&CYDPn)+Od$!hDob8&nL0C9kLJ((<=Li^aLp;S@EL-noqDqIGFT*YPxC2W zOW$v=I*39uevSN4+)kZk*qK#&e>aaMaH1^7D=sV%%-c7ik8l4-Ye!DMV=`$TuyT3q zz8L1_tzv5YS93&yd#!w`s_mKDge-4Rnv1S^qYKQU3FVC(n%jyfeBoN-tMsqz=$v<- z_Z#Z?scEl|HbS7L*Oo^v!kVbUXS=WVWslAlM6!-3+Y-pcw_@@KFr;`P=Mu3R=(Sn& z@5ke(6lGn7xxviL_HhCzN6dr6jpJz5%`j=9{R_i7sXM}OO*J91!8u1}0HA^pwsd^R zA}VV-A2&TwkjOzlkStT2c{iDkJ19i1)|)`psBI8nfx?E?tn)M{l<=3#+(%7RfS);8YaJp!nEIjQM%=KLykX8bQ;vCJrl@A z@}-v{l}k0PnEjoyX!?BmY<_B{ndst zLJqr1w66y=(H=u4%6t_NfMe>i(2Mu`@ef6~Xa9l2F$uQ5(hY|*rQTb~${Xemy}=tt zO2|smE&j7Bd-j{b#>-V>NcVkRR*t)VcvHz*`Bv(M7yb}wt>S;!SMRZBvU7jG#!S1v)o*k4*ihmO{UB}p9+MyOovJE4>_>+crCYf5IQdJ|){*XTy`;Szb>^GU zYMATV_2s`}uh;`0@V4U+Kjc{!G4Emuvt4=h>R#(!zC^ z;hN8l^t9XR>F6Gkvsi82LmoQ!AMOyA_mr7(2p-)_!#r(we>X~SD}->wI#awV!LtS^rIiL(85X_%Ja z@q=djr*5WFQ24;}RQfKP&PwRC@>`8@RmI9PsCHzX3^Vt_LHOZe9QS_h_DpIEVe`fn zRlm|P5~ct%+=XP>bH0{rI3i+c6M#$@gv!W_VKDC!JAF6M_|Y))%;&(@emIWF&mG-4?r^$7ErssYp)$(La!;S@L%`TYFUPq0{|N>HVDkZ{Hafhpd^HlNd8B6p5ZK7q zOuV@%pog!E-l#@gC>8=(2;+R4T8CU4olyl$xYRqTsS&?6>K%kVR?GJs2tCpNx0SW+t%@j2Ck2u~$ z5^&jH>G6AL*1Wl5yHWA^28289R7jJAVX_#kn=);Ui0*B)7O za?}$Dx7M>)57}c0y=k8sI`dyCFgw3yPpN-YS7iSl16?3!d?uxbm6E^Y2UZbz)vixf z+(ctzPeREm1QG)ApTnof9Y$qUw3O2;teVrRsD#pt-izMd_Mg80km2+}QuyD>f_eeP z8eX2}#gFskueh$6KrP{J!q1`=t0J|9UVfsw?T6RM*i44;;sY@qF|DwX8 z@WDzaPfXTc40&Yv$aBWTn(8sT6phXe2dZ)Woj*D5r6+WVMB?dn`kY3+muOkLe!nDR3Y3&QO<)SbMT^s~Xw(!{2X@(VK0ClbP{UF9)N$+1q*9 zKcUH3x9-sC8(!(Fiw3%}!~h zSGxQ8D+2mNxGg=sIi-o{9eT!(D$o)Cr$q+u5PrB&BYj8>i^2Pgg11(8GL6$-TNKm3 z5q}ZtOzM-zMhk>)@x!|dS&5&NZ<%I(oWK6-vLCGd(7~%GTx+NTK4@vAt-t9&gv)1DmbJm5 z@}3>N5HqpoSc2bayOl3R73$9!i!j*T?5t9!KK8sbANDH>RW-=;rlWL#$1&^mwCxue z`=^rJ`XLWtmWR>HVBXMFok?I&`ePU@$#3J1;<=w zwz}R+P8DAl(*~ku>3OAYdA4mV;R5>_cCZ_UG*R}onubD8m`v&9(F;w}&(6v(cd$Kh zIVlh;znKG`}G=u^uRc|VIv3O;OkdJ-8p>k74s*jae z-5M^x(CHy4WvP4sxuvM8Ka%tFR+O#onVZVc&DoMCzeDW)Pk_h zVtn4@JM{2TZhh8R?Z^5j)Nrd&YyKGY#ZW^F)9Jo)1BFBmUa7!%6rw7j<44{-N||ri z>}6ECOvc|Tpiz)xzAXi#G%pwpEN%+PJhK&^u|aZ{Uf zy*rr!?|B25U@H=dbYjE3BwXn-W&N+zQOi0I#NFzS;LeegLAn~&5|{Snf=|<8UK4TvG|LO4Y`aL zBo^B$5L#fSiM{PmnrBQcAJO}6kNUQ1XT+uz*T2gXNqooUJOfwO^B~0!fGE&9~Esx!LI02@P;|bIX^GXfTGM}$6s6o zUg%`Bus*1uU=N7$NZtuVh$&rcq?rf&)siMY1%vmghGeVrJw*h>-#<(cqzh z=23i#_@KW}7BVEE)sv_%{n>~S5``Q2M^ljP76;-WhR*PBmS zHw4%NQ$}{5Wuv`iD7VZfhiWbyXgf>F;*yw249!=JrJIx$D<*4L5_WSdw^CtivKmne z{Ety5)t)(eYLXE(5_1V#Ie;w!9~5ZlR5Wr2p^6mc1y_Q;`9#n3ZbdfD_!v zXxb;4+}5gZxo%JOpkzNirEwt4#T~_%Z#W1Y=+iz7eE44P;)w@?w8GtN zlZ!qUMBR9!`<2m2ktMG)6opzN5?civmhKhn~27;e9OPD+D`TZU%<#%BFW(_>h z7#(TUV?r2)S0SoUgCY^R6mc~I@s|RfaM_2k{{F!UVXyLt9<+qqlW|a^76EuY^S~OM zw~q#@=BCy>VTrmHWo8w3O~s+%vH@9=7Vw78c`#x`sLa9a)^9M!S0-t=_Hu9{vWxA8 zRN3j(>Us|ka8RnO3@-A6>Z)#YSp2qt!Zx>;)2RD>IL*BQc^!j(u%Eov0atQa>2u=@ z;78#F#r*WwX1jJHVbLO;bVI(?_HOlqMe`ntf z#!gWfQq6mWVI@&L3=jJQtOR3<<4__&9GRrvudRd2+{rG)szw(f;W80luBCVg1k8CO zc~}PEXCRg5Omkn|{V?B04P#VS^nj6#^Ey8!Es_p!Q=)G?sHB}8aCYRqZfY* zR|McD8UCm$a;(jg<`IKs-F{6SBDKN*0LmQ=rR=}7^T~!qiCka$;fHR^$lnPml1ETX zl`@g8ZyV;|s^%$+)d2t+yvB^QOeXkFO(j&E)`q3?X!oiu3l~CitAzf9DcG zItk}i0`vLq>D!ZeKNsIKpyE<7iF*~(8`&b)BOP!wsgi7Y4oFEQe8QC`|6{GSB1pS5 zzqRWW`n!1ER|oH^^4vY+OGM!uEnBT8DV<16U5zL6@{cp}1s=IU?{@9}CDky5=2zR{ zJLESD>5f?E*Fam7aV0RZHK-K`e*<=N@=J+S*FV`N2}+-s8JVzi7Vt;e{M*YLJk zUyFOgLlModvcXQpky;ZIW!AS}3ZIjD`n|m*H9(ul`8TgeRE;2~AbyYwiu8Sh$OCfm z>1?Eq#M3xziTQX38Nz4RUCfca-#K9T0OyD!Aq2clyn{woMkkc?QUF-(B*Z~K;U=Q; z74T>CmeSP47lP}bNm6r|{VkV%Z2^}(X{dz^hJ4t(?*;K)bh(^3pTlhuW`|vN?1S}N zTj)4i#D{zd0wa@=C{mT?LtkbfD0@Wyfq3eqJ2!EtL9!F7G*q~=gw3dh)-r{X^mDOy zi^4}mqHFxxa9t@EIG~Qkme5mj4qW}6om+0J$WAd5TvHT*wEL=%P3;rS(sH;%CH%%Q z3}a2MNz=%Z_HWZLgex^;%N>>Z z=XhePI-Y#A;j{|jyk$Hubk9kFDTt19Y6(6ybWqHgxBl)=6Mx5W@=AVu&9uMf z*Y8{Zc=O_mfhijOf&Yv*481@-V>cZq%f4n(l>BdK<|<|%v;R|S$or6~mALIzs-+&Zw6v*z zx_$!>t)xKq3Mi+3i?MEy8uUGbv{F|jB~R;t9ga8Hu%YP#TigLjw5+L-qA6kBlumaY zjr%r9{o`tM!>=`~2a%(d7RWeEj`uDf`!tjPwyE=ZpzB5APW;aRF zK6Y=d2D~XA1CIS@J!}yuyJ=0!YDCzKL-V^CTbQb}QQz~V%KHK~+V7I*lLnxge(A&a z&o(z57G<#SbiSRy6gsQ28ydZKMJuia+2aHI5Jwe#$%X+@(E3vKr$RQPeF9PsAK9f! zbna>%-0<4Je#S8%@M#rK)i^w|TPYg;oBlqN?vOp3j?wbI%k(&iXF5()l`fTFc#zBo zhKQJs#q|Z18jtaTbP0Wj7g0&A!eY@1AFt+J4R?H_$B5D0cUtg@I8C^F*yVhGXD}nR`mEPJ}6t4{?ZQf#eo{vC1kb7 z<(DX)<~M>58Ir;ChwJvqpn!mrLO;+8s7>MECDkAtP{@20J{~Hf|yrfJ%Ou&d(=_ir?0Rd1~d9Gac7#8?Hu?efL diff --git a/icons/obj/machines/minimap_table.dmi b/icons/obj/machines/minimap_table.dmi new file mode 100644 index 0000000000000000000000000000000000000000..bb68f2da612c99a757e86f3c1af51b70f4799cda GIT binary patch literal 991 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 Pj`T1C~oNb23EEfhS=Z>BSmam{=jf%+7=yL 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 W)*@!pmqq_TgK(a%elF{r5}E)c2kQ?2 literal 0 HcmV?d00001 diff --git a/icons/ui_icons/minimap/draw_tools.dmi b/icons/ui_icons/minimap/draw_tools.dmi new file mode 100644 index 0000000000000000000000000000000000000000..ba72a74475e458285c5c85a93aa049d7d30a83dd GIT binary patch literal 603 zcmV-h0;K(kP)w|7QQgSvtG`0004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+ z(=$pSoZ^zil2jm5DJiEkRf&r;C9|j)$Tj5ROe;#vO@*-GigFT@QgaBZs!Ywv$uB3U ztSB{wpqhfxqJkX4?n*66EKV)LrA%4D)z1YSC;(OyPr4o%xX}Or0aQsuK~zYI?Ulc3 z!!QuW-Ik;oqoI2d$zBk70iy>90YS$u)!e0M?dZqu=^V`ckt}-(w7E>D@4ow)QzUiW zgE1WmO9B_3oaQ6*RLJq-l72%(Rj(oHdIeF}p~XcRX7vzkxwNKlF7pPh+j&D%zsH}8ZHz2`PKl=a9}#2x zpm|E^iyDsNoB)6!0KgDd9<^Lg5xJfsj`FCr4C*wu4C*vD4HD5bNCZxaw7@B`mIcHo zZ2|S){HryBwE%=@nGrv9K@Fmi56mFHQs?i(O2ja%LqPpH#7-F&Ah=-xLKx)z-+C|f p{oi^o)cxOjFZ5}@zX$(3egVIoq3JS*IzIpa002ovPDHLkV1j6Q39A4A literal 0 HcmV?d00001 diff --git a/icons/ui_icons/minimap/map_blips.dmi b/icons/ui_icons/minimap/map_blips.dmi new file mode 100644 index 0000000000000000000000000000000000000000..ce7c1e579c9ac1045d8967adc31e29b742ea4cf9 GIT binary patch literal 886 zcmV-+1Bv{JP)sMiA*&iPU1_l5C z00RR9EXD=b007+F+)h_p(IX@H#X6Y*0sjCq|C&LWW;6c)0H|;`w9MLwoTpc4etnOb z92^`oGc*7H|Ns9p`PW9kz`!5#X*B=<00DGTPE!Ct=GbNc0097cR9JLGWpiV4X>fFD zZ*Bkpc$}4!!HUBm5Qfk3DWtuI(l%T6w3pISdf2`~7~>=vFdEdf`1UJVcAG;(EF%1l z-~Zz%uKDqNx!(Bc`^xTU9U0BP_{V0;vIj}u#>FSgTBN4+qjnxVMzxYylMo;ju2?3? zx>($?thUhMul`2|{RZq%dmG9goTGa(UXvx=yr%cDiV8xMMP5v-L*J{g=-F=$d7Mw5 zG8K4ZUmJ_3ahJz2v4KFf+>eL2Uk-gLDa}JKvI?ZcnG;VVgO(JVOStwwvQ!8u(G>*L zdO5g5Ny6Bfr<{POn>4U8odBPNj$L7gRXc~S`T2Glf6EW*L+>*2?V8sB00EjwL_t(I zjg68Gdx9Vog-MisuqY-(l9 zlQApc8PG2*Eht`Dg|crfYu7BBm1VivWP%*nZgXX;>aD6Qum*Iw!MGL_N$34Iq$Cd~xn)k2LyCBi zBsrJ5P617wyEk!)d8dhZ>1m1^_(fVv>f;`fZ1U<#;Wvk9rfG^+4!|UOAaRb^uX3cb z%(>c6bX@lHNL_!<_FpaDV=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#atwj&jMU8Z zj1mZ^xFoS8706UdFG@|#i%-cc&W_JdOH<Br?t8oAT0$WK$K~#9! z?Ug@h8gUfIKbNQ=6e)Btw3(%lVhBb8nQjPX2{`mmz))bvV7;>1nQ@amj<@p1^ ze%TT?20#RYlR?gsd6bv}fD%&(P6i>OqdU28=A2`}!K`zJwoz zKNhFuvLJ=P*Lo~)@|r9HN+Hss;*ZK>;`UPxdFhmTX(pU zQ5)M?rv`0jom~R|!&MIKU7S9VF@3O%0=UB93X@T~gIeXKKA`GxE?6+UB wS!MgePDpADEuqm@+-dD)e_1!5cyi zE*d|0q;uX!^CUx|PQ#p@D`&p+2x+X}p|Vj$^h8+Dqeng`b+p)wcz0S{?h+~vR?JCd z4YwEHFq7egwM3=PME7iV=-0C=2*%CQQQysTJ)2H8$EpiJL);A(E~tc0000>P)t-s0001hfPnx1|Ge`1v)TWl z+~%3gW`v!zK%W0*nKK8C$Yy3{5Ov*OUtc{}V+&fVGiCq?KX)@TGanxx1tLE)0A?2# z7Y`2)00027X)ZMY0007XQchCq$gGRCwCGmVs`AAQVO0ZPikp^6;+Z z|G#u_)sU(bD9dh4lcqTb3J)KrlX;m_GRA1Fl~PU9DBUrdUzBn`WEdQ8qS4w5zN4YQ z@ir1?FrGh0LW9wcpQh2Of0f(=c0i;Jluq&vrjpQ9< zOSdr;lH*-~;zD962LrP&<*<8kfkhv9k;2o+U>s+DeIYy+!Sn7#)_?{GgN2{6-$;jf z+=C$OUao-rRB)X4{N(s_9n?3L`qoz8Tx;9=Ukvc`BI&QLqNuJk6i{I3m9e zI&;7aKtY!!i15V%$c8Tz;1d$~LIL?tXIS}C0r|`20-5? XLoKo&Nev)Y00000NkvXXu0mjfK($|w literal 0 HcmV?d00001 diff --git a/icons/ui_icons/minimap/minimap_mouse/draw_blue.dmi b/icons/ui_icons/minimap/minimap_mouse/draw_blue.dmi new file mode 100644 index 0000000000000000000000000000000000000000..bae80afea3c2292599ab551887ac63ac5d24b91b GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJl&X-35|`BC)e_1!5cyiE*d|0q;uX!^CUx2Pwx&3;~?Y9#$F0@9!)wj zDMTUIv$NY+b@K{|6DCg{`DlBc@on8ORW#;r%mFnfhFRMsxNBE8Is@$s@pN$vskrs_ zk|Eat10I%xfB)b9vfOv_u_KJ(LT%DJqM|#d)?IV|f32)W!^wYo151zHqE@l9g0DZ$ z)e_1!5cyiE*d|0q;uX!^CUx2Pwx&3;~?Y9#$F0@9!)wj zDMTUIv$NY+b@K{|6DCg{`DlBc@on8ORW#;r%mFnfhFRMsxNBE8Is@$s^mK6yskrs_ z+(O<11|rOX{ zg2M`mO22;zF8KKMiI%sn*10q1gExd4Tr__0Nawtd=1GR4p57f6#zDrHjlC4+JeqW5 zQiwvZXJ@yu>gE*^Crq9^^3nD>o; z1qvVjp8@h2c(3hL0#b}6L4Lsu4$p3+0XdGIE{-7;x89yI)e_1!5cyiE*d|0q;uX!^CUx2Pwx&3;~?Y9#$F0@9!)wj zDMTUIv$NY+b@K{|6DCg{`DlBc@on8ORW#;r%mFnfhFRMsxNBE8Is@$s_jGX#skrra z(nih$4g!a_Tz?PEV!k0W^&x>{YH()zDpfnS{S3Iz<5tt>~5=~ z)8l0wN!r0B6FXc~9_`^Ua69l;Mao_3#dO6Mfx03_F{`~Tx3tAy01boFyt=akR{ E0608mH~;_u literal 0 HcmV?d00001 diff --git a/icons/ui_icons/minimap/minimap_mouse/draw_yellow.dmi b/icons/ui_icons/minimap/minimap_mouse/draw_yellow.dmi new file mode 100644 index 0000000000000000000000000000000000000000..5489f87ce4202a8a0570bdbe10568d1b2cbe619d GIT binary patch literal 252 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJl&X-35|`BC)e_1!5cyiE*d|0q;uX!^CUx2Pwx&3;~?Y9#$F0@9!)wj zDMTUIv$NY+b@K{|6DCg{`DlBc@on8ORW#;r%mFnfhFRMsxNBE8Is@$s_H=O!skrra zk|9?^fXLyh|C_)16$k4UDODj6B`&GO$wiq3C7Jno3=9=> zg2M`mO22;zF8KKMiI%sn*10q1gExd4Tr__0Nawtd=1GR4p57f6#zDrHjlC4+JeqW5 zQiwvZXJ@yu>gE*^Crq9^^3nD>}%WQgJIe z;fKG{5r+Ss3_Exmq?k7{OZ#qNTp^)oClYg@;X=!8Rgq&%XL%HO7BU=CmR+#?NTBkH pbe777B4z=%o~A$pE;dO92IdKia@bN2wE|6L@O1TaS?83{1OVyQR|Eh6 literal 0 HcmV?d00001 diff --git a/tgstation.dme b/tgstation.dme index 66d0a665136..7dd74e24b78 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -163,6 +163,7 @@ #include "code\__DEFINES\melee.dm" #include "code\__DEFINES\memory_defines.dm" #include "code\__DEFINES\mergers.dm" +#include "code\__DEFINES\minimap.dm" #include "code\__DEFINES\mining.dm" #include "code\__DEFINES\mob_spawn.dm" #include "code\__DEFINES\mobfactions.dm" @@ -2829,6 +2830,7 @@ #include "code\game\objects\items\implants\implant_spell.dm" #include "code\game\objects\items\implants\implant_stealth.dm" #include "code\game\objects\items\implants\implant_storage.dm" +#include "code\game\objects\items\implants\implant_tacmap.dm" #include "code\game\objects\items\implants\implantcase.dm" #include "code\game\objects\items\implants\implantchair.dm" #include "code\game\objects\items\implants\implanter.dm" @@ -5080,6 +5082,18 @@ #include "code\modules\meteors\meteor_spawning.dm" #include "code\modules\meteors\meteor_types.dm" #include "code\modules\meteors\meteor_waves.dm" +#include "code\modules\minimap\_minimap.dm" +#include "code\modules\minimap\minimap.dm" +#include "code\modules\minimap\minimap_action.dm" +#include "code\modules\minimap\minimap_table.dm" +#include "code\modules\minimap\hud\minimal_z_level.dm" +#include "code\modules\minimap\hud\minimap_dimmer.dm" +#include "code\modules\minimap\hud\minimap_display.dm" +#include "code\modules\minimap\hud\minimap_drawing.dm" +#include "code\modules\minimap\hud\minimap_element.dm" +#include "code\modules\minimap\hud\minimap_label.dm" +#include "code\modules\minimap\hud\minimap_toolbar.dm" +#include "code\modules\minimap\hud\minimap_tracking_blip.dm" #include "code\modules\mining\aux_base.dm" #include "code\modules\mining\fulton.dm" #include "code\modules\mining\machine_processing.dm"