From e5d3527319c4f1ef46f8cddb006054455c13345a Mon Sep 17 00:00:00 2001 From: dageavtobusnick <71216640+dageavtobusnick@users.noreply.github.com> Date: Sun, 5 Jan 2025 04:43:43 +0500 Subject: [PATCH] port: supply pods launcher admin button (#6305) * port: supply pods launcher admin button * fix * light fix * Reverce pods fix + map fix * limb effect fix * Update tgui.bundle.js * conflicts fixes * Update tgui.bundle.js --- _maps/map_files/generic/CentComm.dmm | 1959 +++++++++++------ code/__DEFINES/cargo.dm | 37 + code/__DEFINES/dcs/signals_object.dm | 10 + code/__DEFINES/is_helpers.dm | 6 + code/__DEFINES/obj_flags.dm | 3 + code/__DEFINES/traits/declarations.dm | 2 + code/__HELPERS/turfs.dm | 27 + code/_globalvars/lists/objects.dm | 2 + code/_onclick/hud/map_view.dm | 2 +- code/datums/components/pellet_cloud.dm | 325 +++ code/datums/pod_style.dm | 258 +++ code/game/area/ss13_areas.dm | 46 + code/game/atoms.dm | 6 + code/game/objects/effects/misc.dm | 4 + .../items/weapons/grenades/atmosgrenade.dm | 1 + .../items/weapons/grenades/bananade.dm | 1 + .../items/weapons/grenades/chem_grenade.dm | 1 + .../items/weapons/grenades/clowngrenade.dm | 2 +- .../items/weapons/grenades/clusterbuster.dm | 1 + .../items/weapons/grenades/confetti.dm | 1 + .../items/weapons/grenades/emgrenade.dm | 1 + .../items/weapons/grenades/fauna_bomb.dm | 1 + .../items/weapons/grenades/flashbang.dm | 1 + .../objects/items/weapons/grenades/frag.dm | 1 + .../items/weapons/grenades/ghettobomb.dm | 1 + .../objects/items/weapons/grenades/grenade.dm | 1 + .../items/weapons/grenades/smokebomb.dm | 1 + .../items/weapons/grenades/spawnergrenade.dm | 2 +- .../items/weapons/grenades/syndieminibomb.dm | 1 + .../structures/crates_lockers/closets.dm | 34 +- code/modules/admin/admin_verbs.dm | 23 +- code/modules/admin/verbs/cantcomm_cargo.dm | 18 + code/modules/asset_cache/assets/supplypods.dm | 27 + code/modules/buildmode/submodes/boom.dm | 17 +- code/modules/cargo/centcom_podlauncher.dm | 872 ++++++++ code/modules/cargo/supplypod.dm | 767 +++++++ code/modules/hallucination/_hallucination.dm | 123 ++ code/modules/mob/living/carbon/brain/brain.dm | 7 + .../living/simple_animal/gondolas/gondola.dm | 74 + .../simple_animal/gondolas/gondolapod.dm | 95 + code/modules/mob/mob.dm | 11 + code/modules/mob/mob_helpers.dm | 11 + code/modules/projectiles/firing.dm | 3 +- code/modules/projectiles/projectile.dm | 6 +- .../projectiles/projectile/shrapnel.dm | 28 + .../mouse_pointers/supplypod_down_target.dmi | Bin 0 -> 464 bytes .../mouse_pointers/supplypod_pickturf.dmi | Bin 0 -> 336 bytes .../supplypod_pickturf_down.dmi | Bin 0 -> 322 bytes .../mouse_pointers/supplypod_target.dmi | Bin 0 -> 392 bytes icons/mob/actions/actions.dmi | Bin 250081 -> 247049 bytes icons/mob/gondolas.dmi | Bin 0 -> 1269 bytes icons/obj/supplypods.dmi | Bin 0 -> 27073 bytes icons/obj/supplypods_32x32.dmi | Bin 0 -> 3393 bytes icons/turf/areas.dmi | Bin 60790 -> 60901 bytes paradise.dme | 12 + sound/effects/podwoosh.ogg | Bin 0 -> 56988 bytes sound/weapons/mortar_long_whistle.ogg | Bin 0 -> 14156 bytes sound/weapons/mortar_whistle.ogg | Bin 0 -> 6885 bytes .../CentcomPodLauncher/DelayHelper.tsx | 63 + .../interfaces/CentcomPodLauncher/PodBays.tsx | 52 + .../CentcomPodLauncher/PodLaunch.tsx | 28 + .../CentcomPodLauncher/PodSounds.tsx | 40 + .../CentcomPodLauncher/PodStatusPage.tsx | 132 ++ .../CentcomPodLauncher/PresetsPage.tsx | 230 ++ .../CentcomPodLauncher/ReverseMenu.tsx | 99 + .../CentcomPodLauncher/StylePage.tsx | 65 + .../interfaces/CentcomPodLauncher/Tabs.tsx | 87 + .../interfaces/CentcomPodLauncher/Timing.tsx | 47 + .../CentcomPodLauncher/ViewTabHolder.tsx | 100 + .../CentcomPodLauncher/constants.ts | 314 +++ .../interfaces/CentcomPodLauncher/hooks.ts | 5 + .../interfaces/CentcomPodLauncher/index.tsx | 74 + .../interfaces/CentcomPodLauncher/types.ts | 70 + tgui/public/tgui.bundle.js | 172 +- 74 files changed, 5576 insertions(+), 834 deletions(-) create mode 100644 code/__DEFINES/cargo.dm create mode 100644 code/__HELPERS/turfs.dm create mode 100644 code/datums/components/pellet_cloud.dm create mode 100644 code/datums/pod_style.dm create mode 100644 code/modules/admin/verbs/cantcomm_cargo.dm create mode 100644 code/modules/asset_cache/assets/supplypods.dm create mode 100644 code/modules/cargo/centcom_podlauncher.dm create mode 100644 code/modules/cargo/supplypod.dm create mode 100644 code/modules/hallucination/_hallucination.dm create mode 100644 code/modules/mob/living/simple_animal/gondolas/gondola.dm create mode 100644 code/modules/mob/living/simple_animal/gondolas/gondolapod.dm create mode 100644 code/modules/projectiles/projectile/shrapnel.dm create mode 100644 icons/effects/mouse_pointers/supplypod_down_target.dmi create mode 100644 icons/effects/mouse_pointers/supplypod_pickturf.dmi create mode 100644 icons/effects/mouse_pointers/supplypod_pickturf_down.dmi create mode 100644 icons/effects/mouse_pointers/supplypod_target.dmi create mode 100644 icons/mob/gondolas.dmi create mode 100644 icons/obj/supplypods.dmi create mode 100644 icons/obj/supplypods_32x32.dmi create mode 100644 sound/effects/podwoosh.ogg create mode 100644 sound/weapons/mortar_long_whistle.ogg create mode 100644 sound/weapons/mortar_whistle.ogg create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/DelayHelper.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/PodBays.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/PodLaunch.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/PodSounds.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/PodStatusPage.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/PresetsPage.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/ReverseMenu.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/StylePage.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/Tabs.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/Timing.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/ViewTabHolder.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/constants.ts create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/hooks.ts create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/index.tsx create mode 100644 tgui/packages/tgui/interfaces/CentcomPodLauncher/types.ts diff --git a/_maps/map_files/generic/CentComm.dmm b/_maps/map_files/generic/CentComm.dmm index d1fe6bbc576..f1d20573346 100644 --- a/_maps/map_files/generic/CentComm.dmm +++ b/_maps/map_files/generic/CentComm.dmm @@ -219,8 +219,8 @@ pixel_y = 6 }, /obj/item/paper/monitorkey{ - pixel_y = 4; - pixel_x = 3 + pixel_x = 3; + pixel_y = 4 }, /obj/item/paper/safe_code{ owner = "captain"; @@ -228,8 +228,8 @@ }, /obj/item/paper/safe_code{ owner = "hos"; - pixel_y = -2; - pixel_x = -3 + pixel_x = -3; + pixel_y = -2 }, /turf/simulated/floor/carpet/cyan, /area/centcom/zone2) @@ -311,6 +311,11 @@ icon_state = "darkredcorners" }, /area/syndicate_mothership/elite_squad) +"aeQ" = ( +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supplypod/loading/one) "aeY" = ( /obj/item/deck/cards, /obj/structure/table/wood, @@ -514,6 +519,12 @@ }, /turf/simulated/wall/indestructible/reinforced, /area/centcom/zone3) +"aiB" = ( +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "aiQ" = ( /obj/structure/table, /obj/item/storage/box/cups, @@ -807,8 +818,8 @@ /area/centcom/specops) "apl" = ( /obj/structure/falsewall/reinforced{ - req_access = list(114); - layer = 5 + layer = 5; + req_access = list(114) }, /turf/simulated/floor/fakespace, /area/centcom/specops) @@ -1217,8 +1228,8 @@ "ayt" = ( /obj/machinery/syndiepad/receivepad, /obj/machinery/conveyor{ - id = "SFBQMLoad"; - dir = 8 + dir = 8; + id = "SFBQMLoad" }, /turf/simulated/floor/plasteel{ dir = 1; @@ -1451,6 +1462,11 @@ name = "floor" }, /area/syndicate_mothership/outside) +"aDR" = ( +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supply) "aDX" = ( /obj/machinery/computer/syndie_supplycomp, /turf/simulated/floor/plasteel{ @@ -1572,6 +1588,12 @@ name = "floor" }, /area/vox_station) +"aHe" = ( +/turf/simulated/floor/plasteel{ + dir = 10; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "aHf" = ( /obj/item/target, /obj/effect/decal/cleanable/confetti, @@ -1813,8 +1835,8 @@ "aLo" = ( /obj/effect/decal/warning_stripes/yellow/hollow, /obj/machinery/conveyor{ - id = "CO2"; - dir = 1 + dir = 1; + id = "CO2" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -1925,10 +1947,10 @@ "aOA" = ( /obj/machinery/door_control/secure{ id = "CC_Armory_SRT1"; - pixel_y = -25; - req_access = list(114); + name = "SRT Team 2"; pixel_x = -25; - name = "SRT Team 2" + pixel_y = -25; + req_access = list(114) }, /turf/simulated/floor/plasteel{ icon_state = "navybluealtstrip" @@ -1975,6 +1997,12 @@ name = "floor" }, /area/syndicate_mothership) +"aOM" = ( +/turf/simulated/floor/plasteel{ + dir = 6; + icon_state = "darkyellowalt" + }, +/area/centcom/supply) "aOO" = ( /obj/effect/turf_decal/siding/yellow{ dir = 1 @@ -2173,8 +2201,8 @@ /obj/structure/bed, /obj/item/bedsheet/rd, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet/arcade, /area/centcom/zone1) @@ -2309,6 +2337,12 @@ /obj/item/toy/desk/fan, /turf/simulated/floor/carpet/black, /area/centcom/zone2) +"aYk" = ( +/turf/simulated/floor/plasteel{ + dir = 6; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "aYm" = ( /obj/structure/window/plasmareinforced{ color = "#00f700"; @@ -2976,11 +3010,11 @@ layer = 9 }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 175; teleport_y = 62; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -3327,10 +3361,10 @@ height = 5; id = "sit"; name = "SIT shuttle"; - roundstart_move = "sit_away"; - width = 11; port_direction = 4; - preferred_direction = 2 + preferred_direction = 2; + roundstart_move = "sit_away"; + width = 11 }, /obj/docking_port/stationary{ dir = 4; @@ -3404,8 +3438,9 @@ }, /area/centcom/specops) "bBe" = ( -/obj/machinery/vending/ntcrates, -/turf/simulated/floor/plating, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, /area/centcom/specops) "bBg" = ( /obj/machinery/embedded_controller/radio/airlock/airlock_controller{ @@ -3524,12 +3559,12 @@ /obj/item/clothing/accessory/holster, /obj/item/storage/backpack/satcheldeluxe, /obj/item/reagent_containers/food/drinks/bottle/vodka/badminka{ - pixel_y = 8; - pixel_x = -4 + pixel_x = -4; + pixel_y = 8 }, /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{ - pixel_y = 12; - pixel_x = 10 + pixel_x = 10; + pixel_y = 12 }, /obj/item/megaphone, /turf/simulated/floor/carpet/black, @@ -3600,6 +3635,12 @@ icon_state = "fancy-wood-oak" }, /area/syndicate_mothership) +"bEA" = ( +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "bEB" = ( /obj/structure/showcase{ desc = "This one has an old damaged suit in it. Not working..."; @@ -3622,8 +3663,8 @@ /area/shuttle/syndicate) "bEW" = ( /obj/structure/railing{ - pixel_y = 32; - density = 0 + density = 0; + pixel_y = 32 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -3747,6 +3788,11 @@ icon_state = "dark" }, /area/centcom/specops) +"bIN" = ( +/turf/simulated/floor/plasteel{ + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "bIU" = ( /obj/machinery/smartfridge/secure/chemistry/preloaded/syndicate, /turf/simulated/floor/plasteel{ @@ -3996,6 +4042,12 @@ icon_state = "floorgrime" }, /area/ninja/holding) +"bRZ" = ( +/turf/simulated/floor/plasteel{ + dir = 6; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "bSd" = ( /obj/structure/window/reinforced{ dir = 4 @@ -4508,11 +4560,11 @@ name = "Escape Pod Hatch" }, /obj/docking_port/mobile/pod{ + dir = 8; id = "pod2"; name = "escape pod 2"; - roundstart_move = "pod2_home"; - dir = 8; - port_direction = 2 + port_direction = 2; + roundstart_move = "pod2_home" }, /obj/docking_port/stationary{ dir = 8; @@ -4780,36 +4832,36 @@ /obj/structure/table/reinforced, /obj/machinery/door_control/secure{ id = "CC_space_jail_sec"; - pixel_y = -6; - pixel_x = -7 + pixel_x = -7; + pixel_y = -6 }, /obj/machinery/embedded_controller/radio/airlock/access_controller{ frequency = 2000; id_tag = "CC-OP4"; name = "Access Controller OP4"; + pixel_x = -7; pixel_y = 6; req_access = list(109); tag_exterior_door = "CC-OP4-Ext"; - tag_interior_door = "CC-OP4-Int"; - pixel_x = -7 + tag_interior_door = "CC-OP4-Int" }, /obj/machinery/door_control/secure{ - id = "CC_space_jail_cell"; - pixel_y = -6; - pixel_x = 7; color = "#FFA500"; + id = "CC_space_jail_cell"; name = "remote cell shutters control"; + pixel_x = 7; + pixel_y = -6; req_access = list(104,114) }, /obj/machinery/door_control/secure{ - id = "CC_space_jail_door"; - pixel_y = 6; - pixel_x = 7; color = "#ffaaaa"; + id = "CC_space_jail_door"; name = "remote cell door bolts control"; + normaldoorcontrol = 1; + pixel_x = 7; + pixel_y = 6; req_access = list(104,114); - specialfunctions = 4; - normaldoorcontrol = 1 + specialfunctions = 4 }, /turf/simulated/floor/plasteel{ dir = 5; @@ -5099,11 +5151,11 @@ name = "Escape Pod Hatch" }, /obj/docking_port/mobile/pod{ + dir = 4; id = "pod4"; name = "escape pod 4"; - roundstart_move = "pod4_home"; - dir = 4; - port_direction = 2 + port_direction = 2; + roundstart_move = "pod4_home" }, /obj/docking_port/stationary{ dir = 4; @@ -5214,8 +5266,8 @@ /obj/structure/bed, /obj/item/bedsheet/red, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet/arcade, /area/centcom/zone1) @@ -5540,6 +5592,12 @@ name = "floor" }, /area/syndicate_mothership) +"czW" = ( +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "cAA" = ( /obj/item/flag/nt, /turf/simulated/floor/plasteel{ @@ -5547,6 +5605,15 @@ icon_state = "navybluealt" }, /area/centcom/specops) +"cAU" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "cBk" = ( /obj/structure/sign/poster/official/ue_no, /turf/simulated/wall/indestructible/sandstone, @@ -5845,6 +5912,12 @@ name = "floor" }, /area/vox_station) +"cJx" = ( +/turf/simulated/floor/plasteel{ + dir = 10; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "cJJ" = ( /obj/effect/turf_decal{ dir = 8; @@ -5945,8 +6018,8 @@ /area/centcom/zone2) "cKU" = ( /obj/machinery/conveyor_switch/oneway{ - id = "SFBQMLoad2"; - dir = 8 + dir = 8; + id = "SFBQMLoad2" }, /turf/simulated/floor/plasteel{ dir = 1; @@ -6001,8 +6074,8 @@ dir = 4 }, /obj/structure/window/reinforced{ - layer = 3.1; - armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100) + armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100); + layer = 3.1 }, /turf/simulated/floor/plasteel{ dir = 8; @@ -6250,11 +6323,11 @@ layer = 9 }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 175; teleport_y = 63; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -6466,8 +6539,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 1; id_tag = "ERT_armory_lvl2"; - name = "Armory level 2"; - layer = 5 + layer = 5; + name = "Armory level 2" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -6766,10 +6839,10 @@ height = 5; id = "laborcamp"; name = "labor camp shuttle"; + port_direction = 4; rebuildable = 1; roundstart_move = "laborcamp_home"; - width = 9; - port_direction = 4 + width = 9 }, /obj/structure/fans/tiny, /turf/simulated/floor/shuttle, @@ -6872,7 +6945,7 @@ pixel_y = 32 }, /turf/simulated/floor/plasteel{ - dir = 5; + dir = 1; icon_state = "darkyellowalt" }, /area/centcom/supply) @@ -6980,8 +7053,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 2; id_tag = "ERT_armory_lvl3"; - name = "Armory level 3"; - layer = 5 + layer = 5; + name = "Armory level 3" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -7082,11 +7155,11 @@ name = "Escape Pod Hatch" }, /obj/docking_port/mobile/pod{ + dir = 8; id = "pod1"; name = "escape pod 1"; - roundstart_move = "pod1_home"; - dir = 8; - port_direction = 2 + port_direction = 2; + roundstart_move = "pod1_home" }, /obj/docking_port/stationary{ dir = 8; @@ -7109,6 +7182,12 @@ tag = "icon-stage_stairs" }, /area/ninja/holding) +"dtp" = ( +/turf/simulated/floor/plasteel{ + dir = 10; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "dtu" = ( /obj/structure/flora/ausbushes/reedbush, /turf/simulated/floor/indestructible/beach/coastline{ @@ -7467,11 +7546,11 @@ name = "Escape Pod Hatch" }, /obj/docking_port/mobile/pod{ + dir = 4; id = "pod3"; name = "escape pod 3"; - roundstart_move = "pod3_home"; - dir = 4; - port_direction = 2 + port_direction = 2; + roundstart_move = "pod3_home" }, /obj/docking_port/stationary{ dir = 4; @@ -7700,10 +7779,10 @@ /area/vox_station) "dEV" = ( /obj/machinery/door/airlock/external{ + hackProof = 1; id_tag = "supply_away"; name = "Central Command Supply"; - req_access = list(31); - hackProof = 1 + req_access = list(31) }, /obj/machinery/door/poddoor{ id_tag = "CC_supply_space"; @@ -7785,9 +7864,9 @@ "dGB" = ( /obj/effect/decal/warning_stripes/northwestsouth, /obj/machinery/door/poddoor/shutters/preopen/invincible{ + dir = 2; id_tag = "ERT_armory_lvl1"; - name = "Armory level 1"; - dir = 2 + name = "Armory level 1" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -7845,8 +7924,8 @@ req_access = list(114) }, /turf/simulated/floor/plasteel{ - icon_state = "darkgreencorners"; - dir = 1 + dir = 1; + icon_state = "darkgreencorners" }, /area/centcom/specops) "dIi" = ( @@ -8109,11 +8188,11 @@ layer = 9 }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 183; teleport_y = 60; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -8185,6 +8264,15 @@ "dTg" = ( /turf/simulated/floor/plating/airless, /area/centcom/specops) +"dTt" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "dTy" = ( /obj/structure/railing{ dir = 8 @@ -8565,10 +8653,10 @@ height = 18; id = "admin"; name = "administration shuttle"; - roundstart_move = "admin_away"; - width = 18; port_direction = 2; - preferred_direction = 8 + preferred_direction = 8; + roundstart_move = "admin_away"; + width = 18 }, /obj/machinery/door/airlock/external{ frequency = 1331; @@ -8991,8 +9079,8 @@ name = "Любимая игрушка бюрократов" }, /obj/item/reagent_containers/food/drinks/coffee{ - pixel_y = 9; - pixel_x = 6 + pixel_x = 6; + pixel_y = 9 }, /turf/simulated/floor/carpet/black, /area/centcom/zone2) @@ -9210,11 +9298,11 @@ /area/shuttle/administration) "erZ" = ( /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 137; teleport_y = 65; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -9387,8 +9475,8 @@ /area/centcom/zone3) "evD" = ( /obj/structure/falsewall/reinforced{ - req_access = list(114); - layer = 5 + layer = 5; + req_access = list(114) }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -9630,6 +9718,11 @@ }, /turf/simulated/floor/carpet/red, /area/syndicate_mothership/control) +"eDu" = ( +/turf/simulated/floor/plasteel{ + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "eDO" = ( /obj/effect/spawner/lootdrop/trade_sol/largeitem, /turf/simulated/floor/wood{ @@ -9730,6 +9823,15 @@ /obj/machinery/light/small, /turf/simulated/floor/wood/fancy/light, /area/ussp_centcom/secretariat) +"eGx" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "eHj" = ( /obj/item/storage/firstaid/ancient{ pixel_x = 3; @@ -10133,8 +10235,8 @@ name = "Supply Blastdoor" }, /obj/machinery/conveyor{ - id = "CC_crate"; - dir = 1 + dir = 1; + id = "CC_crate" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -10471,6 +10573,12 @@ icon_state = "darkyellowcornersalt" }, /area/centcom/zone3) +"eZq" = ( +/turf/simulated/floor/plasteel{ + dir = 6; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "eZx" = ( /obj/structure/table/wood, /obj/item/reagent_containers/glass/beaker/waterbottle/large{ @@ -10537,9 +10645,9 @@ }, /obj/effect/turf_decal/tile/neutral{ alpha = 85; + icon = 'icons/misc/beach.dmi'; icon_state = "seadeep"; - layer = 9; - icon = 'icons/misc/beach.dmi' + layer = 9 }, /turf/simulated/floor/indestructible/beach/water/deep/sand_floor, /area/centcom/specops) @@ -10788,8 +10896,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 1; id_tag = "ERT_armory_lvl4"; - name = "Armory level 4"; - layer = 5 + layer = 5; + name = "Armory level 4" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -11272,8 +11380,8 @@ /obj/structure/bed, /obj/item/bedsheet/wiz, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet, /area/centcom/zone1) @@ -11283,10 +11391,10 @@ color = "#666666"; damtype = "burn"; health = 1250; + name = "Quarantine Pulse Turret"; region_max = 12; scan_range = 12; - shot_delay = 8; - name = "Quarantine Pulse Turret" + shot_delay = 8 }, /obj/machinery/door/poddoor/shutters/invincible/fake_r_wall{ dir = 1; @@ -11678,8 +11786,8 @@ req_access = list(114) }, /turf/simulated/floor/plasteel{ - icon_state = "darkyellowcorners"; - dir = 1 + dir = 1; + icon_state = "darkyellowcorners" }, /area/centcom/specops) "fCZ" = ( @@ -11712,8 +11820,8 @@ "fDh" = ( /obj/machinery/camera{ c_tag = "CentComm Special Ops. Shuttle"; - network = list("ERT","CentComm"); - dir = 4 + dir = 4; + network = list("ERT","CentComm") }, /obj/machinery/recharge_station/ert, /turf/simulated/floor/shuttle{ @@ -11917,9 +12025,9 @@ /area/ninja/outpost) "fHe" = ( /obj/structure/window/reinforced{ + armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100); dir = 1; - layer = 2; - armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100) + layer = 2 }, /turf/simulated/floor/plasteel{ dir = 1; @@ -11972,6 +12080,16 @@ icon_state = "darkgreenfull" }, /area/centcom/specops) +"fJp" = ( +/obj/machinery/door_control/secure{ + id = "ShitRainSupply"; + pixel_x = 24; + pixel_y = 24 + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/specops) "fJz" = ( /obj/machinery/door/poddoor/shutters/invincible{ dir = 2; @@ -12292,6 +12410,12 @@ }, /turf/simulated/floor/carpet/black, /area/ninja/outpost) +"fRi" = ( +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "darkyellowalt" + }, +/area/centcom/supply) "fRH" = ( /obj/machinery/light/small{ dir = 4 @@ -12375,14 +12499,14 @@ /area/syndicate_mothership/control) "fUK" = ( /obj/structure/window/reinforced/survival_pod{ + density = 0; dir = 9; - pixel_y = 1; pixel_x = -1; - density = 0 + pixel_y = 1 }, /obj/structure/fishingrodcabinet{ - pixel_y = 32; - pixel_x = 3 + pixel_x = 3; + pixel_y = 32 }, /turf/simulated/floor/plasteel{ dir = 5; @@ -13262,15 +13386,15 @@ }, /obj/structure/fans/tiny, /obj/docking_port/mobile{ + alone_shuttle = 1; dir = 8; dwidth = 2; height = 5; id = "ruins_transport_shuttle"; name = "USSP Cargo Shuttle"; + port_direction = 4; roundstart_move = "ussp_dock"; - alone_shuttle = 1; - width = 8; - port_direction = 4 + width = 8 }, /turf/simulated/floor/shuttle{ icon_state = "floor4" @@ -13309,13 +13433,13 @@ id = "SFBQMLoad" }, /obj/machinery/conveyor{ - id = "SFBQMLoad"; dir = 8; + id = "SFBQMLoad"; layer = 2.494 }, /obj/machinery/conveyor{ - id = "SFBQMLoad"; dir = 4; + id = "SFBQMLoad"; layer = 2.494 }, /turf/simulated/floor/plasteel{ @@ -13575,6 +13699,12 @@ }, /turf/simulated/floor/wood/fancy/light, /area/ninja/outpost) +"gxu" = ( +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "gyg" = ( /obj/effect/turf_decal/siding/wood{ dir = 6 @@ -13688,9 +13818,9 @@ /area/syndicate_mothership/control) "gAp" = ( /obj/structure/closet/cardboard{ - icon_state = "cardboard_librarian"; icon_closed = "cardboard_librarian"; - icon_opened = "cardboard_librarian_open" + icon_opened = "cardboard_librarian_open"; + icon_state = "cardboard_librarian" }, /obj/item/paper/central_command/archive/memes{ info = "
"; @@ -13763,6 +13893,12 @@ icon_state = "darkfull" }, /area/syndicate_mothership/jail) +"gDh" = ( +/turf/simulated/floor/plasteel{ + dir = 9; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "gDk" = ( /obj/machinery/mech_bay_recharge_port{ dir = 8 @@ -13932,6 +14068,12 @@ }, /turf/simulated/floor/indestructible/asteroid, /area/syndicate_mothership/outside) +"gIp" = ( +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "gIz" = ( /obj/effect/decal/cleanable/confetti, /turf/simulated/floor/plasteel{ @@ -14478,6 +14620,12 @@ icon_state = "dark" }, /area/centcom/jail) +"gYf" = ( +/turf/simulated/floor/plasteel{ + dir = 10; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "gYq" = ( /obj/effect/turf_decal/stripes/asteroid/corner{ dir = 4 @@ -14694,14 +14842,14 @@ name = "Food CC Spawner #1" }, /obj/structure/window/reinforced/survival_pod{ + density = 0; dir = 6; - pixel_y = -1; pixel_x = 1; - density = 0 + pixel_y = -1 }, /obj/structure/window/reinforced{ - layer = 3.1; - armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100) + armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100); + layer = 3.1 }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -15094,6 +15242,12 @@ icon_state = "freezerfloor" }, /area/syndicate_mothership) +"hsP" = ( +/turf/simulated/floor/plasteel{ + dir = 10; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "hsS" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -15118,6 +15272,12 @@ icon_state = "darkyellowaltstrip" }, /area/centcom/zone3) +"htF" = ( +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "htL" = ( /obj/structure/flora/grass/brown, /obj/structure/flora/grass/both, @@ -15716,6 +15876,11 @@ /obj/effect/turf_decal/siding/wood/corner, /turf/simulated/floor/carpet/cyan, /area/ninja/outpost) +"hLb" = ( +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supplypod/loading/three) "hLh" = ( /turf/simulated/floor/indestructible/grass, /area/ninja/outside) @@ -15876,15 +16041,15 @@ "hNK" = ( /obj/structure/chair/sofa/right, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet/arcade, /area/centcom/zone1) "hNX" = ( /obj/structure/railing{ - layer = 4.3; - density = 0 + density = 0; + layer = 4.3 }, /obj/effect/turf_decal/tile/neutral{ color = "black"; @@ -15962,6 +16127,12 @@ }, /turf/simulated/floor/shuttle/plating, /area/shuttle/specops) +"hQZ" = ( +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "hRt" = ( /obj/structure/curtain/open/shower/security, /turf/simulated/wall/indestructible/fakeglass, @@ -16049,8 +16220,8 @@ /area/centcom/specops) "hTK" = ( /obj/machinery/conveyor{ - id = "SFBQMLoad2"; - dir = 5 + dir = 5; + id = "SFBQMLoad2" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -16170,9 +16341,9 @@ "hYY" = ( /obj/effect/decal/warning_stripes/northeastsouth, /obj/machinery/door/poddoor/shutters/preopen/invincible{ + dir = 2; id_tag = "ERT_armory_lvl1"; - name = "Armory level 1"; - dir = 2 + name = "Armory level 1" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -16315,8 +16486,8 @@ /area/ninja/outpost) "idQ" = ( /obj/machinery/conveyor/inverted{ - id = "CC_crate"; - dir = 10 + dir = 10; + id = "CC_crate" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -16454,8 +16625,8 @@ /obj/docking_port/mobile/emergency{ dwidth = 11; height = 18; - width = 29; - port_direction = 8 + port_direction = 8; + width = 29 }, /obj/docking_port/stationary{ dir = 4; @@ -16641,6 +16812,11 @@ icon_state = "alien18" }, /area/abductor_ship) +"ilJ" = ( +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supplypod/loading/two) "imw" = ( /obj/machinery/light{ dir = 1 @@ -16996,6 +17172,12 @@ icon_state = "floor12" }, /area/shuttle/syndicate) +"iuR" = ( +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "ivb" = ( /obj/machinery/door_control/secure{ id = "Admin_shuttle_access"; @@ -17420,10 +17602,10 @@ height = 5; id = "sst"; name = "SST shuttle"; - roundstart_move = "sst_away"; - width = 11; port_direction = 8; - preferred_direction = 2 + preferred_direction = 2; + roundstart_move = "sst_away"; + width = 11 }, /obj/docking_port/stationary{ dir = 8; @@ -17442,10 +17624,10 @@ color = "#666666"; damtype = "burn"; health = 1250; + name = "Quarantine Pulse Turret"; region_max = 12; scan_range = 12; - shot_delay = 8; - name = "Quarantine Pulse Turret" + shot_delay = 8 }, /obj/machinery/door/poddoor/shutters/invincible/fake_r_wall{ dir = 2; @@ -17624,11 +17806,11 @@ layer = 9 }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 183; teleport_y = 63; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -17989,6 +18171,12 @@ icon_state = "dark" }, /area/syndicate_mothership/control) +"iRY" = ( +/obj/machinery/light, +/turf/simulated/floor/plasteel{ + icon_state = "darkyellowalt" + }, +/area/centcom/supply) "iSs" = ( /obj/effect/turf_decal{ dir = 5; @@ -18507,6 +18695,12 @@ }, /turf/simulated/floor/indestructible/asteroid, /area/syndicate_mothership/outside) +"jfm" = ( +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "jfv" = ( /obj/machinery/computer/shuttle/ruins_transport_shuttle, /turf/simulated/floor/shuttle{ @@ -18695,10 +18889,10 @@ "jkL" = ( /obj/machinery/door_control/secure{ id = "CC_Armory_SRT"; - pixel_y = -25; - req_access = list(114); + name = "SRT Team 1"; pixel_x = 25; - name = "SRT Team 1" + pixel_y = -25; + req_access = list(114) }, /turf/simulated/floor/plasteel{ icon_state = "navybluealtstrip" @@ -19038,8 +19232,8 @@ /area/syndicate_mothership/outside) "jsa" = ( /obj/machinery/conveyor/inverted{ - id = "SFBQMLoad2"; - dir = 6 + dir = 6; + id = "SFBQMLoad2" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -19465,6 +19659,15 @@ /obj/structure/filingcabinet/employment, /turf/simulated/floor/bluegrid, /area/centcom/bridge) +"jCl" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "jCo" = ( /obj/structure/chair, /obj/effect/decal/cleanable/blood, @@ -19673,8 +19876,8 @@ /obj/machinery/door_control/secure{ id = "CC_supply_external2"; name = "Supply Internal Shutters"; - req_access = list(114); - pixel_x = -24 + pixel_x = -24; + req_access = list(114) }, /turf/simulated/floor/plasteel{ dir = 8; @@ -19697,16 +19900,16 @@ }, /obj/structure/fans/tiny, /obj/docking_port/mobile{ + alone_shuttle = 1; dir = 8; dwidth = 3; height = 4; id = "ruins_civil_shuttle"; name = "Regular Civilian Shuttle"; + port_direction = 4; rebuildable = 1; roundstart_move = "spacebar"; - alone_shuttle = 1; - width = 6; - port_direction = 4 + width = 6 }, /turf/simulated/floor/shuttle{ icon_state = "floor3" @@ -19742,8 +19945,8 @@ dir = 4 }, /obj/machinery/conveyor{ - id = "N2"; - dir = 1 + dir = 1; + id = "N2" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -19827,6 +20030,18 @@ "jJA" = ( /turf/simulated/floor/carpet/red, /area/shuttle/administration) +"jJD" = ( +/obj/machinery/door_control/secure{ + id = "ERT_Supply_Pod"; + name = "ERT Supply Pod Loading Zone"; + pixel_x = 24; + pixel_y = 24; + req_access = list(114) + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/specops) "jJS" = ( /turf/simulated/floor/plasteel{ dir = 4; @@ -20041,10 +20256,10 @@ height = 5; id = "mining"; name = "mining shuttle"; + port_direction = 4; rebuildable = 1; roundstart_move = "mining_home"; - width = 7; - port_direction = 4 + width = 7 }, /obj/structure/fans/tiny, /obj/machinery/door/airlock/shuttle{ @@ -20345,6 +20560,12 @@ water_overlay_icon_state = null }, /area/syndicate_mothership/outside) +"jXp" = ( +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "jXt" = ( /obj/structure/window/reinforced{ dir = 8 @@ -20556,6 +20777,15 @@ }, /turf/simulated/floor/carpet/arcade, /area/syndicate_mothership/infteam) +"kek" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "keo" = ( /turf/simulated/wall/indestructible/iron, /area/syndicate_mothership) @@ -20848,11 +21078,11 @@ layer = 9 }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 183; teleport_y = 62; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -20873,8 +21103,8 @@ dir = 8 }, /turf/simulated/floor/plasteel{ - icon_state = "arrival"; - dir = 10 + dir = 10; + icon_state = "arrival" }, /area/centcom/evac) "kio" = ( @@ -20994,10 +21224,10 @@ color = "#666666"; damtype = "burn"; health = 1250; + name = "Quarantine Pulse Turret"; region_max = 12; scan_range = 12; - shot_delay = 8; - name = "Quarantine Pulse Turret" + shot_delay = 8 }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -21262,8 +21492,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 1; id_tag = "ERT_armory_lvl4"; - name = "Armory level 4"; - layer = 5 + layer = 5; + name = "Armory level 4" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -21288,8 +21518,8 @@ /area/syndicate_mothership/control) "kse" = ( /obj/structure/window/reinforced{ - layer = 3.1; - armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100) + armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100); + layer = 3.1 }, /turf/simulated/floor/wood{ icon_state = "light-fancy-wood" @@ -21513,11 +21743,11 @@ layer = 9 }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 183; teleport_y = 61; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -21787,9 +22017,9 @@ /area/syndicate_mothership/elite_squad) "kGN" = ( /obj/structure/window/reinforced{ + armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100); dir = 1; - layer = 2; - armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100) + layer = 2 }, /turf/simulated/floor/plasteel{ dir = 5; @@ -22357,10 +22587,10 @@ height = 18; id = "trade_sol"; name = "sol trade shuttle"; - roundstart_move = "trade_sol_base"; - width = 15; port_direction = 2; - preferred_direction = 8 + preferred_direction = 8; + roundstart_move = "trade_sol_base"; + width = 15 }, /obj/machinery/door/airlock/shuttle/glass{ id_tag = "s_docking_airlock" @@ -22865,6 +23095,11 @@ icon_state = "dark" }, /area/centcom/zone1) +"lbx" = ( +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supplypod/loading/four) "lbH" = ( /obj/effect/turf_decal/stripes/black{ do_not_delete_me = 1 @@ -22894,6 +23129,11 @@ icon_state = "darkredalt" }, /area/centcom/jail) +"lbZ" = ( +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supplypod/pod_storage) "lcq" = ( /obj/machinery/atmospherics/pipe/manifold/hidden, /turf/simulated/floor/plasteel{ @@ -22959,8 +23199,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 2; id_tag = "ERT_armory_lvl3"; - name = "Armory level 3"; - layer = 5 + layer = 5; + name = "Armory level 3" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -23115,8 +23355,8 @@ /area/centcom/bridge) "lhS" = ( /turf/simulated/floor/plasteel{ - icon_state = "darkgreencorners"; - dir = 8 + dir = 8; + icon_state = "darkgreencorners" }, /area/centcom/specops) "lhU" = ( @@ -23325,8 +23565,8 @@ "lmr" = ( /obj/machinery/syndiepad/receivepad, /obj/machinery/conveyor/inverted{ - id = "SFBQMLoad"; - dir = 5 + dir = 5; + id = "SFBQMLoad" }, /turf/simulated/floor/plasteel{ dir = 1; @@ -23762,6 +24002,12 @@ tag = "icon-stage_stairs" }, /area/syndicate_mothership) +"lwT" = ( +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "lwX" = ( /obj/effect/decal/warning_stripes/north, /obj/effect/decal/warning_stripes/south, @@ -24034,6 +24280,19 @@ icon_state = "dark" }, /area/syndicate_mothership/control) +"lDl" = ( +/obj/machinery/door/airlock/centcom{ + name = "Supply Pods Load 2"; + req_access = list(114) + }, +/obj/machinery/door/poddoor/shutters/invincible{ + dir = 2; + id_tag = "CC_Supply_Pods" + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supply) "lDp" = ( /obj/machinery/door/airlock/hatch/syndicate{ name = "Syndicate Base" @@ -24157,6 +24416,11 @@ name = "floor" }, /area/syndicate_mothership/elite_squad) +"lFA" = ( +/turf/simulated/floor/plasteel{ + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "lFP" = ( /obj/structure/sink{ dir = 4; @@ -24654,8 +24918,8 @@ dir = 1 }, /obj/machinery/portable_atmospherics/canister/oxygen{ - maximum_pressure = 50000; - anchored = 1 + anchored = 1; + maximum_pressure = 50000 }, /turf/simulated/floor/plasteel{ dir = 4; @@ -24769,8 +25033,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 1; id_tag = "ERT_armory_lvl2"; - name = "Armory level 2"; - layer = 5 + layer = 5; + name = "Armory level 2" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -25613,12 +25877,12 @@ name = "Ladder" }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; + mobs_only = 1; teleport_x = 135; teleport_y = 16; - teleport_z = 1; - mobs_only = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -25646,8 +25910,8 @@ /obj/structure/bed, /obj/item/bedsheet/rd, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet/black, /area/centcom/zone1) @@ -25975,8 +26239,8 @@ id = "CC_toilet_unit2"; name = "Door Bolt Control"; normaldoorcontrol = 1; - specialfunctions = 4; - pixel_x = 25 + pixel_x = 25; + specialfunctions = 4 }, /turf/simulated/floor/plasteel{ icon_state = "white" @@ -26352,8 +26616,8 @@ /obj/machinery/door_control/secure{ id = "CC_supply_internal2"; name = "Supply External Shutters"; - req_access = list(114); - pixel_x = -24 + pixel_x = -24; + req_access = list(114) }, /turf/simulated/floor/plasteel{ dir = 8; @@ -26951,6 +27215,12 @@ }, /turf/simulated/floor/wood, /area/centcom/zone3) +"mRm" = ( +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "mRs" = ( /obj/structure/flora/ausbushes/brflowers, /obj/structure/flora/ausbushes/ppflowers, @@ -27085,8 +27355,8 @@ /area/centcom/bridge) "mUi" = ( /obj/machinery/vending/wallmed{ - pixel_y = -32; - pixel_x = -32 + pixel_x = -32; + pixel_y = -32 }, /turf/simulated/floor/plasteel{ icon_state = "darkyellowalt" @@ -27485,19 +27755,19 @@ /obj/effect/decal/remains, /obj/effect/turf_decal/tile/neutral{ alpha = 100; + icon = 'icons/misc/beach.dmi'; icon_state = "seadeep"; - layer = 9; - icon = 'icons/misc/beach.dmi' + layer = 9 }, /obj/item/fish/goldfish{ - pixel_y = 10; - pixel_x = 16 + pixel_x = 16; + pixel_y = 10 }, /obj/structure/window/reinforced/survival_pod{ + density = 0; dir = 5; pixel_x = -32; - pixel_y = -32; - density = 0 + pixel_y = -32 }, /turf/simulated/floor/indestructible/beach/water/deep/sand_floor, /area/centcom/zone2) @@ -27907,15 +28177,15 @@ /area/syndicate_mothership/control) "njh" = ( /obj/structure/window/reinforced{ + armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100); dir = 1; - layer = 2; - armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100) + layer = 2 }, /obj/structure/window/reinforced/survival_pod{ + density = 0; dir = 9; - pixel_y = 1; pixel_x = -1; - density = 0 + pixel_y = 1 }, /turf/simulated/floor/plasteel{ dir = 1; @@ -28123,6 +28393,11 @@ "nnz" = ( /turf/simulated/wall/shuttle/onlyselfsmooth, /area/shuttle/supply) +"nnC" = ( +/turf/simulated/floor/plasteel{ + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "nnM" = ( /obj/machinery/recharge_station/ert, /obj/machinery/light{ @@ -28370,8 +28645,8 @@ /area/centcom/specops) "nsV" = ( /obj/machinery/conveyor_switch/oneway{ - id = "SFBQMLoad2"; - dir = 8 + dir = 8; + id = "SFBQMLoad2" }, /turf/simulated/floor/plasteel{ icon_state = "darkyellowcornersalt" @@ -29110,11 +29385,11 @@ /area/centcom/specops) "nIr" = ( /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 216; teleport_y = 26; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -29375,6 +29650,11 @@ icon_state = "wood-broken6" }, /area/centcom/zone2) +"nNQ" = ( +/turf/simulated/floor/plasteel{ + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "nOe" = ( /obj/structure/window/reinforced{ dir = 8 @@ -29572,11 +29852,11 @@ layer = 9 }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 175; teleport_y = 60; - teleport_z = 1; - icon_state = "x2"; - icon = 'icons/mob/screen_gen.dmi' + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -29919,8 +30199,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 1; id_tag = "ERT_armory_lvl2"; - name = "Armory level 2"; - layer = 5 + layer = 5; + name = "Armory level 2" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -30290,8 +30570,8 @@ color = "red" }, /obj/machinery/conveyor{ - id = "SFBQMLoad2"; - dir = 1 + dir = 1; + id = "SFBQMLoad2" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -30360,8 +30640,8 @@ "olk" = ( /obj/machinery/syndiepad/loadpad, /obj/machinery/conveyor/inverted{ - id = "SFBQMLoad2"; - dir = 6 + dir = 6; + id = "SFBQMLoad2" }, /turf/simulated/floor/plasteel{ dir = 1; @@ -30540,9 +30820,9 @@ /area/syndicate_mothership) "opi" = ( /obj/structure/closet/cardboard{ - icon_state = "cardboard_cargo"; icon_closed = "cardboard_cargo"; - icon_opened = "cardboard_cargo_open" + icon_opened = "cardboard_cargo_open"; + icon_state = "cardboard_cargo" }, /mob/living/simple_animal/hostile/mimic{ faction = list("neutral"); @@ -30833,8 +31113,8 @@ /area/shuttle/siberia) "ovI" = ( /obj/structure/closet/acloset{ - name = "Undercover officer's closet"; - desc = "It's a basic storage unit." + desc = "It's a basic storage unit."; + name = "Undercover officer's closet" }, /obj/item/flashlight, /obj/item/encryptionkey/centcom, @@ -31113,8 +31393,8 @@ /area/syndicate_mothership/jail) "oDS" = ( /obj/machinery/conveyor/inverted{ - id = "CC_crate"; - dir = 9 + dir = 9; + id = "CC_crate" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -31194,8 +31474,8 @@ "oFM" = ( /obj/structure/chair/sofa/right, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet/black, /area/centcom/zone1) @@ -31405,6 +31685,15 @@ icon_state = "dark" }, /area/centcom/supply) +"oKI" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "oKN" = ( /obj/item/flag/syndi, /obj/structure/curtain/black{ @@ -31457,9 +31746,9 @@ /obj/machinery/door_control/secure{ id = "gamma shuttle"; name = "Gamma Armory Shutters"; - req_access = list(114); pixel_x = 24; - pixel_y = 26 + pixel_y = 26; + req_access = list(114) }, /turf/simulated/floor/plasteel{ dir = 4; @@ -31500,8 +31789,8 @@ }, /obj/structure/table, /obj/machinery/computer/library/public{ - pixel_y = 4; - pixel_x = 1 + pixel_x = 1; + pixel_y = 4 }, /obj/machinery/ai_status_display{ pixel_y = 32 @@ -31635,10 +31924,10 @@ /area/syndicate_mothership/control) "oOK" = ( /obj/structure/window/reinforced/survival_pod{ + density = 0; dir = 6; - pixel_y = -1; pixel_x = 1; - density = 0 + pixel_y = -1 }, /turf/simulated/floor/plasteel{ dir = 4; @@ -31690,6 +31979,12 @@ icon_state = "darkfull" }, /area/syndicate_mothership/jail) +"oPk" = ( +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "oPx" = ( /obj/structure/chair/comfy/shuttle{ dir = 8 @@ -31860,8 +32155,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 2; id_tag = "ERT_armory_lvl3"; - name = "Armory level 3"; - layer = 5 + layer = 5; + name = "Armory level 3" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -32133,6 +32428,12 @@ }, /turf/simulated/floor/carpet, /area/centcom/evac) +"paz" = ( +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "pbe" = ( /obj/structure/closet/crate/can, /turf/simulated/floor/wood, @@ -32293,8 +32594,8 @@ }, /obj/docking_port/mobile/supply{ dir = 2; - preferred_direction = 8; - port_direction = 4 + port_direction = 4; + preferred_direction = 8 }, /turf/simulated/wall/shuttle, /area/shuttle/supply) @@ -32331,6 +32632,15 @@ icon_state = "navyblue" }, /area/centcom/specops) +"pgz" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkyellowalt" + }, +/area/centcom/supply) "phK" = ( /obj/effect/decal/syndie_logo, /obj/effect/turf_decal/stripes/black{ @@ -32666,8 +32976,8 @@ dir = 4 }, /obj/machinery/conveyor{ - id = "O2"; - dir = 1 + dir = 1; + id = "O2" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -32694,13 +33004,17 @@ dir = 4 }, /obj/machinery/conveyor{ - id = "O2"; - dir = 1 + dir = 1; + id = "O2" }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, /area/centcom/supply) +"psX" = ( +/obj/machinery/vending/ntcrates, +/turf/simulated/floor/plating, +/area/centcom/specops) "pte" = ( /obj/structure/table/wood{ color = "#996633" @@ -33206,9 +33520,9 @@ height = 12; id = "ferry"; name = "ferry shuttle"; + preferred_direction = 4; roundstart_move = "ferry_away"; - width = 5; - preferred_direction = 4 + width = 5 }, /obj/docking_port/stationary{ dir = 8; @@ -33416,11 +33730,11 @@ layer = 9 }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 175; teleport_y = 61; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -33575,6 +33889,15 @@ icon_state = "darkredalt" }, /area/centcom/jail) +"pPo" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "pPN" = ( /obj/effect/landmark/syndicate_commando{ tag = "Commando" @@ -33723,8 +34046,8 @@ "pST" = ( /obj/machinery/syndiepad/loadpad, /obj/machinery/conveyor{ - id = "SFBQMLoad2"; - dir = 8 + dir = 8; + id = "SFBQMLoad2" }, /turf/simulated/floor/plasteel{ dir = 1; @@ -34041,6 +34364,12 @@ /obj/structure/window/full/shuttle/ninja, /turf/simulated/floor/shuttle/plating, /area/shuttle/ninja) +"pYT" = ( +/turf/simulated/floor/plasteel{ + dir = 6; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "pYZ" = ( /obj/structure/curtain/open/shower/security{ pixel_x = 32 @@ -34086,8 +34415,8 @@ name = "centcom bay 3"; top_left_corner = 8; top_right_corner = 1; - width = 5; - turf_type = /turf/simulated/floor/plating/airless + turf_type = /turf/simulated/floor/plating/airless; + width = 5 }, /turf/simulated/floor/shuttle/plating, /area/shuttle/specops) @@ -34399,8 +34728,8 @@ dir = 4 }, /obj/machinery/conveyor{ - id = "N2O"; - dir = 1 + dir = 1; + id = "N2O" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -34459,8 +34788,8 @@ /obj/structure/bed, /obj/item/bedsheet/qm, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet/arcade, /area/centcom/zone1) @@ -34475,9 +34804,9 @@ /obj/effect/decal/warning_stripes/south, /obj/effect/turf_decal/caution/stand_clear, /obj/machinery/door/poddoor/shutters/preopen/invincible{ + dir = 2; id_tag = "ERT_armory_lvl1"; - name = "Armory level 1"; - dir = 2 + name = "Armory level 1" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -34655,6 +34984,12 @@ icon_state = "dark" }, /area/centcom/zone2) +"qoL" = ( +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "qoS" = ( /obj/machinery/suit_storage_unit/standard_unit, /obj/effect/turf_decal/stripes/black{ @@ -34948,6 +35283,15 @@ icon_state = "floor4" }, /area/shuttle/gamma) +"qtl" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "qto" = ( /turf/simulated/floor/plasteel{ dir = 8; @@ -34983,8 +35327,8 @@ "quA" = ( /obj/effect/decal/warning_stripes/yellow/hollow, /obj/machinery/conveyor{ - id = "CO2"; - dir = 1 + dir = 1; + id = "CO2" }, /obj/machinery/portable_atmospherics/canister/carbon_dioxide{ maximum_pressure = 50000 @@ -35167,6 +35511,12 @@ }, /turf/simulated/floor/shuttle, /area/shuttle/nt_droppod) +"qAI" = ( +/turf/simulated/floor/plasteel{ + dir = 9; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "qAL" = ( /obj/structure/rack/holorack, /obj/item/clothing/under/assistantformal, @@ -36587,6 +36937,12 @@ /obj/structure/AIcore, /turf/simulated/floor/shuttle/objective_check/vox, /area/shuttle/vox) +"rdz" = ( +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "rdZ" = ( /obj/machinery/light/small{ dir = 8 @@ -36796,9 +37152,9 @@ "riy" = ( /obj/effect/turf_decal/tile/neutral{ alpha = 85; + icon = 'icons/misc/beach.dmi'; icon_state = "seadeep"; - layer = 9; - icon = 'icons/misc/beach.dmi' + layer = 9 }, /obj/structure/window/reinforced{ dir = 4; @@ -36806,10 +37162,10 @@ }, /obj/structure/flora/rock/pile, /obj/structure/window/reinforced/survival_pod{ + density = 0; dir = 6; - pixel_y = -7; pixel_x = 1; - density = 0 + pixel_y = -7 }, /turf/simulated/floor/indestructible/beach/water/deep/sand_floor, /area/centcom/specops) @@ -37746,11 +38102,11 @@ /area/syndicate_mothership/elite_squad) "rFY" = ( /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 205; teleport_y = 89; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/space, /area/space) @@ -37984,16 +38340,16 @@ /obj/structure/fans/tiny, /obj/machinery/door/airlock/external, /obj/docking_port/mobile{ + alone_shuttle = 1; dir = 8; dwidth = 2; height = 7; id = "funeral"; name = "Funeral shuttle"; - roundstart_move = "graveyard_dock"; - alone_shuttle = 1; - width = 10; port_direction = 8; - preferred_direction = 2 + preferred_direction = 2; + roundstart_move = "graveyard_dock"; + width = 10 }, /turf/simulated/floor/shuttle/plating, /area/shuttle/funeral) @@ -38081,8 +38437,8 @@ icon_state = "tile_full" }, /obj/structure/railing{ - layer = 4.3; - density = 0 + density = 0; + layer = 4.3 }, /turf/simulated/floor/plasteel{ dir = 8; @@ -38141,8 +38497,8 @@ dir = 4 }, /obj/machinery/conveyor{ - id = "N2"; - dir = 1 + dir = 1; + id = "N2" }, /obj/machinery/portable_atmospherics/canister/nitrogen{ maximum_pressure = 50000 @@ -38726,6 +39082,19 @@ /obj/structure/window/full/shuttle/gray, /turf/simulated/floor/plating/airless, /area/shuttle/syndicate) +"saq" = ( +/obj/machinery/door/airlock/centcom{ + name = "Supply Pods Load 1"; + req_access = list(114) + }, +/obj/machinery/door/poddoor/shutters/invincible{ + dir = 2; + id_tag = "CC_Supply_Pods" + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supply) "sas" = ( /turf/simulated/floor/plasteel{ dir = 6; @@ -38939,9 +39308,9 @@ /obj/structure/flora/ausbushes/stalkybush, /obj/effect/turf_decal/tile/neutral{ alpha = 85; + icon = 'icons/misc/beach.dmi'; icon_state = "seadeep"; - layer = 9; - icon = 'icons/misc/beach.dmi' + layer = 9 }, /turf/simulated/floor/indestructible/beach/water/deep/sand_floor, /area/centcom/specops) @@ -38988,8 +39357,8 @@ }, /obj/effect/decal/warning_stripes/yellow/hollow, /obj/machinery/conveyor{ - id = "Toxin"; - dir = 1 + dir = 1; + id = "Toxin" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -39026,9 +39395,9 @@ }, /obj/effect/turf_decal/tile/neutral{ alpha = 85; + icon = 'icons/misc/beach.dmi'; icon_state = "seadeep"; - layer = 9; - icon = 'icons/misc/beach.dmi' + layer = 9 }, /turf/simulated/floor/indestructible/beach/water/deep/sand_floor, /area/centcom/specops) @@ -39395,6 +39764,15 @@ icon_state = "grimy" }, /area/centcom/zone1) +"srJ" = ( +/obj/machinery/light{ + dir = 4; + switchcount = 50 + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/specops) "sse" = ( /obj/effect/decal/syndie_logo{ icon_state = "logo11" @@ -39918,10 +40296,10 @@ /obj/structure/fans/tiny, /obj/effect/decal/warning_stripes/white, /obj/machinery/door/airlock/external{ + hackProof = 1; id_tag = "supply_away"; name = "Central Command Supply"; - req_access = list(31); - hackProof = 1 + req_access = list(31) }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -40014,8 +40392,8 @@ /obj/structure/bed, /obj/item/bedsheet/clown, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet/black, /area/centcom/zone1) @@ -40061,10 +40439,30 @@ }, /turf/simulated/floor/shuttle/plating, /area/shuttle/ninja) +"sIz" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/specops) "sIC" = ( /obj/structure/table/wood, /turf/simulated/floor/carpet, /area/centcom/evac) +"sIQ" = ( +/obj/machinery/door_control/secure{ + id = "CC_Supply_Pods"; + name = "Supply Pods Load"; + pixel_y = -24; + req_access = list(114) + }, +/obj/machinery/light, +/turf/simulated/floor/plasteel{ + icon_state = "darkyellowalt" + }, +/area/centcom/supply) "sIY" = ( /obj/effect/decal/syndie_logo{ icon_state = "logo13" @@ -40576,6 +40974,19 @@ /obj/item/reagent_containers/food/snacks/sliceable/birthdaycake, /turf/simulated/floor/wood, /area/centcom/specops) +"sVB" = ( +/obj/machinery/door/airlock/centcom{ + name = "Supply Pods Load 4"; + req_access = list(114) + }, +/obj/machinery/door/poddoor/shutters/invincible{ + dir = 2; + id_tag = "CC_Supply_Pods" + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supply) "sVH" = ( /obj/machinery/vending/robotics/nt/gygax, /turf/simulated/floor/plasteel{ @@ -40726,76 +41137,76 @@ "sYS" = ( /obj/structure/table/reinforced, /obj/item/radio{ + icon_state = "walkietalkie_sec"; pixel_x = -4; - pixel_y = 5; - icon_state = "walkietalkie_sec" + pixel_y = 5 }, /obj/item/radio{ + icon_state = "walkietalkie_sec"; pixel_x = -4; - pixel_y = 5; - icon_state = "walkietalkie_sec" + pixel_y = 5 }, /obj/item/radio{ + icon_state = "walkietalkie_sec"; pixel_x = -4; - pixel_y = 5; - icon_state = "walkietalkie_sec" + pixel_y = 5 }, /obj/item/radio{ + icon_state = "walkietalkie_sec"; pixel_x = -4; - pixel_y = 5; - icon_state = "walkietalkie_sec" + pixel_y = 5 }, /obj/item/radio{ + icon_state = "walkietalkie_sec"; pixel_x = 4; - pixel_y = 5; - icon_state = "walkietalkie_sec" + pixel_y = 5 }, /obj/item/radio{ + icon_state = "walkietalkie_sec"; pixel_x = 4; - pixel_y = 5; - icon_state = "walkietalkie_sec" + pixel_y = 5 }, /obj/item/radio{ + icon_state = "walkietalkie_sec"; pixel_x = 4; - pixel_y = 5; - icon_state = "walkietalkie_sec" + pixel_y = 5 }, /obj/item/radio{ + icon_state = "walkietalkie_sec"; pixel_x = 4; - pixel_y = 5; - icon_state = "walkietalkie_sec" + pixel_y = 5 }, /obj/item/radio{ - pixel_x = -4; - icon_state = "walkietalkie_sec" + icon_state = "walkietalkie_sec"; + pixel_x = -4 }, /obj/item/radio{ - pixel_x = -4; - icon_state = "walkietalkie_sec" + icon_state = "walkietalkie_sec"; + pixel_x = -4 }, /obj/item/radio{ - pixel_x = -4; - icon_state = "walkietalkie_sec" + icon_state = "walkietalkie_sec"; + pixel_x = -4 }, /obj/item/radio{ - pixel_x = -4; - icon_state = "walkietalkie_sec" + icon_state = "walkietalkie_sec"; + pixel_x = -4 }, /obj/item/radio{ - pixel_x = 4; - icon_state = "walkietalkie_sec" + icon_state = "walkietalkie_sec"; + pixel_x = 4 }, /obj/item/radio{ - pixel_x = 4; - icon_state = "walkietalkie_sec" + icon_state = "walkietalkie_sec"; + pixel_x = 4 }, /obj/item/radio{ - pixel_x = 4; - icon_state = "walkietalkie_sec" + icon_state = "walkietalkie_sec"; + pixel_x = 4 }, /obj/item/radio{ - pixel_x = 4; - icon_state = "walkietalkie_sec" + icon_state = "walkietalkie_sec"; + pixel_x = 4 }, /turf/simulated/floor/plasteel{ icon_state = "navyblue" @@ -40858,6 +41269,11 @@ icon_state = "bot" }, /area/shuttle/escape) +"sZK" = ( +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supplypod/loading/ert) "sZP" = ( /turf/simulated/floor/plasteel{ dir = 8; @@ -41188,6 +41604,12 @@ icon_state = "white" }, /area/centcom/zone1) +"thd" = ( +/turf/simulated/floor/plasteel{ + dir = 9; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "thl" = ( /obj/structure/table/glass, /obj/effect/spawner/lootdrop{ @@ -41251,8 +41673,8 @@ /area/shuttle/syndicate_sit) "tjx" = ( /obj/machinery/conveyor/inverted{ - id = "SFBQMLoad"; - dir = 5 + dir = 5; + id = "SFBQMLoad" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -41344,8 +41766,8 @@ dir = 4 }, /obj/machinery/conveyor{ - id = "N2O"; - dir = 1 + dir = 1; + id = "N2O" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -41932,18 +42354,18 @@ pixel_y = -4 }, /obj/item/paper{ - pixel_x = 9; - info = "Обед через час, работа через вчера" + info = "Обед через час, работа через вчера"; + pixel_x = 9 }, /obj/item/paper{ - pixel_y = -9; + info = "Пофиксить в моем кабинете рантайм трубы в трубе... опять"; pixel_x = 7; - info = "Пофиксить в моем кабинете рантайм трубы в трубе... опять" + pixel_y = -9 }, /obj/item/paper{ - pixel_y = -6; + info = "Начать делать очередную новую станцию и сгореть на втором часу работы в самокопании"; pixel_x = -5; - info = "Начать делать очередную новую станцию и сгореть на втором часу работы в самокопании" + pixel_y = -6 }, /obj/machinery/atmospherics/pipe/manifold/visible{ dir = 8 @@ -42106,8 +42528,8 @@ /area/syndicate_mothership/infteam) "tBG" = ( /obj/machinery/conveyor{ - id = "CC_crate"; - dir = 4 + dir = 4; + id = "CC_crate" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -42243,11 +42665,11 @@ name = "Ladder" }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; teleport_x = 203; teleport_y = 41; - teleport_z = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ dir = 9; @@ -42409,6 +42831,13 @@ icon_state = "darkfull" }, /area/centcom/specops) +"tHL" = ( +/obj/machinery/door/poddoor/shutters/invincible{ + dir = 2; + id_tag = "ShitRainSupply" + }, +/turf/simulated/floor/plating, +/area/centcom/specops) "tHM" = ( /obj/effect/turf_decal/siding/blue{ dir = 1 @@ -42437,6 +42866,17 @@ }, /turf/simulated/floor/shuttle/transparent_floor, /area/shuttle/ninja) +"tIk" = ( +/obj/machinery/door/poddoor/shutters/invincible{ + dir = 2; + id_tag = "ERT_Supply_Pod" + }, +/obj/machinery/door/airlock/centcom{ + name = "ERT Supply Pod Loading Zone"; + req_access = list(114) + }, +/turf/simulated/floor/plating, +/area/centcom/specops) "tIn" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/wood{ @@ -43595,8 +44035,8 @@ /area/centcom/zone3) "ulG" = ( /obj/structure/railing{ - layer = 4.3; - density = 0 + density = 0; + layer = 4.3 }, /turf/simulated/floor/plasteel{ color = "gray"; @@ -44300,6 +44740,12 @@ "uAd" = ( /turf/simulated/wall/indestructible/iron, /area/syndicate_mothership/outside) +"uAg" = ( +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "uAh" = ( /obj/structure/chair/comfy/shuttle{ dir = 4 @@ -44511,8 +44957,8 @@ icon_state = "tile_full" }, /obj/structure/railing{ - pixel_y = 32; - density = 0 + density = 0; + pixel_y = 32 }, /turf/simulated/floor/plasteel{ dir = 8; @@ -44919,8 +45365,8 @@ /area/centcom/zone1) "uMD" = ( /obj/machinery/conveyor{ - id = "SFBQMLoad"; - dir = 6 + dir = 6; + id = "SFBQMLoad" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -45016,8 +45462,8 @@ /area/centcom/zone1) "uNG" = ( /obj/machinery/conveyor{ - id = "SFBQMLoad2"; - dir = 1 + dir = 1; + id = "SFBQMLoad2" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -45033,9 +45479,9 @@ /obj/item/ship_in_a_bottle, /obj/effect/turf_decal/tile/neutral{ alpha = 100; + icon = 'icons/misc/beach.dmi'; icon_state = "seadeep"; - layer = 9; - icon = 'icons/misc/beach.dmi' + layer = 9 }, /turf/simulated/floor/indestructible/beach/water/deep/sand_floor, /area/centcom/zone2) @@ -45155,8 +45601,8 @@ /area/shuttle/vox) "uRC" = ( /obj/structure/falsewall/reinforced{ - req_access = list(114); - layer = 5 + layer = 5; + req_access = list(114) }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -45612,6 +46058,15 @@ icon_state = "bot" }, /area/shuttle/escape) +"vdy" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "vdH" = ( /obj/structure/reagent_dispensers/watertank, /obj/effect/decal/cleanable/dirt, @@ -45887,6 +46342,11 @@ icon_state = "fancy-wood-cherry" }, /area/shuttle/trade/sol) +"vjb" = ( +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supplypod/supplypod_temp_holding) "vjo" = ( /obj/effect/turf_decal/box/corners{ dir = 1 @@ -45912,10 +46372,10 @@ /obj/docking_port/stationary{ dwidth = 3; height = 7; - name = "Emerjency droppod dock"; id = "shit_rain_base"; - width = 7; - pixel_y = -32 + name = "Emerjency droppod dock"; + pixel_y = -32; + width = 7 }, /turf/simulated/floor/shuttle, /area/shuttle/nt_droppod) @@ -45988,8 +46448,8 @@ /area/syndicate_mothership/jail) "vng" = ( /turf/simulated/floor/plasteel{ - icon_state = "darkyellowcorners"; - dir = 1 + dir = 1; + icon_state = "darkyellowcorners" }, /area/centcom/specops) "vnv" = ( @@ -46074,11 +46534,17 @@ /obj/structure/bed, /obj/item/bedsheet/mime, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet, /area/centcom/zone1) +"voW" = ( +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/four) "vpg" = ( /turf/simulated/floor/shuttle{ icon_state = "floor4" @@ -46352,8 +46818,8 @@ pixel_y = -1 }, /obj/structure/window/reinforced{ - layer = 3.1; - armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100) + armor = list("melee"=100,"bullet"=100,"laser"=0,"energy"=0,"bomb"=25,"bio"=100,"rad"=100,"fire"=80,"acid"=100); + layer = 3.1 }, /turf/simulated/floor/plasteel{ dir = 4; @@ -46768,10 +47234,10 @@ /area/syndicate_mothership) "vGX" = ( /obj/item/flashlight/lamp/green{ - pixel_x = -6; - pixel_y = 16; + icon = 'icons/obj/library.dmi'; icon_state = "bigscenner"; - icon = 'icons/obj/library.dmi' + pixel_x = -6; + pixel_y = 16 }, /obj/item/paper_bin/nanotrasen{ pixel_x = -2; @@ -46811,10 +47277,12 @@ }, /area/syndicate_mothership) "vHF" = ( -/obj/machinery/door/poddoor/shutters/invincible{ - id_tag = "ShitRainSupply" +/obj/machinery/door/airlock/centcom{ + name = "ERT Supply Pods" + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" }, -/turf/simulated/floor/plating, /area/centcom/specops) "vHT" = ( /obj/effect/turf_decal/delivery, @@ -46843,8 +47311,8 @@ /area/shuttle/vox) "vIU" = ( /obj/structure/falsewall/reinforced{ - req_access = list(114); - layer = 2.9 + layer = 2.9; + req_access = list(114) }, /obj/effect/mine/sound/bwoink{ invisibility = 1; @@ -47417,6 +47885,12 @@ icon_state = "grimy" }, /area/centcom/jail) +"vUp" = ( +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/three) "vUy" = ( /obj/effect/decal/warning_stripes/yellow, /obj/machinery/door/airlock/gold/glass{ @@ -47625,6 +48099,12 @@ icon_state = "dark" }, /area/shuttle/administration) +"vZp" = ( +/turf/simulated/floor/plasteel{ + dir = 9; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/two) "vZr" = ( /obj/machinery/light, /obj/structure/chair/comfy/shuttle{ @@ -47764,12 +48244,12 @@ name = "Ladder" }, /obj/effect/step_trigger/teleporter{ + icon = 'icons/mob/screen_gen.dmi'; + icon_state = "x2"; + mobs_only = 1; teleport_x = 135; teleport_y = 16; - teleport_z = 1; - mobs_only = 1; - icon = 'icons/mob/screen_gen.dmi'; - icon_state = "x2" + teleport_z = 1 }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -48633,39 +49113,39 @@ color = "#ff9999"; id = "ERT_armory_lvl3"; name = "ERT Armory Level 3"; - req_access = list(114); pixel_x = -6; - pixel_y = 8 + pixel_y = 8; + req_access = list(114) }, /obj/machinery/door_control/secure{ color = "#99ff99"; id = "ERT_armory_lvl1"; name = "ERT Armory Level 1"; - req_access = list(114); pixel_x = -6; - pixel_y = -8 + pixel_y = -8; + req_access = list(114) }, /obj/machinery/door_control/secure{ color = "#9999ff"; id = "ERT_armory_lvl2"; name = "ERT Armory Level 2"; - req_access = list(114); - pixel_x = -6 + pixel_x = -6; + req_access = list(114) }, /obj/machinery/door_control{ id = "ERT_Quarantine"; name = "ERT Quarantine"; - req_access = list(114); + pixel_x = 6; pixel_y = 6; - pixel_x = 6 + req_access = list(114) }, /obj/machinery/door_control/secure{ color = "#ffdd99"; id = "ERT_armory_lvl4"; name = "ERT Armory Level 4"; - req_access = list(114); pixel_x = 6; - pixel_y = -14 + pixel_y = -14; + req_access = list(114) }, /obj/effect/turf_decal/siding{ color = "#444444"; @@ -48817,6 +49297,15 @@ }, /turf/simulated/floor/carpet/black, /area/centcom/specops) +"wEu" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + dir = 4; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "wEF" = ( /obj/structure/grille, /obj/machinery/door/poddoor/shutters/preopen{ @@ -48921,6 +49410,12 @@ icon_state = "darkred" }, /area/shuttle/escape) +"wJm" = ( +/turf/simulated/floor/plasteel{ + dir = 9; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "wJo" = ( /obj/machinery/door_control/secure{ id = "ERT_Drop"; @@ -49135,6 +49630,12 @@ icon_state = "darkfull" }, /area/centcom/specops) +"wPe" = ( +/turf/simulated/floor/plasteel{ + dir = 6; + icon_state = "darkyellow" + }, +/area/centcom/supplypod/loading/one) "wPq" = ( /obj/structure/noticeboard{ pixel_x = -32 @@ -49316,6 +49817,19 @@ /obj/item/storage/belt/fannypack/black, /turf/simulated/floor/wood/fancy/light, /area/centcom/specops) +"wTC" = ( +/obj/machinery/door/airlock/centcom{ + name = "Supply Pods Load 3"; + req_access = list(114) + }, +/obj/machinery/door/poddoor/shutters/invincible{ + dir = 2; + id_tag = "CC_Supply_Pods" + }, +/turf/simulated/floor/plasteel{ + icon_state = "Dark" + }, +/area/centcom/supply) "wTK" = ( /turf/simulated/floor/shuttle/objective_check{ dir = 5; @@ -49681,10 +50195,10 @@ height = 10; id = "ombra"; name = "Spider Clan Ombra"; - roundstart_move = "ombra_home"; - width = 21; port_direction = 2; - preferred_direction = 2 + preferred_direction = 2; + roundstart_move = "ombra_home"; + width = 21 }, /obj/structure/fans/tiny/invisible, /obj/docking_port/stationary{ @@ -49775,9 +50289,9 @@ height = 22; id = "syndicate"; name = "syndicate shuttle"; + port_direction = 2; roundstart_move = "syndicate_away"; - width = 18; - port_direction = 2 + width = 18 }, /obj/structure/lattice/catwalk, /obj/docking_port/stationary{ @@ -50186,8 +50700,8 @@ dir = 4 }, /obj/machinery/conveyor{ - id = "Air"; - dir = 1 + dir = 1; + id = "Air" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -50232,10 +50746,10 @@ color = "#666666"; damtype = "burn"; health = 1250; + name = "Quarantine Pulse Turret"; region_max = 12; scan_range = 12; - shot_delay = 8; - name = "Quarantine Pulse Turret" + shot_delay = 8 }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -50507,17 +51021,6 @@ }, /turf/simulated/floor/plating, /area/syndicate_mothership/cargo) -"xqF" = ( -/obj/machinery/door_control/secure{ - id = "ShitRainSupply"; - pixel_x = -24; - pixel_y = -24 - }, -/turf/simulated/floor/plasteel{ - dir = 9; - icon_state = "navybluealt" - }, -/area/centcom/specops) "xqM" = ( /obj/structure/lattice/catwalk, /obj/structure/marker_beacon{ @@ -50937,8 +51440,8 @@ /obj/machinery/door/poddoor/shutters/invincible{ dir = 1; id_tag = "ERT_armory_lvl4"; - name = "Armory level 4"; - layer = 5 + layer = 5; + name = "Armory level 4" }, /turf/simulated/floor/plasteel{ icon_state = "darkfull" @@ -51028,8 +51531,8 @@ "xCr" = ( /obj/structure/bookcase, /obj/item/paper{ - name = "Главный строить мужик репорт"; - info = "
" + info = "
"; + name = "Главный строить мужик репорт" }, /turf/simulated/floor/plating, /area/centcom/zone2) @@ -51525,8 +52028,8 @@ /obj/structure/bed, /obj/item/bedsheet/qm, /obj/effect/mine/sound/bwoink{ - layer = 2.9; - alpha = 0 + alpha = 0; + layer = 2.9 }, /turf/simulated/floor/carpet/black, /area/centcom/zone1) @@ -51680,8 +52183,8 @@ /area/centcom/evac) "xSg" = ( /obj/structure/falsewall/reinforced{ - req_access = list(114); - layer = 5 + layer = 5; + req_access = list(114) }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -51699,8 +52202,8 @@ id = "CC_toilet_unit1"; name = "Door Bolt Control"; normaldoorcontrol = 1; - specialfunctions = 4; - pixel_x = 25 + pixel_x = 25; + specialfunctions = 4 }, /turf/simulated/floor/plasteel{ icon_state = "white" @@ -52142,6 +52645,12 @@ icon_state = "dark" }, /area/centcom/evac) +"yhG" = ( +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "navyblue" + }, +/area/centcom/supplypod/loading/ert) "yhH" = ( /obj/machinery/light/small, /turf/simulated/floor/carpet, @@ -85678,15 +86187,15 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +nAN +nAN +nAN +nAN +nAN +nAN +nAN +nAN mVX mVX mVX @@ -85935,15 +86444,15 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +wJm +yhG +pPo +yhG +aHe +nAN +sIz +nAN mVX mVX mVX @@ -86192,15 +86701,15 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +rdz +sZK +sZK +sZK +eDu +nAN +bBe +nAN jMD mVX mVX @@ -86449,15 +86958,15 @@ mVX mVX mVX jMD -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +rdz +sZK +sZK +sZK +eDu +tIk +jJD +nAN jMD mVX mVX @@ -86706,15 +87215,15 @@ mVX mVX mVX jMD -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +gxu +uAg +jCl +uAg +aYk +nAN +bBe +nAN jMD mVX mVX @@ -86963,15 +87472,15 @@ mVX mVX mVX jMD -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +nAN +nAN +nAN +nAN +nAN +nAN +bBe +nAN jMD mVX mVX @@ -87225,9 +87734,9 @@ nAN nAN nAN nAN -nAN -nAN -nAN +psX +tHL +fJp nAN nAN nAN @@ -87484,7 +87993,7 @@ nAN nAN nAN nAN -nAN +srJ bBe aoW nIr @@ -87999,7 +88508,7 @@ iXI wiU wiU kmM -xqF +aPL qap kpi kpi @@ -108814,8 +109323,8 @@ bbq mVX afP dlT -yeh -tgA +aDR +jHX hAX gFx aLo @@ -109070,9 +109579,9 @@ mVX mVX mVX afP -ecV -ecV -ecV +pgz +aDR +sIQ afP afP afP @@ -109326,17 +109835,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +xhN +afP +qAI +aiB +dTt +aiB +dtp +afP mVX nAN lRD @@ -109583,17 +110092,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +xhN +afP +htF +aeQ +aeQ +aeQ +bIN +afP mVX mVX rFY @@ -109840,21 +110349,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +jHX +saq +htF +aeQ +aeQ +aeQ +bIN +afP mVX mVX mVX @@ -109863,6 +110368,10 @@ mVX mVX mVX nAN +lbZ +lbZ +lbZ +nAN nAN nAN nAN @@ -110097,6 +110606,17 @@ mVX mVX mVX mVX +ecV +dZk +aDR +xhN +afP +bEA +mRm +wEu +mRm +wPe +afP mVX mVX mVX @@ -110104,22 +110624,11 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +lbZ +lbZ +lbZ +nAN mVX mVX mVX @@ -110354,6 +110863,17 @@ mVX mVX mVX mVX +afP +pgz +aDR +iRY +afP +afP +afP +afP +afP +afP +afP mVX mVX mVX @@ -110361,22 +110881,11 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +lbZ +lbZ +lbZ +nAN mVX mVX mVX @@ -110611,6 +111120,17 @@ mVX mVX mVX mVX +ecV +dZk +aDR +xhN +afP +vZp +lwT +oKI +lwT +gYf +afP mVX mVX mVX @@ -110618,22 +111138,11 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +nAN +nAN +nAN +nAN mVX mVX mVX @@ -110868,6 +111377,17 @@ mVX mVX mVX mVX +ecV +dZk +aDR +xhN +afP +paz +ilJ +ilJ +ilJ +lFA +afP mVX mVX mVX @@ -110875,22 +111395,11 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +vjb +vjb +vjb +nAN mVX mVX mVX @@ -111125,6 +111634,17 @@ mVX mVX mVX mVX +ecV +dZk +aDR +jHX +lDl +paz +ilJ +ilJ +ilJ +lFA +afP mVX mVX mVX @@ -111132,22 +111652,11 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +vjb +vjb +vjb +nAN mVX mVX mVX @@ -111382,6 +111891,17 @@ mVX mVX mVX mVX +ecV +dZk +aDR +xhN +afP +jfm +hQZ +vdy +hQZ +bRZ +afP mVX mVX mVX @@ -111389,22 +111909,11 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +vjb +vjb +vjb +nAN mVX mVX mVX @@ -111639,6 +112148,17 @@ mVX mVX mVX mVX +afP +pgz +aDR +iRY +afP +afP +afP +afP +afP +afP +afP mVX mVX mVX @@ -111646,22 +112166,11 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +nAN +nAN +nAN +nAN +nAN mVX mVX mVX @@ -111896,17 +112405,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +xhN +afP +gDh +jXp +kek +jXp +hsP +afP mVX mVX mVX @@ -112153,17 +112662,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +xhN +afP +iuR +hLb +hLb +hLb +nNQ +afP mVX mVX mVX @@ -112410,17 +112919,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +jHX +wTC +iuR +hLb +hLb +hLb +nNQ +afP mVX mVX mVX @@ -112667,17 +113176,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +xhN +afP +vUp +gIp +cAU +gIp +eZq +afP mVX mVX mVX @@ -112924,17 +113433,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +afP +pgz +aDR +iRY +afP +afP +afP +afP +afP +afP +afP mVX mVX mVX @@ -113181,17 +113690,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +xhN +afP +thd +voW +eGx +voW +cJx +afP mVX mVX mVX @@ -113438,17 +113947,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +xhN +afP +qoL +lbx +lbx +lbx +nnC +afP mVX mVX mVX @@ -113695,17 +114204,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +dZk +aDR +jHX +sVB +qoL +lbx +lbx +lbx +nnC +afP mVX mVX mVX @@ -113952,17 +114461,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +ecV +fRi +yeh +aOM +afP +czW +oPk +qtl +oPk +pYT +afP mVX mVX mVX @@ -114209,17 +114718,17 @@ mVX mVX mVX mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX -mVX +afP +ecV +ecV +ecV +afP +afP +afP +afP +afP +afP +afP mVX mVX mVX diff --git a/code/__DEFINES/cargo.dm b/code/__DEFINES/cargo.dm new file mode 100644 index 00000000000..d8aa74db8fa --- /dev/null +++ b/code/__DEFINES/cargo.dm @@ -0,0 +1,37 @@ +#define STYLE_STANDARD 1 +#define STYLE_BLUESPACE 2 +#define STYLE_CENTCOM 3 +#define STYLE_SYNDICATE 4 +#define STYLE_BLUE 5 +#define STYLE_CULT 6 +#define STYLE_MISSILE 7 +#define STYLE_RED_MISSILE 8 +#define STYLE_BOX 9 +#define STYLE_HONK 10 +#define STYLE_FRUIT 11 +#define STYLE_INVISIBLE 12 +#define STYLE_GONDOLA 13 + +#define POD_ICON_STATE 1 +#define POD_NAME 2 +#define POD_DESC 3 + +#define POD_SHAPE_NORMAL 1 +#define POD_SHAPE_OTHER 2 + +#define RUBBLE_NONE 1 +#define RUBBLE_NORMAL 2 +#define RUBBLE_WIDE 3 +#define RUBBLE_THIN 4 + +#define POD_TRANSIT "1" +#define POD_FALLING "2" +#define POD_OPENING "3" +#define POD_LEAVING "4" + +#define MOB_OPTION "Mobs" +#define UNANCHORED_OPTION "Unanchored" +#define ANCHORED_OPTION "Anchored" +#define MECHA_OPTION "Mecha" + +#define SUPPLYPOD_X_OFFSET -16 diff --git a/code/__DEFINES/dcs/signals_object.dm b/code/__DEFINES/dcs/signals_object.dm index 1d81249ab54..90cbb8b0150 100644 --- a/code/__DEFINES/dcs/signals_object.dm +++ b/code/__DEFINES/dcs/signals_object.dm @@ -22,3 +22,13 @@ ///from base of [/obj/proc/update_integrity]: (old_value, new_value) #define COMSIG_OBJ_INTEGRITY_CHANGED "obj_integrity_changed" + +///sent to targets during the process_hit proc of projectiles +#define COMSIG_FIRE_CASING "fire_casing" + +///called in /obj/item/grenade/proc/prime(): (user) +#define COMSIG_GRENADE_DETONATE "grenade_prime" + +///from [/obj/structure/closet/supplypod/proc/preOpen]: +#define COMSIG_SUPPLYPOD_LANDED "supplypodgoboom" + diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 65a3903b03f..0f780e66738 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -56,6 +56,12 @@ #define isstorage(A) (istype(A, /obj/item/storage)) +#define isgrenade(A) (istype(A, /obj/item/grenade)) + +#define issupplypod(A) (istype(A, /obj/structure/closet/supplypod)) + +#define isammocasing(A) (istype(A, /obj/item/ammo_casing)) + #define ismachinery(A) (istype(A, /obj/machinery)) #define isapc(A) (istype(A, /obj/machinery/power/apc)) diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 625ea9e3d55..5e2e651c8ce 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -75,3 +75,6 @@ /// Checks for finger coverage, prevents damage from nettles #define FINGERS_COVERED (1<<6) +/// Flags for the pod_flags var on /obj/structure/closet/supplypod +#define FIRST_SOUNDS (1<<0) // If it shouldn't play sounds the first time it lands, used for reverse mode + diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 556afae12fb..c0d717bb8ba 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -189,6 +189,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// This trait makes it so that an item literally cannot be removed at all, or at least that's how it should be. Only deleted. #define TRAIT_NODROP "nodrop" +#define TRAIT_SHRAPNEL "shrapnel" + ///Movement type traits for movables. See elements/movetype_handler.dm #define TRAIT_MOVE_GROUND "move_ground" diff --git a/code/__HELPERS/turfs.dm b/code/__HELPERS/turfs.dm new file mode 100644 index 00000000000..fa0f9639d4a --- /dev/null +++ b/code/__HELPERS/turfs.dm @@ -0,0 +1,27 @@ +///Returns a random turf on the station +/proc/get_random_station_turf() + var/list/turfs = get_area_turfs(pick(SSmapping.existing_station_areas)) + if (length(turfs)) + return pick(turfs) + +///Returns a random turf on the station, excludes dense turfs (like walls) and areas that have valid_territory set to FALSE +/proc/get_safe_random_station_turf(list/areas_to_pick_from = SSmapping.existing_station_areas) + for (var/i in 1 to 5) + var/list/turf_list = get_area_turfs(pick(areas_to_pick_from)) + var/turf/target + while (turf_list.len && !target) + var/I = rand(1, turf_list.len) + var/turf/checked_turf = turf_list[I] + var/area/turf_area = get_area(checked_turf) + if(!checked_turf.density && (turf_area.valid_territory) && !isgroundlessturf(checked_turf)) + var/clear = TRUE + for(var/obj/checked_object in checked_turf) + if(checked_object.density) + clear = FALSE + break + if(clear) + target = checked_turf + if (!target) + turf_list.Cut(I, I + 1) + if (target) + return target diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 6a4e744fbed..727a99fcfb5 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -22,6 +22,7 @@ GLOBAL_LIST_INIT(machines, list()) GLOBAL_LIST_INIT(syndiepads, list()) //list of all syndiepads GLOBAL_LIST_INIT(syndie_cargo_consoles, list()) //list of all syndie cargo consoles GLOBAL_LIST_INIT(rcd_list, list()) //list of Rapid Construction Devices. +GLOBAL_LIST_EMPTY(supplypod_loading_bays) GLOBAL_LIST_INIT(apcs, list()) GLOBAL_LIST_INIT(air_alarms, list()) @@ -64,3 +65,4 @@ GLOBAL_LIST_EMPTY(wire_color_directory) // This is an associative list with the GLOBAL_LIST_EMPTY(wire_name_directory) GLOBAL_LIST_EMPTY(visual_portals) +GLOBAL_LIST_EMPTY(pod_styles_by_type) diff --git a/code/_onclick/hud/map_view.dm b/code/_onclick/hud/map_view.dm index bc304f20f8a..38e6b0c984e 100644 --- a/code/_onclick/hud/map_view.dm +++ b/code/_onclick/hud/map_view.dm @@ -55,7 +55,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/map_view) return pop_planes /atom/movable/screen/map_view/proc/hide_from(mob/hide_from) - hide_from?.canon_client.clear_map(assigned_map) + hide_from?.canon_client?.clear_map(assigned_map) var/client_ref = WEAKREF(hide_from?.canon_client) // Make sure we clear the *right* hud diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm new file mode 100644 index 00000000000..eb8635effc0 --- /dev/null +++ b/code/datums/components/pellet_cloud.dm @@ -0,0 +1,325 @@ +// the following defines are used for [/datum/component/pellet_cloud/var/list/wound_info_by_part] to store the damage, wound_bonus, and bw_bonus for each bodypart hit +#define CLOUD_POSITION_DAMAGE 1 +#define CLOUD_POSITION_W_BONUS 2 +#define CLOUD_POSITION_BW_BONUS 3 + +/* + * This component is used when you want to create a bunch of shrapnel or projectiles (say, shrapnel from a fragmentation grenade, or buckshot from a shotgun) from a central point, + * without necessarily printing a separate message for every single impact. This component should be instantiated right when you need it (like the moment of firing), then activated + * by signal. + * + * Pellet cloud currently works on two classes of sources: directed (ammo casings), and circular (grenades, landmines). + * -Directed: This means you're shooting multiple pellets, like buckshot. If an ammo casing is defined as having multiple pellets, it will automatically create a pellet cloud + * and call COMSIG_FIRE_CASING (see [/obj/item/ammo_casing/proc/fire_casing]). Thus, the only projectiles fired will be the ones fired here. + * The magnitude var controls how many pellets are created. + * -Circular: This results in a big spray of shrapnel flying all around the detonation point when the grenade fires COMSIG_GRENADE_DETONATE or landmine triggers COMSIG_MINE_TRIGGERED. + * The magnitude var controls how big the detonation radius is (the bigger the magnitude, the more shrapnel is created). Grenades can be covered with bodies to reduce shrapnel output. + * + * Once all of the fired projectiles either hit a target or disappear due to ranging out/whatever else, we resolve the list of all the things we hit and print aggregate messages so we get + * one "You're hit by 6 buckshot pellets" vs 6x "You're hit by the buckshot blah blah" messages. + * + * Note that this is how all guns handle shooting ammo casings with multiple pellets, in case such a thing comes up. +*/ + +/datum/component/pellet_cloud + /// What's the projectile path of the shrapnel we're shooting? + var/projectile_type + + /// How many shrapnel projectiles are we responsible for tracking? May be reduced for grenades if someone dives on top of it. Defined by ammo casing for casings, derived from magnitude otherwise + var/num_pellets + /// For grenades/landmines, how big is the radius of turfs we're targeting? Note this does not effect the projectiles range, only how many we generate + var/radius = 4 + + /// The list of pellets we're responsible for tracking, once these are all accounted for, we finalize. + var/list/pellets = list() + /// An associated list with the atom hit as the key and how many pellets they've eaten for the value, for printing aggregate messages + var/list/targets_hit = list() + /// Another associated list for hit bodyparts on carbons so we can track how much wounding potential we have for each bodypart + var/list/wound_info_by_part = list() + /// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs] + var/list/bodies + /// For grenades, tracking people who die covering a grenade for achievement purposes, see [/datum/component/pellet_cloud/proc/handle_martyrs] + var/list/purple_hearts + + /// For grenades, tracking how many pellets are removed due to martyrs and how many pellets are added due to the last person to touch it being on top of it + var/pellet_delta = 0 + /// how many pellets ranged out without hitting anything + var/terminated + /// how many pellets impacted something + var/hits + /// If the parent tried deleting and we're not done yet, we send it to nullspace then delete it after + var/queued_delete = FALSE + + /// for if we're an ammo casing being fired + var/mob/living/shooter + + +/datum/component/pellet_cloud/Initialize(projectile_type=/obj/item/projectile/shrapnel, magnitude=5) + if(!isammocasing(parent) && !isgrenade(parent) && !issupplypod(parent)) + return COMPONENT_INCOMPATIBLE + + if(magnitude < 1) + stack_trace("Invalid magnitude [magnitude] < 1 on pellet_cloud, parent: [parent]") + magnitude = 1 + + src.projectile_type = projectile_type + + if(isammocasing(parent)) + num_pellets = magnitude + else if(isgrenade(parent) || issupplypod(parent)) + radius = magnitude + +/datum/component/pellet_cloud/Destroy(force) + purple_hearts = null + pellets = null + targets_hit = null + wound_info_by_part = null + bodies = null + return ..() + +/datum/component/pellet_cloud/RegisterWithParent() + RegisterSignal(parent, COMSIG_PREQDELETED, PROC_REF(nullspace_parent)) + if(isammocasing(parent)) + RegisterSignal(parent, COMSIG_FIRE_CASING, PROC_REF(create_casing_pellets)) + else if(isgrenade(parent)) + RegisterSignal(parent, COMSIG_GRENADE_ARMED, PROC_REF(grenade_armed)) + RegisterSignal(parent, COMSIG_GRENADE_DETONATE, PROC_REF(create_blast_pellets)) + else if(issupplypod(parent)) + RegisterSignal(parent, COMSIG_SUPPLYPOD_LANDED, PROC_REF(create_blast_pellets)) + +/datum/component/pellet_cloud/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_PREQDELETED, COMSIG_FIRE_CASING, COMSIG_GRENADE_DETONATE, COMSIG_GRENADE_ARMED, COMSIG_MOVABLE_MOVED, COMSIG_ITEM_DROPPED)) + +/** + * create_casing_pellets() is for directed pellet clouds for ammo casings that have multiple pellets (buckshot and scatter lasers for instance) + * + * Honestly this is mostly just a rehash of [/obj/item/ammo_casing/proc/fire_casing] for pellet counts > 1, except this lets us tamper with the pellets and hook onto them for tracking purposes. + * The arguments really don't matter, while this proc is triggered by COMSIG_FIRE_CASING, it's just a big mess of the state vars we need for doing the stuff over here. + */ +/datum/component/pellet_cloud/proc/create_casing_pellets(obj/item/ammo_casing/shell, atom/target, mob/living/user, fired_from, randomspread, spread, zone_override, params, distro) + SIGNAL_HANDLER + + shooter = user + var/turf/target_loc = get_turf(target) + if(!zone_override) + zone_override = shooter.zone_selected + + // things like mouth executions and gunpoints can multiply the damage and wounds of projectiles, so this makes sure those effects are applied to each pellet instead of just one + var/original_damage = shell.BB.damage + + for(var/i in 1 to num_pellets) + shell.ready_proj(target, user, TRUE, zone_override, fired_from) + if(distro) + if(randomspread) + spread = round((rand() - 0.5) * distro) + else //Smart spread + spread = round((i / num_pellets - 0.5) * distro) + + RegisterSignal(shell.BB, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(pellet_hit)) + RegisterSignals(shell.BB, list(COMSIG_PROJECTILE_RANGE_OUT, COMSIG_QDELETING), PROC_REF(pellet_range)) + shell.BB.damage = original_damage + pellets += shell.BB + var/turf/current_loc = get_turf(fired_from) + if (!istype(target_loc) || !istype(current_loc) || !(shell.BB)) + return + INVOKE_ASYNC(shell, TYPE_PROC_REF(/obj/item/ammo_casing, throw_proj), target, target_loc, shooter, params, spread, fired_from) + + if(i != num_pellets) + shell.newshot() + +/** + * create_blast_pellets() is for when we have a central point we want to shred the surroundings of with a ring of shrapnel, namely frag grenades and landmines. + * + * Note that grenades have extra handling for someone throwing themselves/being thrown on top of it, see [/datum/component/pellet_cloud/proc/handle_martyrs] + * Landmines just have a small check for [/obj/effect/mine/shrapnel/var/shred_triggerer], and spawn extra shrapnel for them if so + * + * Arguments: + * * O- Our parent, the thing making the shrapnel obviously (grenade or landmine) + * * punishable_triggerer- For grenade lances or people who step on the landmines (if we shred the triggerer), we spawn extra shrapnel for them in addition to the normal spread + */ +/datum/component/pellet_cloud/proc/create_blast_pellets(obj/O, mob/living/triggerer) + SIGNAL_HANDLER + + var/atom/A = parent + + if(isgrenade(parent)) // handle_martyrs can reduce the radius and thus the number of pellets we produce if someone dives on top of a frag grenade + INVOKE_ASYNC(src, PROC_REF(handle_martyrs), triggerer) // note that we can modify radius in this proc + + if(radius < 1) + return + + var/list/all_the_turfs_were_gonna_lacerate = RANGE_TURFS(radius, A) - RANGE_TURFS(radius-1, A) + num_pellets = all_the_turfs_were_gonna_lacerate.len + pellet_delta + + for(var/T in all_the_turfs_were_gonna_lacerate) + INVOKE_ASYNC(src, PROC_REF(pew), T) + +/** + * handle_martyrs() is used for grenades that shoot shrapnel to check if anyone threw themselves/were thrown on top of the grenade, thus absorbing a good chunk of the shrapnel + * + * Between the time the grenade is armed and the actual detonation, we set var/list/bodies to the list of mobs currently on the new tile, as if the grenade landed on top of them, tracking if any of them move off the tile and removing them from the "under" list + * Once the grenade detonates, handle_martyrs() is called and gets all the new mobs on the tile, and add the ones not in var/list/bodies to var/list/martyrs + * We then iterate through the martyrs and reduce the shrapnel magnitude for each mob on top of it, shredding each of them with some of the shrapnel they helped absorb. This can snuff out all of the shrapnel if there's enough bodies + * + * Note we track anyone who's alive and client'd when they get shredded in var/list/purple_hearts, for achievement checking later + */ +/datum/component/pellet_cloud/proc/handle_martyrs(mob/living/punishable_triggerer) + var/magnitude_absorbed + var/list/martyrs = list() + + var/self_harm_radius_mult = 3 + + if(punishable_triggerer && prob(60)) + to_chat(punishable_triggerer, span_userdanger("Your plan to whack someone with a grenade on a stick backfires on you, literally!")) + self_harm_radius_mult = 1 // we'll still give the guy who got hit some extra shredding, but not 3*radius + pellet_delta += radius + for(var/i in 1 to radius) + pew(punishable_triggerer) // thought you could be tricky and lance someone with no ill effects!! + + for(var/mob/living/body in get_turf(parent)) + if(body == shooter) + pellet_delta += radius * self_harm_radius_mult + for(var/i in 1 to radius * self_harm_radius_mult) + pew(body) // free shrapnel if it goes off in your hand, and it doesn't even count towards the absorbed. fun! + else if(!(body in bodies)) + martyrs += body // promoted from a corpse to a hero + + for(var/M in martyrs) + var/mob/living/martyr = M + if(radius > 4) + martyr.visible_message("[span_danger("[martyr] heroically covers \the [parent] with [martyr.p_their()] body, absorbing a load of the shrapnel!")]", span_userdanger("You heroically cover \the [parent] with your body, absorbing a load of the shrapnel!")) + magnitude_absorbed += round(radius * 0.5) + else if(radius >= 2) + martyr.visible_message("[span_danger("[martyr] heroically covers \the [parent] with [martyr.p_their()] body, absorbing some of the shrapnel!")]", span_userdanger("You heroically cover \the [parent] with your body, absorbing some of the shrapnel!")) + magnitude_absorbed += 2 + else + martyr.visible_message("[span_danger("[martyr] heroically covers \the [parent] with [martyr.p_their()] body, snuffing out the shrapnel!")]", span_userdanger("You heroically cover \the [parent] with your body, snuffing out the shrapnel!")) + magnitude_absorbed = radius + + var/pellets_absorbed = (radius ** 2) - ((radius - magnitude_absorbed - 1) ** 2) + radius -= magnitude_absorbed + pellet_delta -= round(pellets_absorbed * 0.5) + + if(martyr.stat != DEAD && martyr.client) + LAZYADD(purple_hearts, martyr) + RegisterSignal(martyr, COMSIG_QDELETING, PROC_REF(on_target_qdel), override=TRUE) + + for(var/i in 1 to round(pellets_absorbed * 0.5)) + pew(martyr) + + if(radius < 1) + break + +///One of our pellets hit something, record what it was and check if we're done (terminated == num_pellets) +/datum/component/pellet_cloud/proc/pellet_hit(obj/item/projectile/P, atom/movable/firer, atom/target, Angle, hit_zone) + SIGNAL_HANDLER + + pellets -= P + terminated++ + hits++ + + var/damage = TRUE + if(isobj(target)) + var/obj/hit_object = target + if(hit_object.damage_deflection > P.damage || !P.damage) + damage = FALSE + + LAZYADDASSOC(targets_hit[target], "hits", 1) + LAZYSET(targets_hit[target], "damage", damage) + if(targets_hit[target]["hits"] == 1) + RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_qdel), override=TRUE) + UnregisterSignal(P, list(COMSIG_QDELETING, COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PROJECTILE_SELF_ON_HIT)) + if(terminated == num_pellets) + finalize() + +///One of our pellets disappeared due to hitting their max range (or just somehow got qdel'd), remove it from our list and check if we're done (terminated == num_pellets) +/datum/component/pellet_cloud/proc/pellet_range(obj/item/projectile/P) + SIGNAL_HANDLER + pellets -= P + terminated++ + UnregisterSignal(P, list(COMSIG_QDELETING, COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PROJECTILE_SELF_ON_HIT)) + if(terminated == num_pellets) + finalize() + +/// Minor convenience function for creating each shrapnel piece with circle explosions, mostly stolen from the MIRV component +/datum/component/pellet_cloud/proc/pew(atom/target, landmine_victim) + + var/obj/item/projectile/P = new projectile_type(get_turf(parent)) + + //Shooting Code: + P.spread = 0 + P.original = target + P.firer_source_atom = parent + P.firer = parent // don't hit ourself that would be really annoying + P.suppressed = TRUE// set the projectiles to make no message so we can do our own aggregate message + P.preparePixelProjectile(target, target, parent) + RegisterSignal(P, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(pellet_hit)) + RegisterSignals(P, list(COMSIG_PROJECTILE_RANGE_OUT, COMSIG_QDELETING), PROC_REF(pellet_range)) + pellets += P + P.fire() + +///All of our pellets are accounted for, time to go target by target and tell them how many things they got hit by. +/datum/component/pellet_cloud/proc/finalize() + UnregisterSignal(parent, COMSIG_PREQDELETED) + if(queued_delete) + qdel(parent) + qdel(src) + +/// Look alive, we're armed! Now we start watching to see if anyone's covering us +/datum/component/pellet_cloud/proc/grenade_armed(obj/item/nade) + SIGNAL_HANDLER + + if(ismob(nade.loc)) + shooter = nade.loc + LAZYINITLIST(bodies) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(grenade_dropped)) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(grenade_moved)) + var/static/list/loc_connections = list( + COMSIG_ATOM_EXITED = PROC_REF(grenade_uncrossed), + ) + AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections) + +/// Someone dropped the grenade, so set them to the shooter in case they're on top of it when it goes off +/datum/component/pellet_cloud/proc/grenade_dropped(obj/item/nade, mob/living/slick_willy) + SIGNAL_HANDLER + + shooter = slick_willy + grenade_moved() + +/// Our grenade has moved, reset var/list/bodies so we're "on top" of any mobs currently on the tile +/datum/component/pellet_cloud/proc/grenade_moved() + SIGNAL_HANDLER + + LAZYCLEARLIST(bodies) + for(var/mob/living/L in get_turf(parent)) + RegisterSignal(L, COMSIG_QDELETING, PROC_REF(on_target_qdel), override=TRUE) + bodies += L + +/// Someone who was originally "under" the grenade has moved off the tile and is now eligible for being a martyr and "covering" it +/datum/component/pellet_cloud/proc/grenade_uncrossed(datum/source, atom/movable/gone, direction) + SIGNAL_HANDLER + + bodies -= gone + +/// Our grenade or landmine or caseless shell or whatever tried deleting itself, so we intervene and nullspace it until we're done here +/datum/component/pellet_cloud/proc/nullspace_parent() + SIGNAL_HANDLER + + var/atom/movable/AM = parent + AM.moveToNullspace() + queued_delete = TRUE + return TRUE + +/// Someone who was originally "under" the grenade has moved off the tile and is now eligible for being a martyr and "covering" it +/datum/component/pellet_cloud/proc/on_target_qdel(atom/target) + SIGNAL_HANDLER + + UnregisterSignal(target, COMSIG_QDELETING) + targets_hit -= target + LAZYREMOVE(bodies, target) + LAZYREMOVE(purple_hearts, target) + + +#undef CLOUD_POSITION_DAMAGE +#undef CLOUD_POSITION_W_BONUS +#undef CLOUD_POSITION_BW_BONUS diff --git a/code/datums/pod_style.dm b/code/datums/pod_style.dm new file mode 100644 index 00000000000..435b0941324 --- /dev/null +++ b/code/datums/pod_style.dm @@ -0,0 +1,258 @@ +/// Datum holding information about pod type visuals, VFX, name and description +/// These are not created anywhere and thus should not be assigned procs, only being used as data storage +/datum/pod_style + /// Name that pods of this style will be named by default + var/name = "supply pod" + /// Name that is displayed to admins in pod config panel + var/ui_name = "Стандартная" + /// Description assigned to droppods of this style + var/desc = "Капсула снабжения «Nanotrasen»." + /// Determines if this pod can use animations/masking/overlays + var/shape = POD_SHAPE_NORMAL + /// Base icon state assigned to this pod + var/icon_state = "pod" + /// Whenever this pod should have a door overlay added to it. Uses [icon_state]_door sprite + var/has_door = TRUE + /// Decals added to this pod, if any + var/decal_icon = "default" + /// Color that this pod glows when landing + var/glow_color = "yellow" + /// Type of rubble that this pod creates upon landing + var/rubble_type = RUBBLE_NORMAL + /// ID for TGUI data + var/id = "standard" + + var/list/ru_names = list( + NOMINATIVE = "капсула снабжения", + GENITIVE = "капсулы снабжения", + DATIVE = "капсуле снабжения", + ACCUSATIVE = "капсулу снабжения", + INSTRUMENTAL = "капсулой снабжения", + PREPOSITIONAL = "капсуле снабжения" + ) + + +/datum/pod_style/advanced + name = "bluespace supply pod" + ui_name = "Продвинутая" + desc = "Блюспейс капсула снабжения Nanotrasen. После доставки телепортируется обратно." + decal_icon = "bluespace" + glow_color = "blue" + id = "bluespace" + ru_names = list( + NOMINATIVE = "блюспейс капсула снабжения", + GENITIVE = "блюспейс капсулы снабжения", + DATIVE = "блюспейс капсуле снабжения", + ACCUSATIVE = "блюспейс капсулу снабжения", + INSTRUMENTAL = "блюспейс капсулой снабжения", + PREPOSITIONAL = "блюспейс капсуле снабжения" + ) + +/datum/pod_style/centcom + name = "\improper CentCom supply pod" + ui_name = "Nanotrasen" + desc = "Капсула снабжения «Nanotrasen», отмеченный обозначениями Центрального командования. После доставки телепортируется обратно." + decal_icon = "centcom" + glow_color = "blue" + id = "centcom" + ru_names = list( + NOMINATIVE = "капсула снабжения Центрального командования", + GENITIVE = "капсулы снабжения Центрального командования", + DATIVE = "капсуле снабжения Центрального командования", + ACCUSATIVE = "капсулу снабжения Центрального командования", + INSTRUMENTAL = "капсулой снабжения Центрального командования", + PREPOSITIONAL = "капсуле снабжения Центрального командования" + ) + +/datum/pod_style/syndicate + name = "blood-red supply pod" + ui_name = "Синдиката" + desc = "Устрашающая капсула снабжения, покрытая кроваво-красными знаками Синдиката. Наверное, лучше держаться подальше." + icon_state = "darkpod" + decal_icon = "syndicate" + glow_color = "red" + id = "syndicate" + ru_names = list( + NOMINATIVE = "кроваво-красная капсула снабжения", + GENITIVE = "кроваво-красной капсулы снабжения", + DATIVE = "кроваво-красной капсуле снабжения", + ACCUSATIVE = "кроваво-красную капсулу снабжения", + INSTRUMENTAL = "кроваво-красной капсулой снабжения", + PREPOSITIONAL = "кроваво-красной капсуле снабжения" + ) + +/datum/pod_style/deathsquad + name = "\improper Deathsquad drop pod" + ui_name = "Отряда Смерти" + desc = "Капсула Nanotrasen. На ней отмечена маркировка элитной ударной группы Nanotrasen." + icon_state = "darkpod" + decal_icon = "deathsquad" + glow_color = "blue" + id = "deathsquad" + ru_names = list( + NOMINATIVE = "капсула Отряда Смерти", + GENITIVE = "капсулы Отряда Смерти", + DATIVE = "капсуле Отряда Смерти", + ACCUSATIVE = "капсулу Отряда Смерти", + INSTRUMENTAL = "капсулой Отряда Смерти", + PREPOSITIONAL = "капсуле Отряда Смерти" + ) + +/datum/pod_style/cultist + name = "bloody supply pod" + ui_name = "Кльтистская" + desc = "Капсула снабжения Nanotrasen, вся в царапинах, крови и странных рунах." + decal_icon = "cultist" + glow_color = "red" + id = "cultist" + ru_names = list( + NOMINATIVE = "кровавая капсула снабжения", + GENITIVE = "кровавой капсулы снабжения", + DATIVE = "кровавой капсуле снабжения", + ACCUSATIVE = "кровавую капсулу снабжения", + INSTRUMENTAL = "кровавой капсулой снабжения", + PREPOSITIONAL = "кровавой капсуле снабжения" + ) + +/datum/pod_style/missile + name = "cruise missile" + ui_name = "Ракета" + desc = "Огромная ракета, которая, похоже, не взорвалась полностью. Вероятно, она была запущена из какой-то далекой ракетной шахты в дальнем космосе. Судя по всему, сбоку имеется люк для вспомогательной полезной нагрузки, хотя открыть его вручную, скорее всего, невозможно." + shape = POD_SHAPE_OTHER + icon_state = "missile" + has_door = FALSE + decal_icon = null + glow_color = null + rubble_type = RUBBLE_THIN + id = "missile" + ru_names = list( + NOMINATIVE = "крылатая ракета", + GENITIVE = "крылатой ракеты", + DATIVE = "крылатой ракете", + ACCUSATIVE = "крылатую ракету", + INSTRUMENTAL = "крылатой ракете", + PREPOSITIONAL = "крылатой ракетой" + ) + +/datum/pod_style/missile/syndicate + name = "\improper Syndicate cruise missile" + ui_name = "Ракета Синдиката" + desc = "Огромная кроваво-красная ракета, которая, похоже, не взорвалась полностью. Вероятно, она была запущена из какой-то ракетной шахты Синдиката в дальнем космосе. Судя по всему, сбоку имеется люк для вспомогательной полезной нагрузки, хотя открыть его вручную, скорее всего, невозможно." + icon_state = "smissile" + id = "syndie_missile" + ru_names = list( + NOMINATIVE = "крылатая ракета Синдиката", + GENITIVE = "крылатой ракеты Синдиката", + DATIVE = "крылатой ракете Синдиката", + ACCUSATIVE = "крылатую ракету Синдиката", + INSTRUMENTAL = "крылатой ракете Синдиката", + PREPOSITIONAL = "крылатой ракетой Синдиката" + ) + +/datum/pod_style/box + name = "\improper Aussec supply crate" + ui_name = "Ящик припасов" + desc = "Невероятно прочный ящик с припасами, рассчитанный на то, чтобы выдержать возвращение на орбиту. Сбоку выгравирована надпись «Aussec Armory — 2532»." + shape = POD_SHAPE_OTHER + icon_state = "box" + decal_icon = null + glow_color = null + rubble_type = RUBBLE_WIDE + id = "supply_box" + ru_names = list( + NOMINATIVE = "ящик с припасами Aussec", + GENITIVE = "ящика с припасами Aussec", + DATIVE = "ящику с припасами Aussec", + ACCUSATIVE = "ящик с припасами Aussec", + INSTRUMENTAL = "ящиком с припасами Aussec", + PREPOSITIONAL = "ящике с припасами Aussec" + ) + +/datum/pod_style/clown + name = "\improper HONK pod" + ui_name = "Капсула Клоунов" + desc = "Яркая капсула снабжения. Вероятно, она отправлена Федерацией клоунов." + icon_state = "clownpod" + decal_icon = "clown" + glow_color = "green" + id = "clown" + ru_names = list( + NOMINATIVE = "ХОНК капсула", + GENITIVE = "ХОНК капсулы", + DATIVE = "ХОНК капсуле", + ACCUSATIVE = "ХОНК капсулу", + INSTRUMENTAL = "ХОНК капсулой", + PREPOSITIONAL = "ХОНК капсуле" + ) + +/datum/pod_style/orange + name = "\improper Orange" + ui_name = "Фрукт" + desc = "Злой апельсин." + shape = POD_SHAPE_OTHER + icon_state = "orange" + decal_icon = null + glow_color = null + rubble_type = RUBBLE_WIDE + id = "orange" + ru_names = list( + NOMINATIVE = "апельсин", + GENITIVE = "апельсина", + DATIVE = "апельсину", + ACCUSATIVE = "апельсин", + INSTRUMENTAL = "апельсином", + PREPOSITIONAL = "апельсине" + ) + +/datum/pod_style/invisible + name = "\improper S.T.E.A.L.T.H. pod MKVII" + ui_name = "Невидимый" + desc = "Капсула снабжения, которая при нормальных обстоятельствах совершенно невидима для обычных методов обнаружения. Как ты вообще её видишь?" + shape = POD_SHAPE_OTHER + has_door = FALSE + icon_state = null + decal_icon = null + glow_color = null + rubble_type = RUBBLE_NONE + id = "invisible" + ru_names = list( + NOMINATIVE = "капсула S.T.E.A.L.T.H. MKVII", + GENITIVE = "капсулы S.T.E.A.L.T.H. MKVII", + DATIVE = "капсуле S.T.E.A.L.T.H. MKVII", + ACCUSATIVE = "капсулу S.T.E.A.L.T.H. MKVII", + INSTRUMENTAL = "капсулой S.T.E.A.L.T.H. MKVII", + PREPOSITIONAL = "капсуле S.T.E.A.L.T.H. MKVII" + ) + +/datum/pod_style/gondola + name = "gondola" + ui_name = "Гандола" + desc = "Бесшумный ходок. Кажется, это сотрудник агентства доставки." + shape = POD_SHAPE_OTHER + icon_state = "gondola" + has_door = FALSE + decal_icon = null + glow_color = null + rubble_type = RUBBLE_NONE + id = "gondola" + ru_names = list( + NOMINATIVE = "гандола", + GENITIVE = "гандолы", + DATIVE = "гандоле", + ACCUSATIVE = "гандолу", + INSTRUMENTAL = "гандолой", + PREPOSITIONAL = "гандоле" + ) + + +/datum/pod_style/seethrough + name = null + ui_name = "Смотрящий насквозь" + desc = null + shape = POD_SHAPE_OTHER + has_door = FALSE + icon_state = null + decal_icon = null + glow_color = null + rubble_type = RUBBLE_NONE + id = "seethrough" diff --git a/code/game/area/ss13_areas.dm b/code/game/area/ss13_areas.dm index e5ea0c52ff5..5cef7ab1305 100644 --- a/code/game/area/ss13_areas.dm +++ b/code/game/area/ss13_areas.dm @@ -524,6 +524,52 @@ This applies to all STANDARD station areas /area/centcom/shuttle name = "Centcom Administration Shuttle" +/area/centcom/supplypod/supplypod_temp_holding + name = "Supplypod Shipping Lane" + icon_state = "supplypod_flight" + area_flags = UNIQUE_AREA + +/area/centcom/supplypod + name = "Supplypod Facility" + icon_state = "supplypod" + +/area/centcom/supplypod/pod_storage + name = "Supplypod Storage" + icon_state = "supplypod_holding" + +/area/centcom/supplypod/loading + name = "Supplypod Loading Facility" + icon_state = "supplypod_loading" + var/loading_id = "" + +/area/centcom/supplypod/loading/Initialize(mapload) + . = ..() + if(!loading_id) + CRASH("[type] created without a loading_id") + if(GLOB.supplypod_loading_bays[loading_id]) + CRASH("Duplicate loading bay area: [type] ([loading_id])") + GLOB.supplypod_loading_bays[loading_id] = src + +/area/centcom/supplypod/loading/one + name = "Bay #1" + loading_id = "1" + +/area/centcom/supplypod/loading/two + name = "Bay #2" + loading_id = "2" + +/area/centcom/supplypod/loading/three + name = "Bay #3" + loading_id = "3" + +/area/centcom/supplypod/loading/four + name = "Bay #4" + loading_id = "4" + +/area/centcom/supplypod/loading/ert + name = "ERT Bay" + loading_id = "5" + //SYNDICATES /area/syndicate_mothership diff --git a/code/game/atoms.dm b/code/game/atoms.dm index be28da3341b..71eff1cfe86 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -332,6 +332,12 @@ /atom/proc/is_open_container() return is_refillable() && is_drainable() +/atom/proc/setOpened() + return + +/atom/proc/setClosed() + return + /// Is this atom injectable into other atoms /atom/proc/is_injectable(mob/user, allowmobs = TRUE) return reagents && (container_type & (INJECTABLE|REFILLABLE)) diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index 707a1b6aa34..4345c39f94d 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -91,6 +91,10 @@ icon_state = "pod_mess" +/obj/effect/supplypod_selector + icon_state = "supplypod_selector" + layer = FLY_LAYER + //Makes a tile fully lit no matter what /obj/effect/fullbright icon = 'icons/effects/alphacolors.dmi' diff --git a/code/game/objects/items/weapons/grenades/atmosgrenade.dm b/code/game/objects/items/weapons/grenades/atmosgrenade.dm index d10359f77ee..655f7db000f 100644 --- a/code/game/objects/items/weapons/grenades/atmosgrenade.dm +++ b/code/game/objects/items/weapons/grenades/atmosgrenade.dm @@ -9,6 +9,7 @@ var/spawn_amount = 100 /obj/item/grenade/gas/prime() + . = ..() var/turf/simulated/target_turf = get_turf(src) if(istype(target_turf)) target_turf.atmos_spawn_air(spawn_contents, spawn_amount) diff --git a/code/game/objects/items/weapons/grenades/bananade.dm b/code/game/objects/items/weapons/grenades/bananade.dm index 43cb37616db..1accb8dcaa7 100644 --- a/code/game/objects/items/weapons/grenades/bananade.dm +++ b/code/game/objects/items/weapons/grenades/bananade.dm @@ -13,6 +13,7 @@ /obj/item/grenade/bananade/prime() + . = ..() if(spawner_type && deliveryamt) // Make a quick flash var/turf/T = get_turf(src) diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 550f4fe8e7f..9b254d6dde3 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -347,6 +347,7 @@ /obj/item/grenade/chem_grenade/prime(mob/user) + . = ..() if(stage != READY) return diff --git a/code/game/objects/items/weapons/grenades/clowngrenade.dm b/code/game/objects/items/weapons/grenades/clowngrenade.dm index 09b00171fca..95fd2821015 100644 --- a/code/game/objects/items/weapons/grenades/clowngrenade.dm +++ b/code/game/objects/items/weapons/grenades/clowngrenade.dm @@ -11,7 +11,7 @@ var/affected_area = 2 /obj/item/grenade/clown_grenade/prime() - ..() + . = ..() playsound(src.loc, 'sound/items/bikehorn.ogg', 25, -3) var/i = 0 var/number = 0 diff --git a/code/game/objects/items/weapons/grenades/clusterbuster.dm b/code/game/objects/items/weapons/grenades/clusterbuster.dm index a7650c2fb22..7880b6753c5 100644 --- a/code/game/objects/items/weapons/grenades/clusterbuster.dm +++ b/code/game/objects/items/weapons/grenades/clusterbuster.dm @@ -12,6 +12,7 @@ var/payload_power = CLUSTERBUSTER_PAYLOAD_POWER /obj/item/grenade/clusterbuster/prime() + . = ..() update_mob() var/numspawned = rand(4,8) var/again = 0 diff --git a/code/game/objects/items/weapons/grenades/confetti.dm b/code/game/objects/items/weapons/grenades/confetti.dm index c0ef064ccee..d4c57175e31 100644 --- a/code/game/objects/items/weapons/grenades/confetti.dm +++ b/code/game/objects/items/weapons/grenades/confetti.dm @@ -5,6 +5,7 @@ var/spawner_type = /obj/effect/decal/cleanable/confetti /obj/item/grenade/confetti/prime() + . = ..() var/turf/T = get_turf(src) playsound(T, 'sound/effects/confetti_partywhistle.ogg', 100, 1) for(var/i in 1 to 20) //20 confettis. Yes. diff --git a/code/game/objects/items/weapons/grenades/emgrenade.dm b/code/game/objects/items/weapons/grenades/emgrenade.dm index 24ec4fccf13..516efc0a6b7 100644 --- a/code/game/objects/items/weapons/grenades/emgrenade.dm +++ b/code/game/objects/items/weapons/grenades/emgrenade.dm @@ -6,6 +6,7 @@ origin_tech = "magnets=3;combat=2" /obj/item/grenade/empgrenade/prime() + . = ..() update_mob() empulse(src, 4, 10, TRUE, name) qdel(src) diff --git a/code/game/objects/items/weapons/grenades/fauna_bomb.dm b/code/game/objects/items/weapons/grenades/fauna_bomb.dm index 6ca2c4314be..ca2b2ff696c 100644 --- a/code/game/objects/items/weapons/grenades/fauna_bomb.dm +++ b/code/game/objects/items/weapons/grenades/fauna_bomb.dm @@ -23,6 +23,7 @@ return ..(user, FALSE) /obj/item/grenade/fauna_bomb/prime() + . = ..() active = FALSE playsound(get_turf(src), 'sound/items/rawr.ogg', 100, TRUE) var/faction = activator.name + "_fauna_bomb" diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index 511f7cc5fa4..8494d0fa372 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -11,6 +11,7 @@ var/range = 7 // The range in tiles of the flashbang /obj/item/grenade/flashbang/prime(power = 1) + . = ..() update_mob() var/turf/T = get_turf(src) if(T) diff --git a/code/game/objects/items/weapons/grenades/frag.dm b/code/game/objects/items/weapons/grenades/frag.dm index a766c3b126b..e6598581233 100644 --- a/code/game/objects/items/weapons/grenades/frag.dm +++ b/code/game/objects/items/weapons/grenades/frag.dm @@ -11,6 +11,7 @@ var/embedded_type = /obj/item/embedded/shrapnel /obj/item/grenade/frag/prime() + . = ..() update_mob() var/turf/epicenter = get_turf(src) for(var/mob/living/carbon/human/H in epicenter) diff --git a/code/game/objects/items/weapons/grenades/ghettobomb.dm b/code/game/objects/items/weapons/grenades/ghettobomb.dm index d5dc255be5f..7331a194e12 100644 --- a/code/game/objects/items/weapons/grenades/ghettobomb.dm +++ b/code/game/objects/items/weapons/grenades/ghettobomb.dm @@ -59,6 +59,7 @@ addtimer(CALLBACK(src, PROC_REF(prime)), det_time) /obj/item/grenade/iedcasing/prime() //Blowing that can up + . = ..() update_mob() explosion(loc, -1, -1, 2, flame_range = 4, cause = src) // small explosion, plus a very large fireball. qdel(src) diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 1fa18ff923d..2d04b633521 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -71,6 +71,7 @@ /obj/item/grenade/proc/prime(mob/user) + SEND_SIGNAL(src, COMSIG_GRENADE_DETONATE, user) return diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm index 92038595b06..cafc27f38f4 100644 --- a/code/game/objects/items/weapons/grenades/smokebomb.dm +++ b/code/game/objects/items/weapons/grenades/smokebomb.dm @@ -18,6 +18,7 @@ return ..() /obj/item/grenade/smokebomb/prime() + . = ..() playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3) smoke.set_up(10, 0) spawn(0) diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 182119e9b3e..6e5d0e7f166 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -10,7 +10,7 @@ spawner_type = /mob/living/simple_animal/hostile/viscerator /obj/item/grenade/spawnergrenade/prime() // Prime now just handles the two loops that query for people in lockers and people who can see it. - + . = ..() if(spawner_type && deliveryamt) // Make a quick flash var/turf/T = get_turf(src) diff --git a/code/game/objects/items/weapons/grenades/syndieminibomb.dm b/code/game/objects/items/weapons/grenades/syndieminibomb.dm index 5c421fc0fd5..a8877bb2296 100644 --- a/code/game/objects/items/weapons/grenades/syndieminibomb.dm +++ b/code/game/objects/items/weapons/grenades/syndieminibomb.dm @@ -8,6 +8,7 @@ /obj/item/grenade/syndieminibomb/prime() + . = ..() update_mob() explosion(loc, 1, 2, 4, flame_range = 2, cause = src) qdel(src) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index e004f91fb64..878317a3f28 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -32,6 +32,7 @@ GLOBAL_LIST_EMPTY(closets) var/locked = FALSE var/large = TRUE var/can_be_emaged = FALSE + var/can_weld_shut = TRUE var/wall_mounted = FALSE //never solid (You can always pass over it) var/lastbang var/open_sound = 'sound/machines/closet_open.ogg' @@ -89,6 +90,26 @@ GLOBAL_LIST_EMPTY(closets) dump_contents() return ..() +/obj/structure/closet/vv_edit_var(vname, vval) + if(vname == NAMEOF(src, opened)) + if(vval == opened) + return FALSE + if(vval && !opened && open()) + datum_flags |= DF_VAR_EDITED + return TRUE + else if(!vval && opened && close()) + datum_flags |= DF_VAR_EDITED + return TRUE + return FALSE + . = ..() + if(vname == NAMEOF(src, welded) && welded && !can_weld_shut) + can_weld_shut = TRUE + else if(vname == NAMEOF(src, can_weld_shut) && !can_weld_shut && welded) + welded = FALSE + update_appearance() + if(vname in list(NAMEOF(src, locked), NAMEOF(src, welded))) + update_appearance() + /obj/structure/closet/CanAllowThrough(atom/movable/mover, border_dir) . = ..() @@ -138,6 +159,9 @@ GLOBAL_LIST_EMPTY(closets) after_open() return TRUE +/obj/structure/closet/setOpened() + open() + ///Proc to override for effects after opening a door /obj/structure/closet/proc/after_open(mob/living/user, force = FALSE) return @@ -188,6 +212,9 @@ GLOBAL_LIST_EMPTY(closets) set_density(ignore_density_closed ? FALSE : TRUE) return TRUE +/obj/structure/closet/setClosed() + close() + /obj/structure/closet/proc/toggle(mob/user) . = TRUE if(!(opened ? close() : open())) @@ -260,6 +287,8 @@ GLOBAL_LIST_EMPTY(closets) if(!opened && user.loc == src) to_chat(user, "You can't weld [src] from inside!") return + if(!can_weld_shut) + return if(!I.tool_use_check(user, 0)) return if(opened) @@ -453,10 +482,13 @@ GLOBAL_LIST_EMPTY(closets) user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1) /obj/structure/closet/ex_act(severity) + contents_explosion() + ..() + +/obj/structure/closet/proc/contents_explosion(severity) for(var/atom/A in contents) A.ex_act(severity) CHECK_TICK - ..() /obj/structure/closet/singularity_act() dump_contents() diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 9e7403ec955..8111891139d 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -112,6 +112,7 @@ GLOBAL_LIST_INIT(admin_verbs_event, list( /client/proc/cmd_admin_headset_message, /client/proc/force_hijack, /client/proc/requests, + /client/proc/centcom_podlauncher, /*Open a window to launch a Supplypod and configure it or it's contents*/ )) GLOBAL_LIST_INIT(admin_verbs_spawn, list( /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ @@ -513,34 +514,34 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list( /client/proc/drop_bomb() // Some admin dickery that can probably be done better -- TLE set category = "Event" set name = "Drop Bomb" - set desc = "Cause an explosion of varying strength at your location." + set desc = "Вызвать взрыв различной силы под вами." if(!check_rights(R_EVENT)) return var/turf/epicenter = mob.loc - var/list/choices = list("Small Bomb", "Medium Bomb", "Big Bomb", "Custom Bomb") - var/choice = input("What size explosion would you like to produce?") as null|anything in choices + var/list/choices = list("Маленькая бомба", "Средняя бомба", "Большая бомба", "Настраиваемая бомба") + var/choice = tgui_input_list(src, "Взрыв какого размера вы хотели бы произвести? ПРИМЕЧАНИЕ. Вы можете сделать все это в IC поле (используя крылатые ракеты!) с помощью кнопки Event/Launch Supplypod.", items = choices) switch(choice) if(null) return 0 - if("Small Bomb") + if("Маленькая бомба") explosion(epicenter, 1, 2, 3, 3, cause = "Admin Drop Bomb") - if("Medium Bomb") + if("Средняя бомба") explosion(epicenter, 2, 3, 4, 4, cause = "Admin Drop Bomb") - if("Big Bomb") + if("Большая бомба") explosion(epicenter, 3, 5, 7, 5, cause = "Admin Drop Bomb") - if("Custom Bomb") - var/devastation_range = tgui_input_number(src, "Devastation range (in tiles):", "Custom Bomb", max_value = 255) + if("Настраиваемая бомба") + var/devastation_range = tgui_input_number(src, "Дальность тотального разрушения. (в тайлах):", "Настраиваемая бомба", max_value = 255) if(isnull(devastation_range)) return - var/heavy_impact_range = tgui_input_number(src, "Heavy impact range (in tiles):", "Custom Bomb", max_value = 255) + var/heavy_impact_range = tgui_input_number(src, "Дальность сильного удара. (в тайлах):", "Настраиваемая бомба", max_value = 255) if(isnull(heavy_impact_range)) return - var/light_impact_range = tgui_input_number(src, "Light impact range (in tiles):", "Custom Bomb", max_value = 255) + var/light_impact_range = tgui_input_number(src, "Дальность легкого удара. (в тайлах):", "Настраиваемая бомба", max_value = 255) if(isnull(light_impact_range)) return - var/flash_range = tgui_input_number(src, "Flash range (in tiles):", "Custom Bomb", max_value = 255) + var/flash_range = tgui_input_number(src, "Дальность вспышки. (в тайлах):", "Настраиваемая бомба", max_value = 255) if(isnull(flash_range)) return explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, 1, 1, cause = "Admin Drop Bomb") diff --git a/code/modules/admin/verbs/cantcomm_cargo.dm b/code/modules/admin/verbs/cantcomm_cargo.dm new file mode 100644 index 00000000000..d40f8383298 --- /dev/null +++ b/code/modules/admin/verbs/cantcomm_cargo.dm @@ -0,0 +1,18 @@ +/client/proc/centcom_podlauncher() + set name = "Launch Supplypod" + set category = "Event" + set desc = "Настройте и запустите капсулу снабжения, полную всего, что душе угодно!" + + if(!check_rights(R_EVENT)) + return + + if(!SSticker) + to_chat(usr, span_warning("Игра еще не началась!")) + return + + if(SSticker.current_state <= GAME_STATE_PREGAME) + to_chat(usr, span_warning("Раунд еще не начался!")) + return + + var/datum/centcom_podlauncher/E = new(src.mob) + E.ui_interact(usr) diff --git a/code/modules/asset_cache/assets/supplypods.dm b/code/modules/asset_cache/assets/supplypods.dm new file mode 100644 index 00000000000..3807c080f62 --- /dev/null +++ b/code/modules/asset_cache/assets/supplypods.dm @@ -0,0 +1,27 @@ +/datum/asset/spritesheet/supplypods + name = "supplypods" + +/datum/asset/spritesheet/supplypods/create_spritesheets() + for (var/datum/pod_style/style as anything in typesof(/datum/pod_style)) + if (ispath(style, /datum/pod_style/seethrough)) + Insert("pod_asset[style::id]", icon('icons/obj/supplypods.dmi' , "seethrough-icon")) + continue + var/base = style::icon_state + if (!base) + Insert("pod_asset[style::id]", icon('icons/obj/supplypods.dmi', "invisible-icon")) + continue + var/icon/podIcon = icon('icons/obj/supplypods.dmi', base) + var/door = style::has_door + if (door) + door = "[base]_door" + podIcon.Blend(icon('icons/obj/supplypods.dmi', door), ICON_OVERLAY) + var/shape = style::shape + if (shape == POD_SHAPE_NORMAL) + var/decal = style::decal_icon + if (decal) + podIcon.Blend(icon('icons/obj/supplypods.dmi', decal), ICON_OVERLAY) + var/glow = style::glow_color + if (glow) + glow = "pod_glow_[glow]" + podIcon.Blend(icon('icons/obj/supplypods.dmi', glow), ICON_OVERLAY) + Insert("pod_asset[style::id]", podIcon) diff --git a/code/modules/buildmode/submodes/boom.dm b/code/modules/buildmode/submodes/boom.dm index 7c1b3da0305..1512bbc9ab2 100644 --- a/code/modules/buildmode/submodes/boom.dm +++ b/code/modules/buildmode/submodes/boom.dm @@ -8,20 +8,21 @@ var/flames = -1 /datum/buildmode_mode/boom/show_help(mob/user) - to_chat(user, "***********************************************************") - to_chat(user, "Mouse Button on obj = Kaboom") - to_chat(user, "***********************************************************") + to_chat(user, span_notice("***********************************************************")) + to_chat(user, span_notice("Кнопка мыши на объекте = Кабум")) + to_chat(user, span_notice("ПРИМЕЧАНИЕ. Использование кнопки «Event/Launch Supplypod» позволяет вам сделать в IC поле (т. е. заставить крылатую ракету упасть с неба и взорваться там, где вы щелкнете!)")) + to_chat(user, span_notice("***********************************************************")) /datum/buildmode_mode/boom/change_settings(mob/user) - devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null + devastation = tgui_input_number(usr, "Дальность тотального разрушения.", text("Ввод")) if(devastation == null) devastation = -1 - heavy = input("Range of heavy impact. -1 to none", text("Input")) as num|null + heavy = tgui_input_number(usr, "Дальность сильного удара.", text("Ввод")) if(heavy == null) heavy = -1 - light = input("Range of light impact. -1 to none", text("Input")) as num|null + light = tgui_input_number(usr, "Дальность легкого удара.", text("Ввод")) if(light == null) light = -1 - flash = input("Range of flash. -1 to none", text("Input")) as num|null + flash = tgui_input_number(usr, "Дальность вспышки.", text("Ввод")) if(flash == null) flash = -1 - flames = input("Range of flames. -1 to none", text("Input")) as num|null + flames = tgui_input_number(usr, "Дальность пламени.", text("Ввод")) if(flames == null) flames = -1 /datum/buildmode_mode/boom/handle_click(user, params, obj/object) diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm new file mode 100644 index 00000000000..b60d57583e7 --- /dev/null +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -0,0 +1,872 @@ +#define TAB_POD 0 //Used to check if the UIs built in camera is looking at the pod +#define TAB_BAY 1 //Used to check if the UIs built in camera is looking at the launch bay area + +#define LAUNCH_ALL 0 //Used to check if we're launching everything from the bay area at once +#define LAUNCH_ORDERED 1 //Used to check if we're launching everything from the bay area in order +#define LAUNCH_RANDOM 2 //Used to check if we're launching everything from the bay area randomly + +//The Great and Mighty CentCom Pod Launcher - MrDoomBringer +//This was originally created as a way to get adminspawned items to the station in an IC manner. It's evolved to contain a few more +//features such as item removal, smiting, controllable delivery mobs, and more. + +//This works by creating a supplypod (refered to as temp_pod) in a special room in the centcom map. +//IMPORTANT: Even though we call it a supplypod for our purposes, it can take on the appearance and function of many other things: Eg. cruise missiles, boxes, or walking, living gondolas. +//When the user launched the pod, items from special "bays" on the centcom map are taken and put into the supplypod + +//The user can change properties of the supplypod using the UI, and change the way that items are taken from the bay (One at a time, ordered, random, etc) +//Many of the effects of the supplypod set here are put into action in supplypod.dm + + +//Variables declared to change how items in the launch bay are picked and launched. (Almost) all of these are changed in the ui_act proc +//Some effect groups are choices, while other are booleans. This is because some effects can stack, while others dont (ex: you can stack explosion and quiet, but you cant stack ordered launch and random launch) +/datum/centcom_podlauncher + /// Static typecache of atoms we won't lift up, or pod or whatever. + var/static/list/ignored_atoms = typecacheof(list( + null, // I don't know why null is the first element of this typepache but it was there when I found it + /mob/dead, + /turf, + /obj/effect/landmark, + /obj/docking_port, + /obj/machinery/light, + /obj/effect/particle_effect/sparks, + /obj/effect/pod_landingzone, + /obj/effect/client_image_holder, + )) + + var/turf/oldTurf //Keeps track of where the user was at if they use the "teleport to centcom" button, so they can go back + var/client/holder //client of whoever is using this datum + var/area/centcom/supplypod/loading/bay //What bay we're using to launch shit from. + var/bayNumber //Quick reference to what bay we're in. Usually set to the loading_id variable for the related area type + var/customDropoff = FALSE + var/picking_dropoff_turf = FALSE + var/launchClone = FALSE //If true, then we don't actually launch the thing in the bay. Instead we call duplicate_object() and send the result + var/launchRandomItem = FALSE //If true, lauches a single random item instead of everything on a turf. + var/launchChoice = LAUNCH_RANDOM //Determines if we launch all at once (0) , in order (1), or at random(2) + var/explosionChoice = 0 //Determines if there is no explosion (0), custom explosion (1), or just do a maxcap (2) + var/damageChoice = 0 //Determines if we do no damage (0), custom amnt of damage (1), or gib + 5000dmg (2) + var/launcherActivated = FALSE //check if we've entered "launch mode" (when we click a pod is launched). Used for updating mouse cursor + var/effectBurst = FALSE //Effect that launches 5 at once in a 3x3 area centered on the target + var/effectAnnounce = TRUE + var/numTurfs = 0 //Counts the number of turfs with things we can launch in the chosen bay (in the centcom map) + var/launchCounter = 1 //Used with the "Ordered" launch mode (launchChoice = 1) to see what item is launched + var/atom/specificTarget //Do we want to target a specific mob instead of where we click? Also used for smiting + var/list/orderedArea = list() //Contains an ordered list of turfs in an area (filled in the createOrderedArea() proc), read top-left to bottom-right. Used for the "ordered" launch mode (launchChoice = 1) + var/list/turf/acceptableTurfs = list() //Contians a list of turfs (in the "bay" area on centcom) that have items that can be launched. Taken from orderedArea + var/list/launchList = list() //Contains whatever is going to be put in the supplypod and fired. Taken from acceptableTurfs + + /// An effect used for showing where a reverse pod will land + var/obj/effect/client_image_holder/dropoff_location/indicator + /// An effect used for keeping track of what item is going to be launched next when in "ordered" mode (launchChoice = 1) + var/obj/effect/client_image_holder/supplypod_selector/selector + + var/obj/structure/closet/supplypod/centcompod/temp_pod //The temporary pod that is modified by this datum, then cloned. The buildObject() clone of this pod is what is launched + // Stuff needed to render the map + var/map_name + var/atom/movable/screen/map_view/cam_screen + var/atom/movable/screen/background/cam_background + var/tabIndex = 1 + var/renderLighting = FALSE + var/static/list/pod_style_info + var/static/list/pod_style_lookup + +/datum/centcom_podlauncher/New(user) //user can either be a client or a mob + if (user) //Prevents runtimes on datums being made without clients + setup(user) + if (!isnull(pod_style_info)) + return + pod_style_info = list() + pod_style_lookup = list() + for (var/datum/pod_style/style as anything in typesof(/datum/pod_style)) + pod_style_info += list(list("id" = style::id, "title" = style::ui_name)) + pod_style_lookup[style::id] = style + +/datum/centcom_podlauncher/proc/setup(user) //H can either be a client or a mob + if (istype(user,/client)) + var/client/user_client = user + holder = user_client //if its a client, assign it to holder + else + var/mob/user_mob = user + holder = user_mob.client //if its a mob, assign the mob's client to holder + bay = locate(/area/centcom/supplypod/loading/one) in GLOB.areas //Locate the default bay (one) from the centcom map + bayNumber = bay.loading_id //Used as quick reference to what bay we're taking items from + var/area/pod_storage_area = locate(/area/centcom/supplypod/pod_storage) in GLOB.areas + temp_pod = new(pick(get_area_turfs(pod_storage_area))) //Create a new temp_pod in the podStorage area on centcom (so users are free to look at it and change other variables if needed) + orderedArea = createOrderedArea(bay) //Order all the turfs in the selected bay (top left to bottom right) to a single list. Used for the "ordered" mode (launchChoice = 1) + selector = new(null, holder.mob) + indicator = new(null, holder.mob) + setDropoff(bay) + initMap() + refreshBay() + ui_interact(holder.mob) + +/datum/centcom_podlauncher/proc/initMap() + if(map_name) + holder.clear_map(map_name) + + map_name = "admin_supplypod_bay_[REF(src)]_map" + // Initialize map objects + cam_screen = new + cam_screen.generate_view(map_name) + + var/datum/plane_master_group/planes = cam_screen.display_to(holder.mob) + + if(!renderLighting) + for(var/atom/movable/screen/plane_master/instance as anything in holder.mob.hud_used.get_true_plane_masters(LIGHTING_PLANE, planes.key)) + instance.set_alpha(100) + + cam_background = new + cam_background.assigned_map = map_name + cam_background.del_on_map_removal = TRUE + refreshView() + holder.register_map_obj(cam_background) + +/datum/centcom_podlauncher/ui_state(mob/user) + if (SSticker.current_state >= GAME_STATE_FINISHED) + return GLOB.always_state //Allow the UI to be given to players by admins after roundend + return GLOB.admin_state + +/datum/centcom_podlauncher/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/supplypods), + ) + +/datum/centcom_podlauncher/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + // Open UI + ui = new(user, src, "CentcomPodLauncher") + ui.open() + refreshView() + +/datum/centcom_podlauncher/ui_static_data(mob/user) + var/list/data = list() + data["mapRef"] = map_name + data["defaultSoundVolume"] = initial(temp_pod.soundVolume) //default volume for pods + data["podStyles"] = pod_style_info + return data + +/datum/centcom_podlauncher/ui_data(mob/user) //Sends info about the pod to the UI. + var/list/data = list() //*****NOTE*****: Many of these comments are similarly described in supplypod.dm. If you change them here, please consider doing so in the supplypod code as well! + bayNumber = bay?.loading_id //Used as quick reference to what bay we're taking items from + data["bayNumber"] = bayNumber //Holds the bay as a number. Useful for comparisons in centcom_podlauncher.ract + data["oldArea"] = (oldTurf ? get_area(oldTurf) : null) //Holds the name of the area that the user was in before using the teleportCentcom action + data["picking_dropoff_turf"] = picking_dropoff_turf //If we're picking or have picked a dropoff turf. Only works when pod is in reverse mode + data["customDropoff"] = customDropoff + data["renderLighting"] = renderLighting + data["launchClone"] = launchClone //Do we launch the actual items in the bay or just launch clones of them? + data["launchRandomItem"] = launchRandomItem //Do we launch a single random item instead of everything on the turf? + data["launchChoice"] = launchChoice //Launch turfs all at once (0), ordered (1), or randomly(1) + data["explosionChoice"] = explosionChoice //An explosion that occurs when landing. Can be no explosion (0), custom explosion (1), or maxcap (2) + data["damageChoice"] = damageChoice //Damage that occurs to any mob under the pod when it lands. Can be no damage (0), custom damage (1), or gib+5000dmg (2) + data["delays"] = temp_pod.delays + data["rev_delays"] = temp_pod.reverse_delays + data["custom_rev_delay"] = temp_pod.custom_rev_delay + data["styleChoice"] = temp_pod.style::id //Style is a variable that keeps track of what the pod is supposed to look like. + data["effectShrapnel"] = temp_pod.effectShrapnel //If true, creates a cloud of shrapnel of a decided type and magnitude on landing + data["shrapnelType"] = "[temp_pod.shrapnel_type]" //Path2String + data["shrapnelMagnitude"] = temp_pod.shrapnel_magnitude + data["effectStun"] = temp_pod.effectStun //If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish! + data["effectLimb"] = temp_pod.effectLimb //If true, pops off a limb (if applicable) from anyone caught under the pod when it lands + data["effectOrgans"] = temp_pod.effectOrgans //If true, yeets the organs out of any bodies caught under the pod when it lands + data["effectBluespace"] = temp_pod.bluespace //If true, the pod deletes (in a shower of sparks) after landing + data["effectStealth"] = temp_pod.effectStealth //If true, a target icon isn't displayed on the turf where the pod will land + data["effectQuiet"] = temp_pod.effectQuiet //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc) + data["effectMissile"] = temp_pod.effectMissile //If true, the pod deletes the second it lands. If you give it an explosion, it will act like a missile exploding as it hits the ground + data["effectCircle"] = temp_pod.effectCircle //If true, allows the pod to come in at any angle. Bit of a weird feature but whatever its here + data["effectBurst"] = effectBurst //IOf true, launches five pods at once (with a very small delay between for added coolness), in a 3x3 area centered around the area + data["effectReverse"] = temp_pod.reversing //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom + data["reverse_option_list"] = temp_pod.reverse_option_list + data["effectTarget"] = specificTarget //Launches the pod at the turf of a specific mob target, rather than wherever the user clicked. Useful for smites + data["effectName"] = temp_pod.adminNamed //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc) + data["podName"] = temp_pod.name + data["podDesc"] = temp_pod.desc + data["effectAnnounce"] = effectAnnounce + data["giveLauncher"] = launcherActivated //If true, the user is in launch mode, and whenever they click a pod will be launched (either at their mouse position or at a specific target) + data["numObjects"] = numTurfs //Counts the number of turfs that contain a launchable object in the centcom supplypod bay + data["fallingSound"] = temp_pod.fallingSound != initial(temp_pod.fallingSound)//Admin sound to play as the pod falls + data["landingSound"] = temp_pod.landingSound //Admin sound to play when the pod lands + data["openingSound"] = temp_pod.openingSound //Admin sound to play when the pod opens + data["leavingSound"] = temp_pod.leavingSound //Admin sound to play when the pod leaves + data["soundVolume"] = temp_pod.soundVolume //Admin sound to play when the pod leaves + return data + +/datum/centcom_podlauncher/ui_act(action, params) + . = ..() + if(.) + return + switch(action) + ////////////////////////////UTILITIES////////////////// + if("gamePanel") + holder.holder.Game() + SSblackbox.record_feedback("tally", "admin_verb", 1, "Game Panel") //If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + . = TRUE + if("buildMode") + var/mob/holder_mob = holder.mob + if (holder_mob && (check_rights(R_BUILDMODE, user = holder_mob))) + togglebuildmode(holder_mob) + SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Build Mode") //If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + . = TRUE + if("loadDataFromPreset") + var/list/savedData = params["payload"] + loadData(savedData) + . = TRUE + if("switchBay") + bayNumber = params["bayNumber"] + refreshBay() + . = TRUE + if("pickDropoffTurf") //Enters a mode that lets you pick the dropoff location for reverse pods + if (picking_dropoff_turf) + picking_dropoff_turf = FALSE + updateCursor() //Update the cursor of the user to a cool looking target icon + return + if (launcherActivated) + launcherActivated = FALSE //We don't want to have launch mode enabled while we're picking a turf + picking_dropoff_turf = TRUE + updateCursor() //Update the cursor of the user to a cool looking target icon + . = TRUE + if("clearDropoffTurf") + setDropoff(bay) + customDropoff = FALSE + picking_dropoff_turf = FALSE + updateCursor() + . = TRUE + if("teleportDropoff") //Teleports the user to the dropoff point. + var/mob/M = holder.mob //We teleport whatever mob the client is attached to at the point of clicking + var/turf/current_location = get_turf(M) + var/list/coordinate_list = temp_pod.reverse_dropoff_coords + var/turf/dropoff_turf = locate(coordinate_list[1], coordinate_list[2], coordinate_list[3]) + if (current_location != dropoff_turf) + oldTurf = current_location + M.forceMove(dropoff_turf) //Perform the actual teleport + log_admin("[key_name(usr)] jumped to [AREACOORD(dropoff_turf)]") + message_admins("[key_name_admin(usr)] jumped to [AREACOORD(dropoff_turf)]") + . = TRUE + if("teleportCentcom") //Teleports the user to the centcom supply loading facility. + var/mob/holder_mob = holder.mob //We teleport whatever mob the client is attached to at the point of clicking + var/turf/current_location = get_turf(holder_mob) + var/area/bay_area = bay + if (current_location.loc != bay_area) + oldTurf = current_location + var/turf/teleport_turf = pick(get_area_turfs(bay_area)) + holder_mob.forceMove(teleport_turf) //Perform the actual teleport + if (holder.holder) + log_admin("[key_name(usr)] jumped to [AREACOORD(teleport_turf)]") + message_admins("[key_name_admin(usr)] jumped to [AREACOORD(teleport_turf)]") + . = TRUE + if("teleportBack") //After teleporting to centcom/dropoff, this button allows the user to teleport to the last spot they were at. + var/mob/M = holder.mob + if (!oldTurf) //If theres no turf to go back to, error and cancel + to_chat(M, "Nowhere to jump to!") + return + M.forceMove(oldTurf) //Perform the actual teleport + if (holder.holder) + log_admin("[key_name(usr)] jumped to [AREACOORD(oldTurf)]") + message_admins("[key_name_admin(usr)] jumped to [AREACOORD(oldTurf)]") + . = TRUE + + ////////////////////////////LAUNCH STYLE CHANGES////////////////// + if("launchClone") //Toggles the launchClone var. See variable declarations above for what this specifically means + launchClone = !launchClone + . = TRUE + if("launchRandomItem") //Pick random turfs from the supplypod bay at centcom to launch + launchRandomItem = TRUE + . = TRUE + if("launchWholeTurf") //Pick random turfs from the supplypod bay at centcom to launch + launchRandomItem = FALSE + . = TRUE + if("launchAll") //Launch turfs (from the orderedArea list) all at once, from the supplypod bay at centcom + launchChoice = LAUNCH_ALL + updateSelector() + . = TRUE + if("launchOrdered") //Launch turfs (from the orderedArea list) one at a time in order, from the supplypod bay at centcom + launchChoice = LAUNCH_ORDERED + updateSelector() + . = TRUE + if("launchRandomTurf") //Pick random turfs from the supplypod bay at centcom to launch + launchChoice = LAUNCH_RANDOM + updateSelector() + . = TRUE + + ////////////////////////////POD EFFECTS////////////////// + if("explosionCustom") //Creates an explosion when the pod lands + if (explosionChoice == 1) //If already a custom explosion, set to default (no explosion) + explosionChoice = 0 + temp_pod.explosionSize = list(0,0,0,0) + return + var/list/expNames = list("тотального разрушения", "тяжелого удара", "легкого удара", "пламени") //Explosions have a range of different types of damage + var/list/boomInput = list() + for (var/i=1 to length(expNames)) //Gather input from the user for the value of each type of damage + boomInput.Add(tgui_input_number(usr, "Введите дальность [expNames[i]]. ВНИМАНИЕ: это игнорирует ограниечение радиуса бомб!", "Дальность [expNames[i]]", 0)) + if (isnull(boomInput[i])) + return + if (!isnum(boomInput[i])) //If the user doesn't input a number, set that specific explosion value to zero + tgui_alert(usr, "Это было не число! Вместо него установлено значение по умолчанию (ноль).") + boomInput = 0 + explosionChoice = 1 + temp_pod.explosionSize = boomInput + . = TRUE + if("explosionBus") //Creates a maxcap when the pod lands + if (explosionChoice == 2) //If already a maccap, set to default (no explosion) + explosionChoice = 0 + temp_pod.explosionSize = list(0,0,0,0) + return + explosionChoice = 2 + temp_pod.explosionSize = list(GLOB.max_ex_devastation_range, GLOB.max_ex_heavy_range, GLOB.max_ex_light_range, GLOB.max_ex_flame_range) //Set explosion to max cap of server + . = TRUE + if("damageCustom") //Deals damage to whoevers under the pod when it lands + if (damageChoice == 1) //If already doing custom damage, set back to default (no damage) + damageChoice = 0 + temp_pod.damage = 0 + return + var/damageInput = tgui_input_number(usr, "Введите сумму урона травмами, который нанесется при ударе.", "Сколько урона нанести?", 0) + if (isnull(damageInput)) + return + if (!isnum(damageInput)) //Sanitize the input for damage to deal.s + tgui_alert(usr, "Это было не число! Вместо него установлено значение по умолчанию (ноль).") + damageInput = 0 + damageChoice = 1 + temp_pod.damage = damageInput + . = TRUE + if("damageGib") //Gibs whoever is under the pod when it lands. Also deals 5000 damage, just to be sure. + if (damageChoice == 2) //If already gibbing, set back to default (no damage) + damageChoice = 0 + temp_pod.damage = 0 + temp_pod.effectGib = FALSE + return + damageChoice = 2 + temp_pod.damage = 5000 + temp_pod.effectGib = TRUE //Gibs whoever is under the pod when it lands + . = TRUE + if("effectName") //Give the supplypod a custom name. Supplypods automatically get their name based on their style (see supplypod/setStyle() proc), so doing this overrides that. + if (temp_pod.adminNamed) //If we're already adminNamed, set the name of the pod back to default + temp_pod.adminNamed = FALSE + temp_pod.setStyle(temp_pod.style) //This resets the name of the pod based on its current style (see supplypod/setStyle() proc) + return + var/nameInput= tgui_input_text(usr, "Введите новое имя капсулы", "Новое имя", temp_pod.style::name, MAX_NAME_LEN) //Gather input for name and desc + if (isnull(nameInput)) + return + var/descInput = tgui_input_text(usr, "Введите новое описание капсулы", "Новое описание", temp_pod.style::desc) + if (isnull(descInput)) + return + temp_pod.name = nameInput + temp_pod.desc = descInput + temp_pod.adminNamed = TRUE //This variable is checked in the supplypod/setStyle() proc + . = TRUE + if("effectShrapnel") //Creates a cloud of shrapnel on landing + if (temp_pod.effectShrapnel == TRUE) //If already doing custom damage, set back to default (no shrapnel) + temp_pod.effectShrapnel = FALSE + return + var/shrapnelInput = tgui_input_list(usr, "Пожалуйста, введите тип облака снарядов, которое вы хотите создать при приземлении (может быть любой снаряд!)", "Тип снаряда", sort_list(subtypesof(/obj/item/projectile), GLOBAL_PROC_REF(cmp_typepaths_asc)), null) + if (isnull(shrapnelInput)) + return + var/shrapnelMagnitude = tgui_input_number(usr, "Введите размер облака снарядов. Обычно это значение от 1 до 5. Обратите внимание: Если вы выберите слишком большой размер, вы можете вызвать сбой сервера.", "Размер облака", 0) + if (isnull(shrapnelMagnitude)) + return + if (!isnum(shrapnelMagnitude)) + tgui_alert(usr, "Это было не число! Вместо него установлено значение 3.") + shrapnelMagnitude = 3 + temp_pod.shrapnel_type = shrapnelInput + temp_pod.shrapnel_magnitude = shrapnelMagnitude + temp_pod.effectShrapnel = TRUE + . = TRUE + if("effectStun") //Toggle: Any mob under the pod is stunned (cant move) until the pod lands, hitting them! + temp_pod.effectStun = !temp_pod.effectStun + . = TRUE + if("effectLimb") //Toggle: Anyone carbon mob under the pod loses a limb when it lands + temp_pod.effectLimb = !temp_pod.effectLimb + . = TRUE + if("effectOrgans") //Toggle: Anyone carbon mob under the pod loses a limb when it lands + temp_pod.effectOrgans = !temp_pod.effectOrgans + . = TRUE + if("effectBluespace") //Toggle: Deletes the pod after landing + temp_pod.bluespace = !temp_pod.bluespace + . = TRUE + if("effectStealth") //Toggle: There is no red target indicator showing where the pod will land + temp_pod.effectStealth = !temp_pod.effectStealth + . = TRUE + if("effectQuiet") //Toggle: The pod makes no noise (explosions, opening sounds, etc) + temp_pod.effectQuiet = !temp_pod.effectQuiet + . = TRUE + if("effectMissile") //Toggle: The pod deletes the instant it lands. Looks nicer than just setting the open delay and leave delay to zero. Useful for combo-ing with explosions + temp_pod.effectMissile = !temp_pod.effectMissile + . = TRUE + if("effectCircle") //Toggle: The pod can come in from any descent angle. Goof requested this im not sure why but it looks p funny actually + temp_pod.effectCircle = !temp_pod.effectCircle + . = TRUE + if("effectBurst") //Toggle: Launch 5 pods (with a very slight delay between) in a 3x3 area centered around the target + effectBurst = !effectBurst + . = TRUE + if("effectAnnounce") //Toggle: Launch 5 pods (with a very slight delay between) in a 3x3 area centered around the target + effectAnnounce = !effectAnnounce + . = TRUE + if("effectReverse") //Toggle: Don't send any items. Instead, after landing, close (taking any objects inside) and go back to the centcom bay it came from + temp_pod.reversing = !temp_pod.reversing + if (temp_pod.reversing) + indicator.alpha = 150 + else + indicator.alpha = 0 + . = TRUE + if("reverseOption") + var/reverseOption = params["reverseOption"] + temp_pod.reverse_option_list[reverseOption] = !temp_pod.reverse_option_list[reverseOption] + . = TRUE + if("effectTarget") //Toggle: Launch at a specific mob (instead of at whatever turf you click on). Used for the supplypod smite + if (specificTarget) + specificTarget = null + return + + var/list/possible_destinations = GLOB.mob_living_list + var/mob/target = tgui_input_list(usr, "Выберите моба!", "Цель", possible_destinations) + + if (isnull(target) || QDELETED(target)) + return + + + specificTarget = target + + . = TRUE + ////////////////////////////TIMER DELAYS////////////////// + if("editTiming") //Change the different timers relating to the pod + var/delay = params["timer"] + var/value = params["value"] + var/reverse = params["reverse"] + if (reverse) + temp_pod.reverse_delays[delay] = value * 10 + else + temp_pod.delays[delay] = value * 10 + . = TRUE + if("resetTiming") + temp_pod.delays = list(POD_TRANSIT = 20, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30) + temp_pod.reverse_delays = list(POD_TRANSIT = 20, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30) + . = TRUE + if("toggleRevDelays") + temp_pod.custom_rev_delay = !temp_pod.custom_rev_delay + . = TRUE + ////////////////////////////ADMIN SOUNDS////////////////// + if("fallingSound") //Admin sound from a local file that plays when the pod lands + if ((temp_pod.fallingSound) != initial(temp_pod.fallingSound)) + temp_pod.fallingSound = initial(temp_pod.fallingSound) + temp_pod.fallingSoundLength = initial(temp_pod.fallingSoundLength) + return + var/soundInput = input(holder, "Пожалуйста, выберите звуковой файл, который будет воспроизводиться, когда капсула будет приземляться! Звук начнет воспроизводиться и попытается прекратится, когда капсула приземлится.", "Выберите звуковой файл") as null|sound + if (isnull(soundInput)) + return + var/sound/tempSound = sound(soundInput) + playsound(holder.mob, tempSound, 1) + var/list/sounds_list = holder.SoundQuery() + var/soundLen = 0 + for (var/playing_sound in sounds_list) + if (isnull(playing_sound)) + stack_trace("client.SoundQuery() Returned a list containing a null sound! Somehow!") + continue + var/sound/found = playing_sound + if (found.file == tempSound.file) + soundLen = length(found) + if (!soundLen) + soundLen = tgui_input_number(holder, "Не удалось автоматически определить длительность звукового файла. Какова его точная длительность в секундах? Это число будет использоваться для выравнивания звука так, чтобы он заканчивался сразу после приземления капсулы!", "Введите длительность файла", 0.3) + if (isnull(soundLen)) + return + if (!isnum(soundLen)) + tgui_alert(usr, "Это было не число! Вместо него установлено значение по умолчанию ([initial(temp_pod.fallingSoundLength) * 0.1]).") + temp_pod.fallingSound = soundInput + temp_pod.fallingSoundLength = 10 * soundLen + . = TRUE + if("landingSound") //Admin sound from a local file that plays when the pod lands + if (!isnull(temp_pod.landingSound)) + temp_pod.landingSound = null + return + var/soundInput = input(holder, "Пожалуйста, выберите звуковой файл, который будет воспроизводиться, когда капсула приземлится! Рекомендуется «ох, черт, прости!» в случае, если вы кого-нибудь ударите капсулой.", "Выберите звуковой файл") as null|sound + if (isnull(soundInput)) + return + temp_pod.landingSound = soundInput + . = TRUE + if("openingSound") //Admin sound from a local file that plays when the pod opens + if (!isnull(temp_pod.openingSound)) + temp_pod.openingSound = null + return + var/soundInput = input(holder, "Пожалуйста, выберите звуковой файл, который будет воспроизводиться при открытии капсулы! Рекомендуется стандартный звуковой эффект детей, радующихся вечеринке, в случае, если в вашей капсуле полно веселых и интересных вещей!", "Выберите звуковой файл") as null|sound + if (isnull(soundInput)) + return + temp_pod.openingSound = soundInput + . = TRUE + if("leavingSound") //Admin sound from a local file that plays when the pod leaves + if (!isnull(temp_pod.leavingSound)) + temp_pod.leavingSound = null + return + var/soundInput = input(holder, "Пожалуйста, выберите звуковой файл, который будет воспроизводиться, когда капсула исчезнет! Рекомендуется хороший звук свистка, особенно если вы используете эффект возвращаемой капсулы.", "Выберите звуковой файл") as null|sound + if (isnull(soundInput)) + return + temp_pod.leavingSound = soundInput + . = TRUE + if("soundVolume") //Admin sound from a local file that plays when the pod leaves + if (temp_pod.soundVolume != initial(temp_pod.soundVolume)) + temp_pod.soundVolume = initial(temp_pod.soundVolume) + return + var/soundInput = tgui_input_number(holder, "Пожалуйста, выберите громкость. По умолчанию — от 1 до 100, где 50 — среднее значение, но выбирайте любое. Если вы по-прежнему не слышите звук, попробуйте включить эффект «Тихо». При этом будут отключены все звуки капсулы, за исключением пользовательских, заданных администратором тремя предыдущими кнопками.", "Выберите громкость админских звуков") + if (isnull(soundInput)) + return + temp_pod.soundVolume = soundInput + . = TRUE + ////////////////////////////STYLE CHANGES////////////////// + //as a way to get the proper icon state, name, and description of the pod. + if("tabSwitch") + tabIndex = params["tabIndex"] + refreshView() + . = TRUE + if("refreshView") + refreshView() + . = TRUE + if("renderLighting") + renderLighting = !renderLighting + . = TRUE + if("setStyle") + var/chosenStyle = params["style"] + temp_pod.setStyle(pod_style_lookup[chosenStyle]) + . = TRUE + if("refresh") //Refresh the Pod bay. User should press this if they spawn something new in the centcom bay. Automatically called whenever the user launches a pod + refreshBay() + . = TRUE + if("giveLauncher") //Enters the "Launch Mode". When the launcher is activated, temp_pod is cloned, and the result it filled and launched anywhere the user clicks (unless specificTarget is true) + launcherActivated = !launcherActivated + if (picking_dropoff_turf) + picking_dropoff_turf = FALSE //We don't want to have launch mode enabled while we're picking a turf + updateCursor() //Update the cursor of the user to a cool looking target icon + updateSelector() + . = TRUE + if("clearBay") //Delete all mobs and objs in the selected bay + if(tgui_alert(usr, "Это приведет к удалению всех объектов и мобов в [bay]. Вы уверены?", "Подтверждение", list("Удали это дерьмо", "Нет")) == "Удали это дерьмо") + clearBay() + refreshBay() + . = TRUE + +/datum/centcom_podlauncher/ui_close(mob/user) //Uses the destroy() proc. When the user closes the UI, we clean up the temp_pod and supplypod_selector variables. + QDEL_NULL(temp_pod) + QDEL_NULL(cam_screen) + QDEL_NULL(cam_background) + qdel(src) + +/datum/centcom_podlauncher/proc/setupViewPod() + setupView(RANGE_TURFS(1, temp_pod)) + +/datum/centcom_podlauncher/proc/setupViewBay() + var/list/visible_turfs = list() + for(var/turf/bay_turf in bay) + visible_turfs += bay_turf + setupView(visible_turfs) + +/datum/centcom_podlauncher/proc/setupViewDropoff() + var/list/coords_list = temp_pod.reverse_dropoff_coords + var/turf/drop = locate(coords_list[1], coords_list[2], coords_list[3]) + setupView(RANGE_TURFS(3, drop)) + +/datum/centcom_podlauncher/proc/setupView(list/visible_turfs) + var/list/bbox = get_bbox_of_atoms(visible_turfs) + var/size_x = bbox[3] - bbox[1] + 1 + var/size_y = bbox[4] - bbox[2] + 1 + + cam_screen.vis_contents = visible_turfs + cam_background.icon_state = "clear" + cam_background.fill_rect(1, 1, size_x, size_y) + +/datum/centcom_podlauncher/proc/updateCursor(forceClear = FALSE) //Update the mouse of the user + if (!holder) //Can't update the mouse icon if the client doesnt exist! + return + if (!forceClear && (launcherActivated || picking_dropoff_turf)) //If the launching param is true, we give the user new mouse icons. + if(launcherActivated) + holder.mouse_up_icon = 'icons/effects/mouse_pointers/supplypod_target.dmi' //Icon for when mouse is released + holder.mouse_down_icon = 'icons/effects/mouse_pointers/supplypod_down_target.dmi' //Icon for when mouse is pressed + else if(picking_dropoff_turf) + holder.mouse_up_icon = 'icons/effects/mouse_pointers/supplypod_pickturf.dmi' //Icon for when mouse is released + holder.mouse_down_icon = 'icons/effects/mouse_pointers/supplypod_pickturf_down.dmi' //Icon for when mouse is pressed + holder.mouse_override_icon = holder.mouse_up_icon //Icon for idle mouse (same as icon for when released) + holder.mouse_pointer_icon = holder.mouse_override_icon + holder.click_intercept = src //Create a click_intercept so we know where the user is clicking + else + var/mob/holder_mob = holder.mob + holder.mouse_up_icon = null + holder.mouse_down_icon = null + holder.mouse_override_icon = null + holder.click_intercept = null + holder_mob?.update_mouse_pointer() //set the moues icons to null, then call update_moues_pointer() which resets them to the correct values based on what the mob is doing (in a mech, holding a spell, etc)() + +/datum/centcom_podlauncher/proc/InterceptClickOn(user,params,atom/target) //Click Intercept so we know where to send pods where the user clicks + var/list/modifiers = params2list(params) + + var/left_click = LAZYACCESS(modifiers, LEFT_CLICK) + + if (launcherActivated) + //Clicking on UI elements shouldn't launch a pod + if(istype(target,/atom/movable/screen)) + return FALSE + + . = TRUE + + if(left_click) //When we left click: + preLaunch() //Fill the acceptableTurfs list from the orderedArea list. Then, fill up the launchList list with items from the acceptableTurfs list based on the manner of launch (ordered, random, etc) + if (!isnull(specificTarget)) + target = get_turf(specificTarget) //if we have a specific target, then always launch the pod at the turf of the target + else if (target) + target = get_turf(target) //Make sure we're aiming at a turf rather than an item or effect or something + else + return //if target is null and we don't have a specific target, cancel + if (effectAnnounce) + var/old_layer = temp_pod.layer + var/old_plane = temp_pod.plane + var/pod_name = (!temp_pod.adminNamed)? temp_pod.declent_ru(NOMINATIVE) : temp_pod.name + notify_ghosts( + title = "Запущена [pod_name]", + message = "На станцию запущена специальная посылка.", + source = target, + alert_overlay = temp_pod) + temp_pod.layer = old_layer + temp_pod.plane = old_plane + var/list/bouttaDie = list() + for (var/mob/living/target_mob in target) + bouttaDie.Add(target_mob) + if (holder.holder) + supplypod_punish_log(bouttaDie) + if (!effectBurst) //If we're not using burst mode, just launch normally. + launch(target) + else + for (var/i in 1 to 5) //If we're using burst mode, launch 5 pods + if (isnull(target)) + break //if our target gets deleted during this, we stop the show + preLaunch() //Same as above + var/landingzone = locate(target.x + rand(-1,1), target.y + rand(-1,1), target.z) //Pods are randomly adjacent to (or the same as) the target + if (landingzone) //just incase we're on the edge of the map or something that would cause target.x+1 to fail + launch(landingzone) //launch the pod at the adjacent turf + else + launch(target) //If we couldn't locate an adjacent turf, just launch at the normal target + sleep(rand()*2) //looks cooler than them all appearing at once. Gives the impression of burst fire. + else if (picking_dropoff_turf) + //Clicking on UI elements shouldn't pick a dropoff turf + if(istype(target,/atom/movable/screen)) + return FALSE + + . = TRUE + if(left_click) //When we left click: + var/turf/target_turf = get_turf(target) + setDropoff(target_turf) + customDropoff = TRUE + to_chat(user, span_notice("Вы выбрали [target_turf] в [COORD(target_turf)] в качестве места сброса")) + +/datum/centcom_podlauncher/proc/refreshView() + switch(tabIndex) + if (TAB_POD) + setupViewPod() + if (TAB_BAY) + setupViewBay() + else + setupViewDropoff() + +/datum/centcom_podlauncher/proc/refreshBay() //Called whenever the bay is switched, as well as wheneber a pod is launched + bay = GLOB.supplypod_loading_bays[bayNumber] + orderedArea = createOrderedArea(bay) //Create an ordered list full of turfs form the bay + preLaunch() //Fill acceptable turfs from orderedArea, then fill launchList from acceptableTurfs (see proc for more info) + refreshView() + +/datum/centcom_podlauncher/proc/createOrderedArea(area/area_to_order) //This assumes the area passed in is a continuous square + if (isnull(area_to_order)) //If theres no supplypod bay mapped into centcom, throw an error + to_chat(holder.mob, "В мире нет /area/centcom/supplypod/loading/one (или /two, /three или /four)! На данный момент вы можете сделать их самостоятельно (а затем обновить список), но попросите маппера исправить это сегодня!") + CRASH("No /area/centcom/supplypod/loading/one (or /two or /three or /four) has been mapped into the centcom z-level!") + orderedArea = list() + if (length(area_to_order.contents)) //Go through the area passed into the proc, and figure out the top left and bottom right corners by calculating max and min values + var/startX = area_to_order.contents[1].x //Create the four values (we do it off a.contents[1] so they have some sort of arbitrary initial value. They should be overwritten in a few moments) + var/endX = area_to_order.contents[1].x + var/startY = area_to_order.contents[1].y + var/endY = area_to_order.contents[1].y + for (var/turf/turf_in_area in area_to_order) //For each turf in the area, go through and find: + if (turf_in_area.x < startX) //The turf with the smallest x value. This is our startX + startX = turf_in_area.x + else if (turf_in_area.x > endX) //The turf with the largest x value. This is our endX + endX = turf_in_area.x + else if (turf_in_area.y > startY) //The turf with the largest Y value. This is our startY + startY = turf_in_area.y + else if (turf_in_area.y < endY) //The turf with the smallest Y value. This is our endY + endY = turf_in_area.y + for (var/vertical in endY to startY) + for (var/horizontal in startX to endX) + orderedArea.Add(locate(horizontal, startY - (vertical - endY), 1)) //After gathering the start/end x and y, go through locating each turf from top left to bottom right, like one would read a book + return orderedArea //Return the filled list + +/datum/centcom_podlauncher/proc/preLaunch() //Creates a list of acceptable items, + numTurfs = 0 //Counts the number of turfs that can be launched (remember, supplypods either launch all at once or one turf-worth of items at a time) + acceptableTurfs = list() + for (var/t in orderedArea) //Go through the orderedArea list + var/turf/unchecked_turf = t + if (iswallturf(unchecked_turf) || length(typecache_filter_list_reverse(unchecked_turf.contents, ignored_atoms))) //if there is something in this turf that isn't in the blacklist, we consider this turf "acceptable" and add it to the acceptableTurfs list + acceptableTurfs.Add(unchecked_turf) //Because orderedArea was an ordered linear list, acceptableTurfs will be as well. + numTurfs ++ + + launchList = list() //Anything in launchList will go into the supplypod when it is launched + if (length(acceptableTurfs) && !temp_pod.reversing && !temp_pod.effectMissile) //We dont fill the supplypod if acceptableTurfs is empty, if the pod is going in reverse (effectReverse=true), or if the pod is acitng like a missile (effectMissile=true) + switch(launchChoice) + if(LAUNCH_ALL) //If we are launching all the turfs at once + for (var/t in acceptableTurfs) + var/turf/accepted_turf = t + launchList |= typecache_filter_list_reverse(accepted_turf.contents, ignored_atoms) //We filter any blacklisted atoms and add the rest to the launchList + if(LAUNCH_ORDERED) //If we are launching one at a time + if (launchCounter > length(acceptableTurfs)) //Check if the launchCounter, which acts as an index, is too high. If it is, reset it to 1 + launchCounter = 1 //Note that the launchCounter index is incremented in the launch() proc + var/turf/next_turf_in_line = acceptableTurfs[launchCounter] + launchList |= typecache_filter_list_reverse(next_turf_in_line.contents, ignored_atoms) //Filter the specicic turf chosen from acceptableTurfs, and add it to the launchList + if(LAUNCH_RANDOM) //If we are launching randomly + var/turf/acceptable_turf = pick_n_take(acceptableTurfs) + launchList |= typecache_filter_list_reverse(acceptable_turf.contents, ignored_atoms) //filter a random turf from the acceptableTurfs list and add it to the launchList + updateSelector() //Call updateSelector(), which, if we are launching one at a time (launchChoice == 2), will move to the next turf that will be launched + //UpdateSelector() is here (instead if the if(1) switch block) because it also moves the selector to nullspace (to hide it) if needed + +/datum/centcom_podlauncher/proc/launch(turf/target_turf) //Game time started + if (isnull(target_turf)) + return + var/obj/structure/closet/supplypod/centcompod/toLaunch = DuplicateObject(temp_pod, TRUE, TRUE) //Duplicate the temp_pod (which we have been varediting or configuring with the UI) and store the result + toLaunch.update_appearance()//we update_appearance() here so that the door doesnt "flicker on" right after it lands + var/shippingLane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] + toLaunch.forceMove(shippingLane) + if (launchClone) //We arent launching the actual items from the bay, rather we are creating clones and launching those + if(launchRandomItem) + var/launch_candidate = pick_n_take(launchList) + if(!isnull(launch_candidate)) + var/atom/movable/movable_to_launch = DuplicateObject(launch_candidate, TRUE, TRUE) + movable_to_launch.forceMove(toLaunch) //Duplicate a single atom/movable from launchList and forceMove it into the supplypod + else + for (var/launch_candidate in launchList) + if (isnull(launch_candidate)) + continue + var/atom/movable/movable_to_launch = DuplicateObject(launch_candidate, TRUE, TRUE) + movable_to_launch.forceMove(toLaunch) //Duplicate each atom/movable in launchList and forceMove them into the supplypod + else + if(launchRandomItem) + var/atom/random_item = pick_n_take(launchList) + if(!isnull(random_item)) + var/atom/movable/random_item_movable = random_item + random_item_movable.forceMove(toLaunch) //and forceMove any atom/moveable into the supplypod + else + for (var/thing_to_launch in launchList) //If we aren't cloning the objects, just go through the launchList + if (isnull(thing_to_launch)) + continue + var/atom/movable/movable_to_launch = thing_to_launch + movable_to_launch.forceMove(toLaunch) //and forceMove any atom/moveable into the supplypod + new /obj/effect/pod_landingzone(target_turf, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to its location + if (launchClone) + launchCounter++ //We only need to increment launchCounter if we are cloning objects. + //If we aren't cloning objects, taking and removing the first item each time from the acceptableTurfs list will inherently iterate through the list in order + +/datum/centcom_podlauncher/proc/updateSelector() //Ensures that the selector effect will showcase the next item if needed + if (launchChoice == LAUNCH_ORDERED && length(acceptableTurfs) > 1 && !temp_pod.reversing && !temp_pod.effectMissile) //We only show the selector if we are taking items from the bay + var/index = (launchCounter == 1 ? launchCounter : launchCounter + 1) //launchCounter acts as an index to the ordered acceptableTurfs list, so adding one will show the next item in the list. We don't want to do this for the very first item tho + if (index > length(acceptableTurfs)) //out of bounds check + index = 1 + selector.forceMove(acceptableTurfs[index]) //forceMove the selector to the next turf in the ordered acceptableTurfs list + else + selector.moveToNullspace() //Otherwise, we move the selector to nullspace until it is needed again + +/datum/centcom_podlauncher/proc/clearBay() //Clear all objs and mobs from the selected bay + for (var/obj/O in bay.get_all_contents()) + qdel(O) + for (var/mob/M in bay.get_all_contents()) + qdel(M) + for (var/bayturf in bay) + var/turf/turf_to_clear = bayturf + turf_to_clear.ChangeTurf(/turf/simulated/floor) + +/datum/centcom_podlauncher/Destroy() //The Destroy() proc. This is called by ui_close proc, or whenever the user leaves the game + updateCursor(TRUE) //Make sure our moues cursor resets to default. False means we are not in launch mode + QDEL_NULL(temp_pod) //Delete the temp_pod + QDEL_NULL(selector) //Delete the selector effect + QDEL_NULL(indicator) + return ..() + +/datum/centcom_podlauncher/proc/supplypod_punish_log(list/whoDyin) + var/podString = effectBurst ? "5 pods" : "a pod" + var/whomString = "" + if (LAZYLEN(whoDyin)) + for (var/mob/living/M in whoDyin) + whomString += "[key_name(M)], " + + var/msg = "launched [podString] towards [whomString]" + message_admins("[key_name_admin(usr)] [msg] in [ADMIN_VERBOSEJMP(specificTarget)].") + if (length(whoDyin)) + for (var/mob/living/M in whoDyin) + log_and_message_admins("[key_name_admin(usr)] [msg]") + +/datum/centcom_podlauncher/proc/loadData(list/dataToLoad) + bayNumber = dataToLoad["bayNumber"] + customDropoff = dataToLoad["customDropoff"] + renderLighting = dataToLoad["renderLighting"] + launchClone = dataToLoad["launchClone"] //Do we launch the actual items in the bay or just launch clones of them? + launchRandomItem = dataToLoad["launchRandomItem"] //Do we launch a single random item instead of everything on the turf? + launchChoice = dataToLoad["launchChoice"] //Launch turfs all at once (0), ordered (1), or randomly(1) + explosionChoice = dataToLoad["explosionChoice"] //An explosion that occurs when landing. Can be no explosion (0), custom explosion (1), or maxcap (2) + damageChoice = dataToLoad["damageChoice"] //Damage that occurs to any mob under the pod when it lands. Can be no damage (0), custom damage (1), or gib+5000dmg (2) + temp_pod.delays = dataToLoad["delays"] + temp_pod.reverse_delays = dataToLoad["rev_delays"] + temp_pod.custom_rev_delay = dataToLoad["custom_rev_delay"] + temp_pod.setStyle(pod_style_lookup[dataToLoad["styleChoice"]]) //Style is a variable that keeps track of what the pod is supposed to look like. + temp_pod.effectShrapnel = dataToLoad["effectShrapnel"] //If true, creates a cloud of shrapnel of a decided type and magnitude on landing + temp_pod.shrapnel_type = text2path(dataToLoad["shrapnelType"]) + temp_pod.shrapnel_magnitude = dataToLoad["shrapnelMagnitude"] + temp_pod.effectStun = dataToLoad["effectStun"]//If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish! + temp_pod.effectLimb = dataToLoad["effectLimb"]//If true, pops off a limb (if applicable) from anyone caught under the pod when it lands + temp_pod.effectOrgans = dataToLoad["effectOrgans"]//If true, yeets the organs out of any bodies caught under the pod when it lands + temp_pod.bluespace = dataToLoad["effectBluespace"] //If true, the pod deletes (in a shower of sparks) after landing + temp_pod.effectStealth = dataToLoad["effectStealth"]//If true, a target icon isn't displayed on the turf where the pod will land + temp_pod.effectQuiet = dataToLoad["effectQuiet"] //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc) + temp_pod.effectMissile = dataToLoad["effectMissile"] //If true, the pod deletes the second it lands. If you give it an explosion, it will act like a missile exploding as it hits the ground + temp_pod.effectCircle = dataToLoad["effectCircle"] //If true, allows the pod to come in at any angle. Bit of a weird feature but whatever its here + effectBurst = dataToLoad["effectBurst"] //IOf true, launches five pods at once (with a very small delay between for added coolness), in a 3x3 area centered around the area + temp_pod.reversing = dataToLoad["effectReverse"] //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom + temp_pod.reverse_option_list = dataToLoad["reverse_option_list"] + specificTarget = dataToLoad["effectTarget"] //Launches the pod at the turf of a specific mob target, rather than wherever the user clicked. Useful for smites + temp_pod.adminNamed = dataToLoad["effectName"] //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc) + temp_pod.name = dataToLoad["podName"] + temp_pod.desc = dataToLoad["podDesc"] + effectAnnounce = dataToLoad["effectAnnounce"] + numTurfs = dataToLoad["numObjects"] //Counts the number of turfs that contain a launchable object in the centcom supplypod bay + temp_pod.fallingSound = dataToLoad["fallingSound"]//Admin sound to play as the pod falls + temp_pod.landingSound = dataToLoad["landingSound"]//Admin sound to play when the pod lands + temp_pod.openingSound = dataToLoad["openingSound"]//Admin sound to play when the pod opens + temp_pod.leavingSound = dataToLoad["leavingSound"]//Admin sound to play when the pod leaves + temp_pod.soundVolume = dataToLoad["soundVolume"] //Admin sound to play when the pod leaves + picking_dropoff_turf = FALSE + launcherActivated = FALSE + updateCursor() + refreshView() + +GLOBAL_DATUM_INIT(podlauncher, /datum/centcom_podlauncher, new) + +//Set the dropoff location and indicator to either a specific turf or somewhere in an area +/datum/centcom_podlauncher/proc/setDropoff(target) + var/turf/target_turf + if (isturf(target)) + target_turf = target + else if (isarea(target)) + target_turf = pick(get_area_turfs(target)) + else + CRASH("Improper type passed to setDropoff! Should be /turf or /area") + temp_pod.reverse_dropoff_coords = list(target_turf.x, target_turf.y, target_turf.z) + indicator.forceMove(target_turf) + +/obj/effect/client_image_holder/supplypod_selector // Shows which item will be taken next + name = "Supply Selector (Only you can see this)" + image_icon = 'icons/obj/supplypods_32x32.dmi' + image_state = "selector" + image_layer = FLY_LAYER + layer = FLY_LAYER + plane = ABOVE_GAME_PLANE + alpha = 150 + +/obj/effect/client_image_holder/dropoff_location // Shows where revese pods lands + name = "Dropoff Location (Only you can see this)" + image_icon = 'icons/obj/supplypods_32x32.dmi' + image_state = "dropoff_indicator" + image_layer = FLY_LAYER + layer = FLY_LAYER + plane = ABOVE_GAME_PLANE + alpha = 0 + +#undef LAUNCH_ALL +#undef LAUNCH_ORDERED +#undef LAUNCH_RANDOM +#undef TAB_BAY +#undef TAB_POD diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm new file mode 100644 index 00000000000..9a1ed8dbc41 --- /dev/null +++ b/code/modules/cargo/supplypod.dm @@ -0,0 +1,767 @@ +//The "pod_landingzone" temp visual is created by anything that "launches" a supplypod. This is what animates the pod and makes the pod forcemove to the station. +//------------------------------------SUPPLY POD-------------------------------------// +/obj/structure/closet/supplypod + name = "supply pod" //Names and descriptions are normally created with the setStyle() proc during initialization, but we have these default values here as a failsafe + desc = "Капсула снабжения Nanotrasen." + icon = 'icons/obj/supplypods.dmi' + icon_state = "pod" //This is a common base sprite shared by a number of pods + pixel_x = SUPPLYPOD_X_OFFSET //2x2 sprite + layer = BELOW_OBJ_LAYER //So that the crate inside doesn't appear underneath + can_weld_shut = FALSE + armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80) + anchored = TRUE //So it cant slide around after landing + density = FALSE + ru_names = list( + NOMINATIVE = "капсула снабжения", + GENITIVE = "капсулы снабжения", + DATIVE = "капсуле снабжения", + ACCUSATIVE = "капсулу снабжения", + INSTRUMENTAL = "капсулой снабжения", + PREPOSITIONAL = "капсуле снабжения" + ) + ///List of bitflags for supply pods, see: code\__DEFINES\obj_flags.dm + var/pod_flags = NONE + + //*****NOTE*****: Many of these comments are similarly described in centcom_podlauncher.dm. If you change them here, please consider doing so in the centcom podlauncher code as well! + var/adminNamed = FALSE //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc) + var/bluespace = FALSE //If true, the pod deletes (in a shower of sparks) after landing + var/delays = list(POD_TRANSIT = 30, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30) + var/reverse_delays = list(POD_TRANSIT = 30, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30) + var/custom_rev_delay = FALSE + var/damage = 0 //Damage that occurs to any mob under the pod when it lands. + var/effectStun = FALSE //If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish! + var/effectLimb = FALSE //If true, pops off a limb (if applicable) from anyone caught under the pod when it lands + var/effectOrgans = FALSE //If true, yeets out every limb and organ from anyone caught under the pod when it lands + var/effectGib = FALSE //If true, anyone under the pod will be gibbed when it lands + var/effectStealth = FALSE //If true, a target icon isn't displayed on the turf where the pod will land + var/effectQuiet = FALSE //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc) + var/effectMissile = FALSE //If true, the pod deletes the second it lands. If you give it an explosion, it will act like a missile exploding as it hits the ground + var/effectCircle = FALSE //If true, allows the pod to come in at any angle. Bit of a weird feature but whatever its here + var/datum/pod_style/style = /datum/pod_style //Style is a variable that keeps track of what the pod is supposed to look like. Only stores a path, type is set for ease of var access + var/reversing = FALSE //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom + var/list/reverse_dropoff_coords //Turf that the reverse pod will drop off its newly-acquired cargo to + var/fallingSoundLength = 11 + var/fallingSound = 'sound/weapons/mortar_long_whistle.ogg'//Admin sound to play before the pod lands + var/landingSound //Admin sound to play when the pod lands + var/openingSound //Admin sound to play when the pod opens + var/leavingSound //Admin sound to play when the pod leaves + var/soundVolume = 80 //Volume to play sounds at. Ignores the cap + var/list/explosionSize = list(0,0,2,3) + var/stay_after_drop = FALSE + var/specialised = FALSE // It's not a general use pod for cargo/admin use + var/rubble_type //Rubble effect associated with this supplypod + var/decal = "default" //What kind of extra decals we add to the pod to make it look nice + var/door = "pod_door" + var/fin_mask = "topfin" + var/obj/effect/supplypod_rubble/rubble + var/obj/effect/engineglow/glow_effect + var/effectShrapnel = FALSE + var/shrapnel_type = /obj/item/projectile/shrapnel + var/shrapnel_magnitude = 3 + var/list/reverse_option_list = list(MOB_OPTION=FALSE, UNANCHORED_OPTION=FALSE, ANCHORED_OPTION=FALSE, MECHA_OPTION=FALSE) + +/obj/structure/closet/supplypod/bluespacepod + style = /datum/pod_style/advanced + bluespace = TRUE + explosionSize = list(0,0,1,2) + +//type used for one drop spawning items. doesn't have a style as style is set by the helper that creates this +/obj/structure/closet/supplypod/podspawn + bluespace = TRUE + explosionSize = list(0,0,0,0) + +/obj/structure/closet/supplypod/podspawn/deathmatch + desc = "Десантная капсула в кроваво-красном стиле." + specialised = TRUE + +/obj/structure/closet/supplypod/podspawn/deathmatch/preOpen() + for(var/mob/living/critter in contents) + critter.faction = list("hostile") //No infighting, but also KILL!! + return ..() + +/obj/structure/closet/supplypod/extractionpod + name = "Syndicate Extraction Pod" + desc = "Специализированная капсула кроваво-красного цвета для эвакуации ценных целей из зон активных задач. Для правильной доставки цели необходимо вручную поместить в капсулу." + specialised = TRUE + style = /datum/pod_style/syndicate + bluespace = TRUE + explosionSize = list(0,0,1,2) + delays = list(POD_TRANSIT = 25, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30) + reversing = TRUE + stay_after_drop = TRUE + leavingSound = 'sound/effects/podwoosh.ogg' + reverse_option_list = list(MOB_OPTION=TRUE, UNANCHORED_OPTION=FALSE, ANCHORED_OPTION=FALSE, MECHA_OPTION=FALSE) + ru_names = list( + NOMINATIVE = "капсула эвакуации Синдиката", + GENITIVE = "капсулы эвакуации Синдиката", + DATIVE = "капсуле эвакуации Синдиката", + ACCUSATIVE = "капсулу эвакуации Синдиката", + INSTRUMENTAL = "капсулой эвакуации Синдиката", + PREPOSITIONAL = "капсуле эвакуации Синдиката" + ) + +/obj/structure/closet/supplypod/centcompod + style = /datum/pod_style/centcom + bluespace = TRUE + explosionSize = list(0,0,0,0) + delays = list(POD_TRANSIT = 20, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30) + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + +/obj/structure/closet/supplypod/centcompod/sisyphus + delays = list(POD_TRANSIT = 0, POD_FALLING = 0, POD_OPENING = 0, POD_LEAVING = 0.2) + reverse_delays = list(POD_TRANSIT = 0, POD_FALLING = 1.5 SECONDS, POD_OPENING = 0.6 SECONDS, POD_LEAVING = 0) + custom_rev_delay = TRUE + effectStealth = TRUE + reversing = TRUE + reverse_option_list = list( + MOB_OPTION = TRUE, + UNANCHORED_OPTION = FALSE, + ANCHORED_OPTION = FALSE, + MECHA_OPTION = TRUE, + ) + +/obj/structure/closet/supplypod/back_to_station + name = "blood-red supply pod" + desc = "Устрашающая капсула снабжения, покрытая кроваво-красными отметинами." + bluespace = TRUE + explosionSize = list(0,0,0,0) + style = /datum/pod_style/syndicate + specialised = TRUE + ru_names = list( + NOMINATIVE = "кроваво-красная капсула снабжения", + GENITIVE = "кроваво-красной капсулы снабжения", + DATIVE = "кроваво-красной капсуле снабжения", + ACCUSATIVE = "кроваво-красную капсулу снабжения", + INSTRUMENTAL = "кроваво-красной капсулой снабжения", + PREPOSITIONAL = "кроваво-красной капсуле снабжения" + ) + +/obj/structure/closet/supplypod/deadmatch_missile + name = "cruise missile" + desc = "Огромная ракета, вероятно, запущенная из какой-то далекой ракетной шахты в дальнем космосе" + style = /datum/pod_style/missile/syndicate + explosionSize = list(0,1,2,2) + effectShrapnel = TRUE + specialised = TRUE + delays = list(POD_TRANSIT = 2.6 SECONDS, POD_FALLING = 0.4 SECONDS) + effectMissile = TRUE + ru_names = list( + NOMINATIVE = "крылатая ракета", + GENITIVE = "крылатой ракеты", + DATIVE = "крылатой ракете", + ACCUSATIVE = "крылатую ракету", + INSTRUMENTAL = "крылатой ракете", + PREPOSITIONAL = "крылатой ракетой" + ) + + +/obj/structure/closet/supplypod/Initialize(mapload, customStyle = FALSE) + . = ..() + if (!loc) + var/shippingLane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] //temporary holder for supplypods mid-transit + forceMove(shippingLane) + if (customStyle) + style = customStyle + setStyle(style) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly + +/obj/structure/closet/supplypod/proc/setStyle(datum/pod_style/chosen_style) //Used to give the sprite an icon state, name, and description. + style = chosen_style + if(!(style in GLOB.pod_styles_by_type)) + GLOB.pod_styles_by_type[chosen_style] = new chosen_style + chosen_style = GLOB.pod_styles_by_type[chosen_style] + icon_state = chosen_style.icon_state + decal = chosen_style.decal_icon + rubble_type = chosen_style.rubble_type + if (!adminNamed && !specialised) //We dont want to name it ourselves if it has been specifically named by an admin using the centcom_podlauncher datum + name = chosen_style.name + desc = chosen_style.desc + ru_names = chosen_style.ru_names + if (chosen_style.has_door) + door = "[icon_state]_door" + else + door = FALSE + update_appearance() + +/obj/structure/closet/supplypod/proc/SetReverseIcon() + fin_mask = "bottomfin" + if (style::shape == POD_SHAPE_NORMAL) + icon_state = style::icon_state + "_reverse" + pixel_x = initial(pixel_x) + transform = matrix() + update_appearance() + +/obj/structure/closet/supplypod/proc/backToNonReverseIcon() + fin_mask = initial(fin_mask) + if (style::shape == POD_SHAPE_NORMAL) + icon_state = style::icon_state + pixel_x = initial(pixel_x) + transform = matrix() + update_appearance() + + +/obj/structure/closet/supplypod/update_overlays() + . = ..() + if(ispath(style, /datum/pod_style/invisible)) + return + + if(rubble) + . += rubble.getForeground(src) + + if(ispath(style, /datum/pod_style/seethrough)) + for(var/atom/A in contents) + var/mutable_appearance/itemIcon = new(A) + itemIcon.transform = matrix().Translate(-1 * SUPPLYPOD_X_OFFSET, 0) + . += itemIcon + return + + if(opened) //We're opened means all we have to worry about is masking a decal if we have one + if(!decal) //We don't have a decal to mask + return + if(!door) //We have a decal but no door, so let's just add the decal + . += decal + return + var/icon/masked_decal = new(icon, decal) //The decal we want to apply + var/icon/door_masker = new(icon, door) //The door shape we want to 'cut out' of the decal + door_masker.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 1,1,1,0, 0,0,0,1) + door_masker.SwapColor("#ffffffff", null) + door_masker.Blend(COLOR_BLACK, ICON_SUBTRACT) + masked_decal.Blend(door_masker, ICON_ADD) + . += masked_decal + return + + //If we're closed + if(!door) //We have no door, lets see if we have a decal. If not, theres nothing we need to do + if(decal) + . += decal + return + else if (style::shape != POD_SHAPE_NORMAL) //If we're not a normal pod shape (aka, if we don't have fins), just add the door without masking + . += door + else + var/icon/masked_door = new(icon, door) //The door we want to apply + var/icon/fin_masker = new(icon, "mask_[fin_mask]") //The fin shape we want to 'cut out' of the door + fin_masker.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 1,1,1,0, 0,0,0,1) + fin_masker.SwapColor("#ffffffff", null) + fin_masker.Blend(COLOR_BLACK, ICON_SUBTRACT) + masked_door.Blend(fin_masker, ICON_ADD) + . += masked_door + if(decal) + . += decal + + +/obj/structure/closet/supplypod/tool_act(mob/living/user, obj/item/I, tool_type) + if(bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways. + return FALSE + else + ..() + + +/obj/structure/closet/supplypod/ex_act() //Explosions dont do SHIT TO US! This is because supplypods create explosions when they land. + return FALSE + +/obj/structure/closet/supplypod/contents_explosion() //Supplypods also protect their contents from the harmful effects of fucking exploding. + return + +/obj/structure/closet/supplypod/toggle(mob/living/user) + return + +///Called by the drop pods that return captured crewmembers from the ninja den. +/obj/structure/closet/supplypod/proc/return_from_capture(mob/living/victim, turf/destination = get_safe_random_station_turf()) + if(isnull(destination)) //Uuuuh, something went wrong. This is gonna hurt. + to_chat(victim, span_holoparasite("Миллион голосов эхом звучит в твоей голове... «Похоже, там, куда тебя отправили, не могут справиться с нашей капсулой...\ + как будто мы хотели, чтобы пассажир выжил. Держись, корпоративная собака»")) + explosionSize = list(0,1,1,1) + destination = get_random_station_turf() + + do_sparks(8, FALSE, victim) + victim.visible_message(span_notice("[victim] исчезает...")) + + victim.forceMove(src) + + new /obj/effect/pod_landingzone(destination, src) + +/obj/structure/closet/supplypod/proc/handleReturnAfterDeparting(atom/movable/holder = src) + reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open_pod() ) + bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever + pod_flags &= ~FIRST_SOUNDS //Make it so we play sounds now + if (!effectQuiet && !ispath(style, /datum/pod_style/seethrough)) + audible_message(span_notice("Капсула шипит, закрываясь и улетая прочь от станции."), span_notice("Земля вибрирует, и вы слышите звук работающих двигателей.")) + stay_after_drop = FALSE + holder.pixel_z = initial(holder.pixel_z) + holder.alpha = initial(holder.alpha) + if (holder != src) + contents |= holder.contents + qdel(holder) + var/shippingLane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] + forceMove(shippingLane) //Move to the centcom-z-level until the pod_landingzone says we can drop back down again + if (custom_rev_delay) + delays = reverse_delays + backToNonReverseIcon() + var/turf/return_turf = locate(reverse_dropoff_coords[1], reverse_dropoff_coords[2], reverse_dropoff_coords[3]) + new /obj/effect/pod_landingzone(return_turf, src) + +/obj/structure/closet/supplypod/proc/preOpen() //Called before the open_pod() proc. Handles anything that occurs right as the pod lands. + var/turf/turf_underneath = get_turf(src) + var/list/B = explosionSize //Mostly because B is more readable than explosionSize :p + resistance_flags = initial(resistance_flags) + set_density(TRUE) //Density is originally false so the pod doesn't block anything while it's still falling through the air + AddComponent(/datum/component/pellet_cloud, projectile_type=shrapnel_type, magnitude=shrapnel_magnitude) + if(effectShrapnel) + SEND_SIGNAL(src, COMSIG_SUPPLYPOD_LANDED) + for (var/mob/living/target_living in turf_underneath) + if (iscarbon(target_living)) //If effectLimb is true (which means we pop limbs off when we hit people): + if (effectLimb && !effectOrgans && ishuman(target_living)) + var/mob/living/carbon/human/human_target_mob = target_living + var/obj/item/organ/external/bodypart + var/list/possible_organs = list() + for (var/bp in human_target_mob.bodyparts) + bodypart = bp + if(bodypart.limb_zone != BODY_ZONE_HEAD && bodypart.limb_zone != BODY_ZONE_CHEST \ + && bodypart.limb_zone != BODY_ZONE_PRECISE_GROIN && !(bodypart.cannot_amputate))//we dont want to kill him, just teach em a lesson! + possible_organs |= bp + if(possible_organs.len) + bodypart = pick(possible_organs) + bodypart.droplimb() + + if (effectOrgans) //effectOrgans means remove every organ in our mob + var/mob/living/carbon/carbon_target_mob = target_living + for(var/obj/item/organ/internal/organ_to_yeet as anything in carbon_target_mob.internal_organs) + var/destination = get_edge_target_turf(turf_underneath, pick(GLOB.alldirs)) //Pick a random direction to toss them in + organ_to_yeet.remove(carbon_target_mob) //Note that this isn't the same proc as for lists + organ_to_yeet.forceMove(turf_underneath) //Move the organ outta the body + organ_to_yeet.throw_at(destination, 2, 3) //Thow the organ at a random tile 3 spots away + if(!ishuman(carbon_target_mob)) + continue + var/mob/living/carbon/human/human_target_mob = carbon_target_mob + for (var/bp in human_target_mob.bodyparts) //Look at the bodyparts in our poor mob beneath our pod as it lands + var/obj/item/organ/external/bodypart = bp + var/destination = get_edge_target_turf(turf_underneath, pick(GLOB.alldirs)) + if (!(bodypart.cannot_amputate)) + bodypart.droplimb()//Using the power of flextape i've sawed this man's bodypart in half! + bodypart.throw_at(destination, 2, 3) + + if (effectGib) //effectGib is on, that means whatever's underneath us better be fucking oof'd on + target_living.adjustBruteLoss(5000) //THATS A LOT OF DAMAGE (called just in case gib() doesnt work on em) + if (!QDELETED(target_living)) + target_living.gib() //After adjusting the fuck outta that brute loss we finish the job with some satisfying gibs + else + target_living.adjustBruteLoss(damage) + var/explosion_sum = B[1] + B[2] + B[3] + B[4] + if (explosion_sum != 0) //If the explosion list isn't all zeroes, call an explosion + explosion(turf_underneath, B[1], B[2], B[3], flame_range = B[4], silent = effectQuiet, ignorecap = istype(src, /obj/structure/closet/supplypod/centcompod), cause = src) //less advanced equipment than bluespace pod, so larger explosion when landing + else if (!effectQuiet && !(pod_flags & FIRST_SOUNDS)) //If our explosion list IS all zeroes, we still make a nice explosion sound (unless the effectQuiet var is true) + playsound(src, "explosion", landingSound ? soundVolume * 0.25 : soundVolume, TRUE) + if (landingSound) + playsound(turf_underneath, landingSound, soundVolume, FALSE, FALSE) + if (effectMissile) //If we are acting like a missile, then right after we land and finish fucking shit up w explosions, we should delete + opened = TRUE //We set opened to TRUE to avoid spending time trying to open (due to being deleted) during the Destroy() proc + qdel(src) + return + if (ispath(style, /datum/pod_style/gondola)) //Checks if we are supposed to be a gondola pod. If so, create a gondolapod mob, and move this pod to nullspace. I'd like to give a shout out, to my man oranges + var/mob/living/simple_animal/pet/gondola/gondolapod/benis = new(turf_underneath, src) + benis.contents |= contents //Move the contents of this supplypod into the gondolapod mob. + for (var/mob/living/mob_in_pod in benis.contents) + mob_in_pod.reset_perspective(null) + moveToNullspace() + addtimer(CALLBACK(src, PROC_REF(open_pod), benis), delays[POD_OPENING]) //After the opening delay passes, we use the open proc from this supplyprod while referencing the contents of the "holder", in this case the gondolapod mob + else if (ispath(style, /datum/pod_style/seethrough)) + open_pod(src) + else + addtimer(CALLBACK(src, PROC_REF(open_pod), src), delays[POD_OPENING]) //After the opening delay passes, we use the open proc from this supplypod, while referencing this supplypod's contents + +/obj/structure/closet/supplypod/proc/open_pod(atom/movable/holder, broken = FALSE, forced = FALSE) //The holder var represents an atom whose contents we will be working with + if (!holder) + return + if (opened) //This is to ensure we don't open something that has already been opened + return + holder.setOpened() + var/turf/turf_underneath = get_turf(holder) //Get the turf of whoever's contents we're talking about + if (istype(holder, /mob)) //Allows mobs to assume the role of the holder, meaning we look at the mob's contents rather than the supplypod's contents. Typically by this point the supplypod's contents have already been moved over to the mob's contents + var/mob/holder_as_mob = holder + if (holder_as_mob.key && !forced && !broken) //If we are player controlled, then we shouldn't open unless the opening is manual, or if it is due to being destroyed (represented by the "broken" parameter) + return + if (openingSound) + playsound(get_turf(holder), openingSound, soundVolume, FALSE, FALSE) //Special admin sound to play + for (var/cargo in holder.contents) + var/atom/movable/movable_cargo = cargo + movable_cargo.forceMove(turf_underneath) + if (!effectQuiet && !openingSound && !ispath(style, /datum/pod_style/seethrough) && !(pod_flags & FIRST_SOUNDS)) //If we aren't being quiet, play the default pod open sound + playsound(get_turf(holder), open_sound, 15, TRUE, -3) + if (broken) //If the pod is opening because it's been destroyed, we end here + return + if (ispath(style, /datum/pod_style/seethrough)) + startExitSequence(src) + else + if (reversing) + addtimer(CALLBACK(src, PROC_REF(SetReverseIcon)), delays[POD_LEAVING]/2) //Finish up the pod's duties after a certain amount of time + if(!stay_after_drop) // Departing should be handled manually + addtimer(CALLBACK(src, PROC_REF(startExitSequence), holder), delays[POD_LEAVING]*(4/5)) //Finish up the pod's duties after a certain amount of time + +/obj/structure/closet/supplypod/proc/startExitSequence(atom/movable/holder) + if (leavingSound) + playsound(get_turf(holder), leavingSound, soundVolume, FALSE, FALSE) + if (reversing) //If we're reversing, we call the close proc. This sends the pod back up to centcom + close(holder) + else if (bluespace) //If we're a bluespace pod, then delete ourselves (along with our holder, if a separate holder exists) + deleteRubble() + if (!effectQuiet && !ispath(style, /datum/pod_style/invisible) && !ispath(style, /datum/pod_style/seethrough)) + do_sparks(5, TRUE, holder) //Create some sparks right before closing + qdel(src) //Delete ourselves and the holder + if (holder != src) + qdel(holder) + +/obj/structure/closet/supplypod/close(atom/movable/holder) //Closes the supplypod and sends it back to centcom. Should only ever be called if the "reversing" variable is true + if (!holder) + return + take_contents(holder) + playsound(holder, close_sound, soundVolume*0.75, TRUE, -3) + holder.setClosed() + addtimer(CALLBACK(src, PROC_REF(preReturn), holder), delays[POD_LEAVING] * 0.2) //Start to leave a bit after closing for cinematic effect + +/obj/structure/closet/supplypod/take_contents(atom/movable/holder) + var/turf/turf_underneath = holder.drop_location() + for(var/atom_to_check in turf_underneath) + if(atom_to_check != src && !insert(atom_to_check, holder)) // Can't insert that + continue + insert(turf_underneath, holder) + +/obj/structure/closet/supplypod/proc/insert(atom/to_insert, atom/movable/holder) + if(insertion_allowed(to_insert)) + var/atom/movable/movable_to_insert = to_insert + movable_to_insert.forceMove(holder) + return TRUE + else + return FALSE + +/obj/structure/closet/supplypod/proc/insertion_allowed(atom/to_insert) + if(to_insert.invisibility == INVISIBILITY_ABSTRACT) + return FALSE + if(ismob(to_insert)) + if(!reverse_option_list[MOB_OPTION]) + return FALSE + if(!isliving(to_insert)) //let's not put ghosts or camera mobs inside + return FALSE + var/mob/living/mob_to_insert = to_insert + if(mob_to_insert.anchored || mob_to_insert.incorporeal_move) + return FALSE + mob_to_insert.stop_pulling() + + else if(isobj(to_insert)) + var/obj/obj_to_insert = to_insert + if(issupplypod(obj_to_insert)) + return FALSE + if(istype(obj_to_insert, /obj/effect/supplypod_smoke)) + return FALSE + if(istype(obj_to_insert, /obj/effect/pod_landingzone)) + return FALSE + if(istype(obj_to_insert, /obj/effect/supplypod_rubble)) + return FALSE + if(istype(obj_to_insert, /obj/machinery/light)) + return FALSE + + if(!obj_to_insert.anchored && reverse_option_list[UNANCHORED_OPTION]) + return TRUE + if(obj_to_insert.anchored && !ismecha(obj_to_insert) && reverse_option_list[ANCHORED_OPTION]) //Mecha are anchored but there is a separate option for them + return TRUE + if(ismecha(obj_to_insert) && reverse_option_list[MECHA_OPTION]) + return TRUE + return FALSE + + else if (isturf(to_insert)) + return FALSE + return TRUE + +/obj/structure/closet/supplypod/proc/preReturn(atom/movable/holder) + deleteRubble() + animate(holder, alpha = 0, time = 8, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL) + animate(holder, pixel_z = 400, time = 10, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL) //Animate our rising pod + addtimer(CALLBACK(src, PROC_REF(handleReturnAfterDeparting), holder), 15) //Finish up the pod's duties after a certain amount of time + +/obj/structure/closet/supplypod/extractionpod/preReturn(atom/movable/holder) + // Double ensure we're loaded, this SHOULD be here by now but you never know + var/turf/picked_turf = pick(GLOB.ninja_teleport) + reverse_dropoff_coords = list(picked_turf.x, picked_turf.y, picked_turf.z) + return ..() + +/obj/structure/closet/supplypod/setOpened() //Proc exists here, as well as in any atom that can assume the role of a "holder" of a supplypod. Check the open_pod() proc for more details + opened = TRUE + set_density(FALSE) + update_appearance() + after_open(null, FALSE) + +/obj/structure/closet/supplypod/open() + return + +/obj/structure/closet/supplypod/extractionpod/setOpened() + opened = TRUE + set_density(TRUE) + update_appearance() + after_open(null, FALSE) + +/obj/structure/closet/supplypod/setClosed() //Ditto + opened = FALSE + set_density(TRUE) + update_appearance() + +/obj/structure/closet/supplypod/proc/tryMakeRubble(turf/T) //Ditto + if (rubble_type == RUBBLE_NONE) + return + if (rubble) + return + if (effectMissile) + return + if (isspaceturf(T) || iswallturf(T) || ismineralturf(T)) + return + rubble = new /obj/effect/supplypod_rubble(T) + rubble.setStyle(rubble_type, src) + update_appearance() + +/obj/structure/closet/supplypod/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) + deleteRubble() + return ..() + +/obj/structure/closet/supplypod/proc/deleteRubble() + rubble?.fadeAway() + rubble = null + update_appearance() + +/obj/structure/closet/supplypod/proc/addGlow() + if (style::shape != POD_SHAPE_NORMAL) + return + glow_effect = new(src) + glow_effect.icon_state = "pod_glow_" + style::glow_color + vis_contents += glow_effect + glow_effect.layer = GASFIRE_LAYER + SET_PLANE_EXPLICIT(glow_effect, ABOVE_GAME_PLANE, src) + RegisterSignal(glow_effect, COMSIG_QDELETING, PROC_REF(remove_glow)) + +/obj/structure/closet/supplypod/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) + . = ..() + if(same_z_layer) + return + if(glow_effect) + SET_PLANE_EXPLICIT(glow_effect, ABOVE_GAME_PLANE, src) + +/obj/structure/closet/supplypod/proc/endGlow() + if(!glow_effect) + return + glow_effect.layer = LOW_ITEM_LAYER + glow_effect.fadeAway(delays[POD_OPENING]) + //Trust the signals + +/obj/structure/closet/supplypod/proc/remove_glow() + SIGNAL_HANDLER + UnregisterSignal(glow_effect, COMSIG_QDELETING) + vis_contents -= glow_effect + glow_effect = null + +/obj/structure/closet/supplypod/Destroy() + deleteRubble() + //Trust the signals even harder + qdel(glow_effect) + open_pod(src, broken = TRUE) //Lets dump our contents by opening up + return ..() + +//------------------------------------TEMPORARY_VISUAL-------------------------------------// +/obj/effect/supplypod_smoke //Falling pod smoke + name = "" + icon = 'icons/obj/supplypods_32x32.dmi' + icon_state = "smoke" + desc = "" + layer = PROJECTILE_HIT_THRESHHOLD_LAYER + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + alpha = 0 + +/obj/effect/engineglow //Falling pod smoke + name = "" + icon = 'icons/obj/supplypods.dmi' + icon_state = "pod_glow_green" + desc = "" + layer = GASFIRE_LAYER + plane = ABOVE_GAME_PLANE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + alpha = 255 + +/obj/effect/engineglow/proc/fadeAway(leaveTime) + var/duration = min(leaveTime, 25) + animate(src, alpha=0, time = duration) + QDEL_IN(src, duration + 5) + +/obj/effect/supplypod_smoke/proc/drawSelf(amount) + alpha = max(0, 255-(amount*20)) + +/obj/effect/supplypod_rubble + name = "debris" + desc = "Небольшой кратер из обломков. При ближайшем рассмотрении выясняется, что обломки состоят в основном из фрагментов металла. Вы почти уверены, что они скоро рассеется." + icon = 'icons/obj/supplypods.dmi' + layer = PROJECTILE_HIT_THRESHHOLD_LAYER // We want this to go right below the layer of supplypods and supplypod_rubble's forground. + icon_state = "rubble_bg" + anchored = TRUE + pixel_x = SUPPLYPOD_X_OFFSET + var/foreground = "rubble_fg" + var/verticle_offset = 0 + ru_names = list( + NOMINATIVE = "обломки", + GENITIVE = "обломков", + DATIVE = "обломкам", + ACCUSATIVE = "обломки", + INSTRUMENTAL = "обломками", + PREPOSITIONAL = "обломках" + ) + +/obj/effect/supplypod_rubble/proc/getForeground(obj/structure/closet/supplypod/pod) + var/mutable_appearance/rubble_overlay = mutable_appearance('icons/obj/supplypods.dmi', foreground) + rubble_overlay.appearance_flags = KEEP_APART|RESET_TRANSFORM + rubble_overlay.transform = matrix().Translate(SUPPLYPOD_X_OFFSET - pod.pixel_x, verticle_offset) + return rubble_overlay + +/obj/effect/supplypod_rubble/proc/fadeAway() + animate(src, alpha=0, time = 30) + QDEL_IN(src, 35) + +/obj/effect/supplypod_rubble/proc/setStyle(type, obj/structure/closet/supplypod/pod) + if (type == RUBBLE_WIDE) + icon_state += "_wide" + foreground += "_wide" + if (type == RUBBLE_THIN) + icon_state += "_thin" + foreground += "_thin" + if (ispath(pod.style, /datum/pod_style/box)) + verticle_offset = -2 + else + verticle_offset = initial(verticle_offset) + + pixel_y = verticle_offset + +/obj/effect/pod_landingzone_effect + name = "" + desc = "" + icon = 'icons/obj/supplypods_32x32.dmi' + icon_state = "LZ_Slider" + layer = PROJECTILE_HIT_THRESHHOLD_LAYER + +/obj/effect/pod_landingzone_effect/Initialize(mapload, obj/structure/closet/supplypod/pod) + . = ..() + if(!pod) + stack_trace("Pod landingzone effect created with no pod") + return INITIALIZE_HINT_QDEL + transform = matrix() * 1.5 + animate(src, transform = matrix()*0.01, time = pod.delays[POD_TRANSIT]+pod.delays[POD_FALLING]) + +/obj/effect/pod_landingzone //This is the object that forceMoves the supplypod to its location + name = "Landing Zone Indicator" + desc = "Голографическая проекция, обозначающая зону приземления чего-либо. Наверное, лучше стоять в стороне." + icon = 'icons/obj/supplypods_32x32.dmi' + icon_state = "LZ" + layer = PROJECTILE_HIT_THRESHHOLD_LAYER + light_range = 2 + anchored = TRUE + alpha = 0 + var/obj/structure/closet/supplypod/pod //The supplyPod that will be landing ontop of this pod_landingzone + var/obj/effect/pod_landingzone_effect/helper + var/list/smoke_effects = new /list(13) + ru_names = list( + NOMINATIVE = "индикатор зоны приземления", + GENITIVE = "индикатора зоны приземления", + DATIVE = "индикатору зоны приземления", + ACCUSATIVE = "индикатор зоны приземления", + INSTRUMENTAL = "индикатором зоны приземления", + PREPOSITIONAL = "индикаторе зоны приземления" + ) + +/obj/effect/pod_landingzone/Initialize(mapload, podParam, single_order = null, clientman) + . = ..() + if(!podParam) + stack_trace("Pod landingzone created with no pod") + return INITIALIZE_HINT_QDEL + if (ispath(podParam)) //We can pass either a path for a pod (as expressconsoles do), or a reference to an instantiated pod (as the centcom_podlauncher does) + podParam = new podParam() //If its just a path, instantiate it + pod = podParam + pod.resistance_flags |= (INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF) + if (!pod.effectStealth) + helper = new (drop_location(), pod) + alpha = 255 + animate(src, transform = matrix().Turn(90), time = pod.delays[POD_TRANSIT]+pod.delays[POD_FALLING]) + if (single_order) + if (istype(single_order, /datum/supply_order)) + var/datum/supply_order/SO = single_order + if (SO.object.containertype) + SO.createObject(pod) + else if (istype(single_order, /atom/movable)) + var/atom/movable/O = single_order + O.forceMove(pod) + for (var/mob/living/mob_in_pod in pod) //If there are any mobs in the supplypod, we want to set their view to the pod_landingzone. This is so that they can see where they are about to land + mob_in_pod.reset_perspective(src) + if(pod.effectStun) //If effectStun is true, stun any mobs caught on this pod_landingzone until the pod gets a chance to hit them + for (var/mob/living/target_living in get_turf(src)) + target_living.AdjustWeakened(pod.delays[POD_TRANSIT] + 20, TRUE)//you ain't goin nowhere, kid. + target_living.AdjustStunned(pod.delays[POD_TRANSIT] + 20, TRUE) + if (pod.delays[POD_TRANSIT] + pod.delays[POD_FALLING] < pod.fallingSoundLength) + pod.fallingSoundLength = 3 //The default falling sound is a little long, so if the landing time is shorter than the default falling sound, use a special, shorter default falling sound + pod.fallingSound = 'sound/weapons/mortar_whistle.ogg' + var/soundStartTime = pod.delays[POD_TRANSIT] - pod.fallingSoundLength + pod.delays[POD_FALLING] + if (soundStartTime < 0) + soundStartTime = 1 + if (!pod.effectQuiet && !(pod.pod_flags & FIRST_SOUNDS)) + addtimer(CALLBACK(src, PROC_REF(playFallingSound)), soundStartTime) + addtimer(CALLBACK(src, PROC_REF(beginLaunch), pod.effectCircle), pod.delays[POD_TRANSIT]) + +/obj/effect/pod_landingzone/proc/playFallingSound() + playsound(src, pod.fallingSound, pod.soundVolume, TRUE, 6) + +/obj/effect/pod_landingzone/proc/beginLaunch(effectCircle) //Begin the animation for the pod falling. The effectCircle param determines whether the pod gets to come in from any descent angle + pod.addGlow() + pod.update_appearance() + pod.forceMove(drop_location()) + for (var/mob/living/M in pod) //Remember earlier (initialization) when we moved mobs into the pod_landingzone so they wouldnt get lost in nullspace? Time to get them out + M.reset_perspective(null) + var/angle = effectCircle ? rand(0,360) : rand(70,110) //The angle that we can come in from + pod.pixel_x = cos(angle)*32*length(smoke_effects) //Use some ADVANCED MATHEMATICS to set the animated pod's position to somewhere on the edge of a circle with the center being the pod_landingzone + pod.pixel_z = sin(angle)*32*length(smoke_effects) + var/rotation = get_pixel_angle(pod.pixel_z, pod.pixel_x) //CUSTOM HOMEBREWED proc that is just arctan with extra steps + setupSmoke(rotation) + pod.transform = matrix().Turn(rotation) + pod.layer = FLY_LAYER + SET_PLANE_EXPLICIT(pod, ABOVE_GAME_PLANE, src) + if (!ispath(pod.style, /datum/pod_style/invisible)) + animate(pod, pixel_z = -1 * abs(sin(rotation))*4, pixel_x = SUPPLYPOD_X_OFFSET + (sin(rotation) * 20), time = pod.delays[POD_FALLING], easing = LINEAR_EASING) //Make the pod fall! At an angle! + addtimer(CALLBACK(src, PROC_REF(endLaunch)), pod.delays[POD_FALLING], TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation + +/obj/effect/pod_landingzone/proc/setupSmoke(rotation) + if (ispath(pod.style, /datum/pod_style/invisible) || ispath(pod.style, /datum/pod_style/seethrough)) + return + var/turf/our_turf = get_turf(drop_location()) + for ( var/i in 1 to length(smoke_effects)) + var/obj/effect/supplypod_smoke/smoke_part = new (drop_location()) + if (i == 1) + smoke_part.layer = FLY_LAYER + SET_PLANE(smoke_part, ABOVE_GAME_PLANE, our_turf) + smoke_part.icon_state = "smoke_start" + smoke_part.transform = matrix().Turn(rotation) + smoke_effects[i] = smoke_part + smoke_part.pixel_x = sin(rotation)*32 * i + smoke_part.pixel_y = abs(cos(rotation))*32 * i + smoke_part.add_filter("smoke_blur", 1, gauss_blur_filter(size = 4)) + var/time = (pod.delays[POD_FALLING] / length(smoke_effects))*(length(smoke_effects)-i) + addtimer(CALLBACK(smoke_part, TYPE_PROC_REF(/obj/effect/supplypod_smoke/, drawSelf), i), time, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation + QDEL_IN(smoke_part, pod.delays[POD_FALLING] + 35) + +/obj/effect/pod_landingzone/proc/drawSmoke() + if (ispath(pod.style, /datum/pod_style/invisible) || ispath(pod.style, /datum/pod_style/seethrough)) + return + for (var/obj/effect/supplypod_smoke/smoke_part in smoke_effects) + animate(smoke_part, alpha = 0, time = 20, flags = ANIMATION_PARALLEL) + animate(smoke_part.get_filter("smoke_blur"), size = 6, time = 15, easing = CUBIC_EASING|EASE_OUT, flags = ANIMATION_PARALLEL) + +/obj/effect/pod_landingzone/ex_act(severity) + return FALSE + +/obj/effect/pod_landingzone/proc/endLaunch() + var/turf/our_turf = get_turf(drop_location()) + pod.tryMakeRubble(drop_location()) + pod.layer = initial(pod.layer) + SET_PLANE(pod, initial(pod.plane), our_turf) + pod.endGlow() + QDEL_NULL(helper) + pod.preOpen() //Begin supplypod open procedures. Here effects like explosions, damage, and other dangerous (and potentially admin-caused, if the centcom_podlauncher datum was used) memes will take place + drawSmoke() + qdel(src) //The pod_landingzone's purpose is complete. It can rest easy now diff --git a/code/modules/hallucination/_hallucination.dm b/code/modules/hallucination/_hallucination.dm new file mode 100644 index 00000000000..c59b1af61a2 --- /dev/null +++ b/code/modules/hallucination/_hallucination.dm @@ -0,0 +1,123 @@ +/** + * Simple effect that holds an image + * to be shown to one or multiple clients only. + * + * Pass a list of mobs in initialize() that corresponds to all mobs that can see it. + */ +/obj/effect/client_image_holder + invisibility = INVISIBILITY_OBSERVER + anchored = TRUE + + /// A list of mobs which can see us. + var/list/mob/who_sees_us + /// The created image, what we look like. + var/image/shown_image + /// The icon file the image uses. If null, we have no image + var/image_icon + /// The icon state the image uses + var/image_state + /// The x pixel offset of the image + var/image_pixel_x = 0 + /// The y pixel offset of the image + var/image_pixel_y = 0 + /// Optional, the color of the image + var/image_color + /// The layer of the image + var/image_layer = MOB_LAYER + /// The plane of the image + var/image_plane = GAME_PLANE + +/obj/effect/client_image_holder/Initialize(mapload, list/mobs_which_see_us) + . = ..() + if(isnull(mobs_which_see_us)) + stack_trace("Client image holder was created with no mobs to see it.") + return INITIALIZE_HINT_QDEL + + shown_image = generate_image() + + if(!islist(mobs_which_see_us)) + mobs_which_see_us = list(mobs_which_see_us) + + who_sees_us = list() + for(var/mob/seer as anything in mobs_which_see_us) + RegisterSignal(seer, COMSIG_MOB_LOGIN, PROC_REF(show_image_to)) + RegisterSignal(seer, COMSIG_QDELETING, PROC_REF(remove_seer)) + who_sees_us += seer + show_image_to(seer) + +/obj/effect/client_image_holder/Destroy(force) + if(shown_image) + for(var/mob/seer as anything in who_sees_us) + remove_seer(seer) + shown_image = null + + who_sees_us.Cut() // probably not needed but who knows + return ..() + +/obj/effect/client_image_holder/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) + . = ..() + if(QDELETED(src) || same_z_layer) + return + SET_PLANE(shown_image, PLANE_TO_TRUE(shown_image.plane), new_turf) + +/// Signal proc to clean up references if people who see us are deleted. +/obj/effect/client_image_holder/proc/remove_seer(mob/source) + SIGNAL_HANDLER + + UnregisterSignal(source, list(COMSIG_MOB_LOGIN, COMSIG_QDELETING)) + hide_image_from(source) + who_sees_us -= source + + // No reason to exist, anymore + if(!QDELETED(src) && !length(who_sees_us)) + qdel(src) + +/// Generates the image which we take on. +/obj/effect/client_image_holder/proc/generate_image() + var/image/created = image(image_icon, src, image_state, image_layer, dir = src.dir) + SET_PLANE_EXPLICIT(created, image_plane, src) + created.pixel_x = image_pixel_x + created.pixel_y = image_pixel_y + if(image_color) + created.color = image_color + return created + +/// Shows the image we generated to the passed mob +/obj/effect/client_image_holder/proc/show_image_to(mob/show_to) + SIGNAL_HANDLER + + show_to.client?.images |= shown_image + +/// Hides the image we generated from the passed mob +/obj/effect/client_image_holder/proc/hide_image_from(mob/hide_from) + SIGNAL_HANDLER + + hide_from.client?.images -= shown_image + +/// Simple helper for refreshing / showing the image to everyone in our list. +/obj/effect/client_image_holder/proc/regenerate_image() + for(var/mob/seer as anything in who_sees_us) + hide_image_from(seer) + + shown_image = generate_image() + + for(var/mob/seer as anything in who_sees_us) + show_image_to(seer) + +// Whenever we perform icon updates, regenerate our image +/obj/effect/client_image_holder/update_icon(updates = ALL) + . = ..() + regenerate_image() + +// If we move for some reason, regenerate our image +/obj/effect/client_image_holder/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) + . = ..() + if(!loc) + return + regenerate_image() + +/obj/effect/client_image_holder/singularity_pull() + return + +/obj/effect/client_image_holder/singularity_act() + return diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm index f16f77bb016..d5417f35dca 100644 --- a/code/modules/mob/living/carbon/brain/brain.dm +++ b/code/modules/mob/living/carbon/brain/brain.dm @@ -39,6 +39,13 @@ CRASH("Brainmob without container.") forceMove(container) +/mob/living/carbon/brain/update_mouse_pointer() + if (!client) + return + client.mouse_pointer_icon = initial(client.mouse_pointer_icon) + if(!container) + return + /* This will return true if the brain has a container that leaves it less helpless than a naked brain diff --git a/code/modules/mob/living/simple_animal/gondolas/gondola.dm b/code/modules/mob/living/simple_animal/gondolas/gondola.dm new file mode 100644 index 00000000000..e12dbe4e15a --- /dev/null +++ b/code/modules/mob/living/simple_animal/gondolas/gondola.dm @@ -0,0 +1,74 @@ +#define GONDOLA_HEIGHT pick(list("gondola_body_long", "gondola_body_medium", "gondola_body_short")) +#define GONDOLA_COLOR pick(list("A87855", "915E48", "683E2C")) +#define GONDOLA_MOUSTACHE pick(list("gondola_moustache_large", "gondola_moustache_small")) +#define GONDOLA_EYES pick(list("gondola_eyes_close", "gondola_eyes_far")) + +/mob/living/simple_animal/pet/gondola + name = "gondola" + real_name = "gondola" + desc = "Гондола — бесшумный ходок. \ + Не имея рук, он воплощает даосский принцип у-вэй (недействие), а его улыбающееся \ + выражение лица показывает его полное и полное принятие мира таким, какой он есть." + icon = 'icons/mob/gondolas.dmi' + icon_state = "gondola" + icon_living = "gondola" + + maxHealth = 200 + health = 200 + faction = list("gandola") + response_help = "pets" + response_disarm = "bops" + response_harm = "kicks" + + //Gondolas aren't affected by cold. + unsuitable_atmos_damage = 0 + del_on_death = TRUE + + ///List of loot drops on death, since it deletes itself on death (like trooper). + loot = list( + /obj/effect/decal/cleanable/blood/gibs = 1, + ) + + ru_names = list( + NOMINATIVE = "гандола", + GENITIVE = "гандолы", + DATIVE = "гандоле", + ACCUSATIVE = "гандолу", + INSTRUMENTAL = "гандолой", + PREPOSITIONAL = "гандоле" + ) + + +/mob/living/simple_animal/pet/gondola/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_MUTE, INNATE_TRAIT) + create_gondola() + +/mob/living/simple_animal/pet/gondola/proc/create_gondola() + icon_state = null + icon_living = null + var/height = GONDOLA_HEIGHT + var/mutable_appearance/body_overlay = mutable_appearance(icon, height) + var/mutable_appearance/eyes_overlay = mutable_appearance(icon, GONDOLA_EYES) + var/mutable_appearance/moustache_overlay = mutable_appearance(icon, GONDOLA_MOUSTACHE) + body_overlay.color = ("#[GONDOLA_COLOR]") + + //Offset the face to match the Gondola's height. + switch(height) + if("gondola_body_medium") + eyes_overlay.pixel_y = -4 + moustache_overlay.pixel_y = -4 + if("gondola_body_short") + eyes_overlay.pixel_y = -8 + moustache_overlay.pixel_y = -8 + + cut_overlays(TRUE) + add_overlay(body_overlay) + add_overlay(eyes_overlay) + add_overlay(moustache_overlay) + + +#undef GONDOLA_HEIGHT +#undef GONDOLA_COLOR +#undef GONDOLA_MOUSTACHE +#undef GONDOLA_EYES diff --git a/code/modules/mob/living/simple_animal/gondolas/gondolapod.dm b/code/modules/mob/living/simple_animal/gondolas/gondolapod.dm new file mode 100644 index 00000000000..496605b4920 --- /dev/null +++ b/code/modules/mob/living/simple_animal/gondolas/gondolapod.dm @@ -0,0 +1,95 @@ +/mob/living/simple_animal/pet/gondola/gondolapod + name = "gondola" + real_name = "gondola" + desc = "Бесшумный ходок. Кажется, это сотрудник агентства доставки." + icon = 'icons/obj/supplypods.dmi' + icon_state = "gondola" + icon_living = "gondola" + SET_BASE_PIXEL(-16, -5) //2x2 sprite + layer = TABLE_LAYER //so that deliveries dont appear underneath it + + ///Boolean on whether the pod is currently open, and should appear such. + var/opened = FALSE + ///The supply pod attached to the gondola, that actually holds the contents of our delivery. + var/obj/structure/closet/supplypod/centcompod/linked_pod + + ///Static list of actions the gondola is given on creation, and taken away when it successfully delivers. + var/static/list/gondola_delivering_actions = list( + /datum/action/innate/deliver_gondola_package, + /datum/action/innate/check_gondola_contents, + ) + +/mob/living/simple_animal/pet/gondola/gondolapod/Initialize(mapload, pod) + linked_pod = pod || new(src) + name = linked_pod.name + desc = linked_pod.desc + if(!linked_pod.stay_after_drop || !linked_pod.opened) + grant_actions_by_list(gondola_delivering_actions) + return ..() + +/mob/living/simple_animal/pet/gondola/gondolapod/death(gibbed) + QDEL_NULL(linked_pod) //Will cause the open() proc for the linked supplypod to be called with the "broken" parameter set to true, meaning that it will dump its contents on death + return ..() + +/mob/living/simple_animal/pet/gondola/gondolapod/create_gondola() + return + +/mob/living/simple_animal/pet/gondola/gondolapod/update_overlays() + . = ..() + if(opened) + . += "[icon_state]_open" + +/mob/living/simple_animal/pet/gondola/gondolapod/examine(mob/user) + . = ..() + if (contents.len) + . += span_notice("Похоже, посылка еще не доставлена.") + else + . += span_notice("Судя по всему, доставку уже осуществили.") + +/mob/living/simple_animal/pet/gondola/gondolapod/setOpened() + opened = TRUE + layer = initial(layer) + update_appearance() + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom/, setClosed)), 5 SECONDS) + +/mob/living/simple_animal/pet/gondola/gondolapod/setClosed() + opened = FALSE + layer = OBJ_LAYER + update_appearance() + +///Opens the gondola pod and delivers its package, one-time use as it removes all delivery-related actions. +/datum/action/innate/deliver_gondola_package + name = "Доставить" + desc = "Откройте хранилище и освободите все содержимое, хранящееся внутри." + button_icon_state = "arrow" + +/datum/action/innate/deliver_gondola_package/Trigger(left_click) + . = ..() + if(!.) + return + + var/mob/living/simple_animal/pet/gondola/gondolapod/gondola_owner = owner + gondola_owner.linked_pod.open_pod(gondola_owner, forced = TRUE) + for(var/datum/action/actions as anything in gondola_owner.actions) + if(actions.type in gondola_owner.gondola_delivering_actions) + actions.Remove(gondola_owner) + return TRUE + +///Checks the contents of the gondola and lets them know what they're holding. +/datum/action/innate/check_gondola_contents + name = "Проверить содержимое" + desc = "Посмотрите, сколько предметов вы сейчас держите в капсуле." + button_icon_state = "storage" + +/datum/action/innate/check_gondola_contents/Trigger(left_click) + . = ..() + if(!.) + return + + var/mob/living/simple_animal/pet/gondola/gondolapod/gondola_owner = owner + var/total = gondola_owner.contents.len + if (total) + to_chat(gondola_owner, span_notice("You detect [total] object\s within your incredibly vast belly.")) + else + to_chat(gondola_owner, span_notice("A closer look inside yourself reveals... nothing.")) + return TRUE diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index ed9aa8183cb..5c48e96a273 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1001,6 +1001,17 @@ SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT) sync_lighting_plane_alpha() +///Update the mouse pointer of the attached client in this mob +/mob/proc/update_mouse_pointer() + if(!client) + return + + if(client.mouse_pointer_icon != initial(client.mouse_pointer_icon))//only send changes to the client if theyre needed + client.mouse_pointer_icon = initial(client.mouse_pointer_icon) + + if(client.mouse_override_icon) + client.mouse_pointer_icon = client.mouse_override_icon + /mob/proc/set_vision_override(datum/vision_override/O) QDEL_NULL(vision_type) if(O) //in case of null diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 075c44d9ffd..fd397aea8e3 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -850,3 +850,14 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM return FALSE return TRUE + +/// Takes in an associated list (key `/datum/action` typepaths, value is the AI blackboard key) and handles granting the action and adding it to the mob's AI controller blackboard. +/// This is only useful in instances where you don't want to store the reference to the action on a variable on the mob. +/mob/proc/grant_actions_by_list(list/input) + if(length(input) <= 0) + return + + for(var/action in input) + var/datum/action/ability = new action(src) + ability.Grant(src) + diff --git a/code/modules/projectiles/firing.dm b/code/modules/projectiles/firing.dm index d17d0e9141e..dbd7faf36b9 100644 --- a/code/modules/projectiles/firing.dm +++ b/code/modules/projectiles/firing.dm @@ -18,6 +18,7 @@ user.changeNext_move(CLICK_CD_RANGE) user.newtonian_move(get_dir(target, user)) update_icon() + SEND_SIGNAL(src, COMSIG_FIRE_CASING, target, user, firer_source_atom, randomspread, spread, zone_override, params, distro) return TRUE @@ -78,7 +79,7 @@ * If the user is holding a weapon in telekinesis grab, * use a starting location from the firer source */ - var/fire_from_tk_grab = !isnull(firer_source_atom) && user.tkgrabbed_objects[firer_source_atom] + var/fire_from_tk_grab = !isnull(firer_source_atom) && ismob(user) && user.tkgrabbed_objects[firer_source_atom] if (fire_from_tk_grab) curloc = get_turf(firer_source_atom) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index cbbc427c866..ffd8adfc77d 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -287,6 +287,10 @@ return FALSE prehit(bumped_atom) + if(HAS_TRAIT(src, TRAIT_SHRAPNEL)) + bumped_atom.hitby(src, TRUE) + qdel(src) + var/permutation = bumped_atom.bullet_act(src, def_zone) // searches for return value, could be deleted after run so check A isn't null if(permutation == -1 || forcedodge)// the bullet passes through a dense object! if(forcedodge > 0) @@ -393,7 +397,7 @@ Angle = round(get_angle(src, current)) if(spread) Angle += (rand() - 0.5) * spread - if(firer) + if(firer && ismob(firer)) hit_crawling_mobs_chance = firer.a_intent == INTENT_HELP ? 0 : 100 // Turn right away var/matrix/M = new diff --git a/code/modules/projectiles/projectile/shrapnel.dm b/code/modules/projectiles/projectile/shrapnel.dm new file mode 100644 index 00000000000..15b004b4b4b --- /dev/null +++ b/code/modules/projectiles/projectile/shrapnel.dm @@ -0,0 +1,28 @@ +/obj/item/projectile/shrapnel + name = "shrapnel" + icon = 'icons/obj/shards.dmi' + throwforce = 14 + throw_speed = EMBED_THROWSPEED_THRESHOLD + embed_chance = 100 + embedded_fall_chance = 0 + w_class = WEIGHT_CLASS_SMALL + sharp = TRUE + damage = 14 + range = 20 + dismemberment = 5 + ricochets_max = 2 + ricochet_chance = 70 + hitsound = 'sound/weapons/pierce.ogg' + ru_names = list( + NOMINATIVE = "шрапнель", + GENITIVE = "шрапнели", + DATIVE = "шрапнели", + ACCUSATIVE = "шрапнель", + INSTRUMENTAL = "шрапнелью", + PREPOSITIONAL = "шрапнели" + ) + +/obj/item/projectile/shrapnel/Initialize(mapload) + . = ..() + icon_state = pick("shrapnel1", "shrapnel2", "shrapnel3") + ADD_TRAIT(src, TRAIT_SHRAPNEL, INNATE_TRAIT) diff --git a/icons/effects/mouse_pointers/supplypod_down_target.dmi b/icons/effects/mouse_pointers/supplypod_down_target.dmi new file mode 100644 index 0000000000000000000000000000000000000000..53a3bee0a78720f6750cf0cb67b71007140a1a53 GIT binary patch literal 464 zcmV;>0WbcEP)`6wG2eNIUQtuJt*@h&n2LOUwjeY`p+*A$0004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRL zOex6#a?DJ)I5Sc+(=$pSoZ^zil2jm5DKRHUiHkEOv#1!zGvwk-D@x2wg|L+sT>V_Y zh5`Wj1Q|{|dwkUZ0087kL_t(YiS5%}4a6V}0AMU&VHRqk7O+qYwSa|LzycN!b>$~_ z$&HmUa@os~>|yCQ`j;8=<71b>(-qj!1q!fc+pKnh1^|q~9CvoR0|1BtJzD2nH^T@3 zGclvz5l=FVKuZyVmn=#R3djVb#0B)nFami>dx+kL9lP7s0F*W*L5v}mGLIjt020VU zjG+j`!v$AB7BVFfD9I)P5Yb1VO#DlXK}rQMQLeA~8PJL(VrjL=eis8EB@#dpH$Yuh zoffp$N$^%@v1_3Iyel9#sgefFDZ*Bkp zc$`yKaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM;w;ZhDainG%uKjAGg33tGfE(w;*!LY zR3KAHiHkEOv#1!zH00t;D@x2wg|L+sT>V_YCISGQz!()WHs0v~004YRL_t(YiS3lp z4S+BRL|NfhUzKnySHQRJ=z0=>4=@UQ#HuB3*wJplYTHJOxOZ#z-v>Y*HK3 z%>x3(!S*&V8E~(GJ7y~hh{MB@1Zq{w5y46VC)Opf_NJ7b^%lTa!QUj`O@5+;p6V7a ii+|ls^!YE>MQQ*ku^!R&cE#WT0000L*^!tYI%}V;et{}+R z-d5A>n5DKYP?oVI$S;_|;n|HeASb0NB%;J6wK%ybv!En1KaYW-Voq>aK~d@VFTn*L zzdq6O*3~+9=6vvmP=kxc4<6~9_t8AbP;|y;hlO#F@nvH#g*lHV9hnrO5bW96ZLGR^ zg~SPyCy#uzz0UZyZkQ?>^Ec*z8WY2u0}`S}X7^qK?aT9YaSZY3d^_bJ?*RoK=Dkhf zC%7UHYH#?j#kw^lw_Y*ms?s~=P45`hm?CNfFP*vDBO|)(z}oj`9y_gmrn5q<%*By$ z%WWayZ=VC1RN@vbUYUj#%9bZrXoy)7aQSM?! Sq}+R;%?zHdelF{r5}E+-8i7;* literal 0 HcmV?d00001 diff --git a/icons/effects/mouse_pointers/supplypod_target.dmi b/icons/effects/mouse_pointers/supplypod_target.dmi new file mode 100644 index 0000000000000000000000000000000000000000..94401d7a8ae960a33faa3f11682e89d0556d76e7 GIT binary patch literal 392 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%0AGKuV;7-nq3% z`x|X5))E;jF4gmC@>5EBenMn3B_bgDaPUy#%}-GW?}GfPj|u$r?ag+oK+ec0&vdQx z_3^}di5NPzU96JcE4&bbU<7r395Gb5fpZFgwp&P0wl{1aY zTW|7vdqIpu1g|tp42_kV?uJ&YB@+alHINKt-nk9%M?${m57RAUQ3M@wqHrR8&Cn_N zzz7}sB)KG=dsh{=8FD4B)>I^BG;z&^5JM4h)u;k;Zyy~Fr;wd(*%3LD(!cb~=

m(U&7!6uqx>l=3&gNz4~d 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