diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 28ec31372b6..839b62b0058 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,18 +4,6 @@ # In the event that multiple org members are to be informed of changes # to the same file or dir, add them to the end under Multiple Owners -# bobbahbrown -/code/datums/chatmessage.dm @bobbahbrown - -# ChangelingRain - -/code/__DEFINES/clockcult.dm @ChangelingRain -/code/game/gamemodes/blob/ @ChangelingRain -/code/game/gamemodes/clock_cult/ @ChangelingRain -/code/game/gamemodes/miniantags/revenant/ @ChangelingRain -/code/game/objects/effects/temporary_visuals/ @ChangelingRain -/code/modules/reagents/chemistry/reagents/blob_reagents.dm @ChangelingRain - # Cobby /code/modules/reagents/ @ExcessiveUseOfCobblestone /code/modules/research/designs/medical_designs.dm @ExcessiveUseOfCobblestone @@ -26,9 +14,6 @@ # Cyberboss -/code/__DATASTRUCTURES/globals.dm @Cyberboss -/code/__DEFINES/server_tools.config.dm @Cyberboss -/code/__DEFINES/server_tools.dm @Cyberboss /code/controllers/subsystem/atoms.dm @Cyberboss /code/controllers/subsystem/mapping.dm @Cyberboss /code/controllers/globals.dm @Cyberboss @@ -38,14 +23,8 @@ /code/datums/holocall.dm @Cyberboss /code/modules/admin/verbs/adminhelp.dm @Cyberboss /code/modules/admin/verbs/adminpm.dm @Cyberboss -/code/modules/server_tools/ @Cyberboss /code/modules/mapping/ @Cyberboss -# duncathan - -/code/__DEFINES/atmospherics.dm @duncathan -/code/modules/atmospherics/ @duncathan - # Jordie0608 /SQL/ @Jordie0608 @@ -56,7 +35,6 @@ /SQL/database_changelog.txt @MrStonedOne /code/__DEFINES/MC.dm @MrStonedOne -/code/__DEFINES/tick.dm @MrStonedOne /code/controllers/admin.dm @MrStonedOne /code/controllers/master.dm @MrStonedOne /code/controllers/failsafe.dm @MrStonedOne @@ -82,14 +60,9 @@ /tgui @stylemistake -# Qustinnus -/code/datums/components/mood.dm @Qustinnus -/code/datums/mood_events/ @Qustinnus -/code/__DEFINES/mobs.dm @Qustinnus - # Multiple Owners -/code/controllers/subsystem/air.dm @duncathan @MrStonedOne +/code/controllers/subsystem/air.dm @MrStonedOne #SIC SEMPER TYRANNIS /code/modules/hydroponics/grown/citrus.dm @optimumtact diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index b3ad68c1d96..3adca87c622 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -324,7 +324,6 @@ }, /obj/item/reagent_containers/dropper, /obj/effect/turf_decal/trimline/yellow/filled/corner{ - icon_state = "trimline_corner_fill"; dir = 8 }, /obj/effect/turf_decal/tile/yellow, @@ -62708,18 +62707,14 @@ /obj/effect/turf_decal/stripes/line{ dir = 9 }, -/obj/machinery/field/generator{ - anchored = 1 - }, +/obj/machinery/field/generator/anchored, /turf/open/floor/plating/airless, /area/space/nearstation) "clT" = ( /obj/effect/turf_decal/stripes/line{ dir = 5 }, -/obj/machinery/field/generator{ - anchored = 1 - }, +/obj/machinery/field/generator/anchored, /turf/open/floor/plating/airless, /area/space/nearstation) "clU" = ( @@ -68666,18 +68661,14 @@ /obj/effect/turf_decal/stripes/line{ dir = 10 }, -/obj/machinery/field/generator{ - anchored = 1 - }, +/obj/machinery/field/generator/anchored, /turf/open/floor/plating/airless, /area/space/nearstation) "cxB" = ( /obj/effect/turf_decal/stripes/line{ dir = 6 }, -/obj/machinery/field/generator{ - anchored = 1 - }, +/obj/machinery/field/generator/anchored, /turf/open/floor/plating/airless, /area/space/nearstation) "cxD" = ( @@ -92735,8 +92726,7 @@ pixel_y = 9 }, /obj/item/storage/box/monkeycubes{ - pixel_x = 4; - pixel_y = 0 + pixel_x = 4 }, /obj/item/storage/pill_bottle/mutadone{ pixel_x = -8; @@ -96447,7 +96437,6 @@ /area/medical/chemistry) "dAV" = ( /obj/machinery/newscaster{ - pixel_x = 0; pixel_y = -32 }, /obj/structure/disposalpipe/segment{ @@ -99022,7 +99011,6 @@ dir = 1 }, /obj/effect/turf_decal/trimline/yellow/filled/corner{ - icon_state = "trimline_corner_fill"; dir = 8 }, /turf/open/floor/plasteel/white, @@ -112732,7 +112720,6 @@ }, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/trimline/yellow/filled/warning{ - icon_state = "trimline_warn_fill"; dir = 8 }, /obj/structure/cable, @@ -114830,8 +114817,7 @@ icon_state = "plant-21" }, /obj/structure/sign/warning/bodysposal{ - pixel_x = 32; - pixel_y = 0 + pixel_x = 32 }, /turf/open/floor/plasteel, /area/hallway/primary/aft) @@ -115447,9 +115433,7 @@ }, /obj/effect/turf_decal/tile/yellow, /obj/machinery/power/apc{ - dir = 2; name = "Chemistry APC"; - pixel_x = 0; pixel_y = -23 }, /obj/structure/cable, diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 424515d4deb..b90b2c9a65b 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -4965,6 +4965,20 @@ }, /turf/open/floor/plasteel/dark, /area/security/brig) +"akV" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/bounty_board{ + dir = 1; + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/dorms) "akW" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/door/airlock/security/glass{ @@ -8098,10 +8112,6 @@ }, /turf/open/floor/plasteel, /area/security/prison) -"asx" = ( -/obj/structure/door_assembly/door_assembly_mai, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "asy" = ( /obj/machinery/door/airlock/maintenance{ name = "Firefighting Equipment"; @@ -10878,10 +10888,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/hydroponics/garden) -"azr" = ( -/obj/structure/grille/broken, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "azs" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 @@ -11096,16 +11102,6 @@ }, /turf/open/floor/plasteel, /area/quartermaster/miningdock) -"azV" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/dorms) "azW" = ( /turf/open/floor/plasteel, /area/ai_monitored/storage/eva) @@ -11295,22 +11291,12 @@ /obj/structure/cable, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"aAq" = ( -/obj/machinery/atmospherics/components/unary/tank/air{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) -"aAr" = ( -/obj/structure/closet, -/obj/effect/decal/cleanable/cobweb, -/obj/effect/spawner/lootdrop/maintenance, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "aAs" = ( -/obj/structure/closet, -/obj/effect/spawner/lootdrop/maintenance/two, -/turf/open/floor/plating, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/plasteel, /area/maintenance/starboard/fore) "aAt" = ( /obj/machinery/door/poddoor/preopen{ @@ -11772,24 +11758,23 @@ /area/crew_quarters/toilet) "aBB" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/closed/wall, -/area/maintenance/starboard/fore) -"aBC" = ( -/obj/machinery/door/airlock/maintenance{ - req_access_txt = "12" +/obj/machinery/bounty_board{ + dir = 4; + pixel_x = 32 }, +/turf/open/floor/plastic, +/area/hallway/secondary/service) +"aBC" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) -"aBD" = ( -/obj/machinery/meter, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 8 +/obj/machinery/door/airlock{ + name = "Service Hall"; + req_one_access_txt = "22;25;26;28;35;37;38;46;70" }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/machinery/door/firedoor, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aBE" = ( /obj/item/clothing/under/misc/mailman, /obj/item/clothing/head/mailman, @@ -12138,28 +12123,16 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/crew_quarters/fitness) -"aCx" = ( -/obj/machinery/atmospherics/components/binary/valve, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) -"aCy" = ( -/obj/effect/decal/cleanable/oil, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "aCz" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, /obj/structure/cable, +/obj/structure/railing, /turf/open/floor/plating, /area/maintenance/starboard/fore) "aCA" = ( -/obj/structure/grille/broken, -/obj/structure/window{ - dir = 4 - }, -/obj/structure/window, /obj/structure/cable, +/obj/structure/railing, +/obj/effect/spawner/lootdrop/maintenance, +/obj/structure/closet, /turf/open/floor/plating{ icon_state = "panelscorched" }, @@ -12736,22 +12709,10 @@ /obj/structure/cable, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet) -"aDV" = ( -/obj/machinery/meter, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) -"aDW" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "aDX" = ( -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/modular_computer/console/preset/civilian{ + dir = 4 + }, /turf/open/floor/plating, /area/maintenance/starboard/fore) "aDY" = ( @@ -12785,18 +12746,18 @@ /turf/open/floor/plating, /area/maintenance/starboard/fore) "aEb" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Theatre Maintenance"; - req_access_txt = "46" - }, /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/machinery/door/airlock{ + name = "Service Hall"; + req_one_access_txt = "22;25;26;28;35;37;38;46;70" + }, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aEc" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -13032,8 +12993,8 @@ dir = 4 }, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aEB" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 4 @@ -13344,10 +13305,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"aFn" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "aFo" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -13934,8 +13891,8 @@ }, /obj/machinery/atmospherics/pipe/manifold4w/supply/hidden, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aGz" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -13945,8 +13902,15 @@ dir = 4 }, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/table, +/obj/item/circuitboard/machine/vendatray, +/obj/item/circuitboard/machine/vendatray, +/obj/item/camera, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aGA" = ( /obj/structure/disposalpipe/sorting/mail{ dir = 4; @@ -13956,8 +13920,9 @@ dir = 1 }, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/effect/turf_decal/trimline/brown/filled/line, +/turf/open/floor/wood, +/area/hallway/secondary/service) "aGB" = ( /obj/structure/disposalpipe/sorting/mail{ dir = 4; @@ -13967,8 +13932,8 @@ dir = 1 }, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "aGC" = ( /obj/machinery/button/door{ id = "xenobio5"; @@ -14048,8 +14013,8 @@ dir = 4 }, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aGJ" = ( /obj/structure/bed, /obj/effect/spawner/lootdrop/prison_contraband, @@ -14134,18 +14099,24 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock{ + name = "Service Hall"; + req_one_access_txt = "22;25;26;28;35;37;38;46;70" + }, /turf/open/floor/plating, -/area/maintenance/starboard/fore) +/area/hallway/secondary/service) "aGQ" = ( /obj/structure/disposalpipe/segment{ dir = 10 }, +/obj/structure/cable, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/structure/cable, /turf/open/floor/plating, /area/maintenance/starboard/fore) "aGR" = ( @@ -14589,16 +14560,16 @@ /area/hallway/primary/central) "aHS" = ( /obj/structure/disposalpipe/segment, -/obj/machinery/door/airlock/maintenance{ - name = "Bar Storage Maintenance"; - req_access_txt = "25" - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/machinery/door/airlock{ + name = "Bar Service Hall"; + req_one_access_txt = "25" + }, +/turf/open/floor/wood, +/area/hallway/secondary/service) "aHT" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -14651,8 +14622,9 @@ /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/effect/turf_decal/trimline/white/line, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "aHZ" = ( /obj/machinery/airalarm{ dir = 4; @@ -14676,40 +14648,42 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/effect/turf_decal/trimline/green/line, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aIb" = ( -/obj/machinery/power/apc{ - areastring = "/area/crew_quarters/theatre"; - dir = 8; - name = "Theatre APC"; - pixel_x = -25 - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 }, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/machinery/rnd/production/techfab/department/service, +/obj/machinery/camera{ + c_tag = "Service Hallway West"; + dir = 4 + }, +/obj/effect/turf_decal/trimline/green/line, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aIc" = ( /obj/machinery/power/apc{ areastring = "/area/crew_quarters/bar"; name = "Bar APC"; pixel_y = -23 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/effect/turf_decal/trimline/green/line, +/obj/item/kirbyplants/fullysynthetic, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aId" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/effect/turf_decal/trimline/green/line, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "aIe" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -14722,8 +14696,9 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/effect/turf_decal/trimline/white/line, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "aIg" = ( /obj/machinery/navbeacon{ codes_txt = "delivery;dir=2"; @@ -14747,8 +14722,10 @@ dir = 4 }, /obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/effect/turf_decal/trimline/white/line, +/obj/item/kirbyplants/fullysynthetic, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "aIi" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 @@ -14760,8 +14737,10 @@ dir = 4; sortType = 21 }, -/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, /turf/open/floor/plating, /area/maintenance/starboard/fore) "aIk" = ( @@ -15307,14 +15286,16 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet) "aJA" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Kitchen Maintenance"; - req_access_txt = "28" - }, /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock{ + name = "Kitchen Service Hall"; + req_access_txt = "28"; + req_one_access_txt = null + }, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "aJB" = ( /obj/structure/disposalpipe/segment, /obj/machinery/door/airlock/maintenance{ @@ -25979,15 +25960,6 @@ /obj/structure/closet/wardrobe/black, /turf/open/floor/plating, /area/maintenance/central) -"bjD" = ( -/obj/machinery/door/airlock{ - name = "Service Hall"; - req_one_access_txt = "22;25;26;28;35;37;38;46;70" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable, -/turf/open/floor/plating, -/area/hallway/secondary/service) "bjE" = ( /obj/machinery/airalarm{ dir = 4; @@ -26218,14 +26190,19 @@ /turf/open/floor/plasteel/dark, /area/medical/morgue) "bke" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Bar Maintenance"; - req_one_access_txt = "12;25;26;35;28;22;37;46;38;70" - }, /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/machinery/door/airlock{ + name = "Service Hall"; + req_one_access_txt = "22;25;26;28;35;37;38;46;70" + }, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/turf_decal/tile/bar, +/obj/machinery/door/firedoor, +/turf/open/floor/plasteel, +/area/hallway/secondary/service) "bkf" = ( /obj/machinery/light/small{ dir = 4 @@ -33808,20 +33785,6 @@ }, /turf/closed/wall, /area/quartermaster/miningdock) -"bBI" = ( -/obj/machinery/power/apc{ - areastring = "/area/hallway/secondary/service"; - dir = 1; - name = "Service Hall APC"; - pixel_y = 23 - }, -/obj/structure/cable, -/obj/machinery/bounty_board{ - dir = 8; - pixel_x = -32 - }, -/turf/open/floor/plasteel, -/area/hallway/secondary/service) "bBK" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -37294,7 +37257,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/open/floor/plating/asteroid/snow/icemoon, +/turf/open/transparent/openspace/icemoon, /area/icemoon/surface/outdoors) "bKt" = ( /obj/structure/table, @@ -37442,7 +37405,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/plating/asteroid/snow/icemoon, +/turf/open/transparent/openspace/icemoon, /area/icemoon/surface/outdoors) "bKL" = ( /obj/structure/disposalpipe/segment{ @@ -50690,6 +50653,10 @@ }, /turf/open/floor/plasteel, /area/science/xenobiology) +"cSk" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "cSz" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -51110,6 +51077,27 @@ }, /turf/open/floor/plasteel/white, /area/science/lab) +"dlp" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/turf_decal/stripes/white/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/filled/corner, +/turf/open/floor/wood, +/area/hallway/secondary/service) +"dlx" = ( +/obj/structure/punching_bag, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/fore) "dni" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -51297,6 +51285,10 @@ "dGF" = ( /turf/closed/wall/r_wall, /area/science/mixing/chamber) +"dHJ" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/space/basic, +/area/maintenance/starboard/fore) "dHL" = ( /obj/machinery/suit_storage_unit/cmo, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -51323,6 +51315,10 @@ }, /turf/open/floor/plasteel/white, /area/science/mixing) +"dJS" = ( +/obj/structure/sign/poster/official/random, +/turf/closed/wall, +/area/hallway/secondary/service) "dMb" = ( /obj/effect/turf_decal/tile/brown{ dir = 8 @@ -51476,6 +51472,12 @@ }, /turf/open/floor/engine, /area/science/misc_lab) +"ezU" = ( +/obj/item/clothing/gloves/boxing/green, +/obj/structure/rack, +/obj/item/reagent_containers/food/drinks/waterbottle, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "eAi" = ( /obj/structure/table, /obj/item/stack/package_wrap, @@ -51492,6 +51494,14 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/vacant_room/commissary) +"eAT" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "eFD" = ( /obj/structure/table/glass, /obj/item/storage/box/disks{ @@ -51650,16 +51660,9 @@ /turf/open/floor/plasteel, /area/science/mixing) "fnC" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 - }, -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -23 - }, -/obj/structure/cable, -/turf/open/floor/plasteel, -/area/hallway/secondary/service) +/obj/effect/decal/cleanable/ash, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "fpR" = ( /obj/machinery/door/window/northleft{ base_state = "right"; @@ -51763,6 +51766,17 @@ }, /turf/open/floor/plasteel/grimy, /area/security/detectives_office) +"fCu" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) +"fDD" = ( +/obj/item/assembly/mousetrap, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "fGg" = ( /obj/effect/turf_decal/tile/blue{ dir = 8 @@ -51813,6 +51827,10 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /turf/open/floor/plasteel/white, /area/medical/medbay) +"fPh" = ( +/obj/structure/sign/painting/library, +/turf/closed/wall, +/area/hallway/secondary/service) "fQA" = ( /obj/machinery/airalarm{ dir = 4; @@ -51965,6 +51983,12 @@ "gjl" = ( /turf/closed/wall, /area/quartermaster/warehouse) +"gjD" = ( +/obj/structure/window, +/obj/structure/rack, +/obj/item/assembly/signaler, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "gkC" = ( /obj/structure/closet/l3closet/virology, /obj/effect/turf_decal/stripes/line{ @@ -51997,6 +52021,19 @@ }, /turf/open/floor/plasteel, /area/science/nanite) +"goT" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + dir = 8 + }, +/turf/open/floor/wood, +/area/hallway/secondary/service) "gpE" = ( /obj/structure/table/wood, /obj/item/book/manual/wiki/security_space_law, @@ -52164,6 +52201,12 @@ "gQb" = ( /turf/closed/mineral/random/snow/no_caves, /area/icemoon/surface/outdoors/unexplored/rivers/no_monsters) +"gQz" = ( +/obj/machinery/firealarm{ + pixel_y = 24 + }, +/turf/open/floor/wood, +/area/hallway/secondary/service) "gUV" = ( /obj/machinery/computer/crew{ dir = 4 @@ -52247,6 +52290,19 @@ dir = 5 }, /area/science/research) +"hxq" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/turf_decal/stripes/white/line{ + dir = 4 + }, +/turf/open/floor/wood, +/area/hallway/secondary/service) "hxs" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -52460,11 +52516,29 @@ }, /turf/open/floor/plasteel/white, /area/science/xenobiology) +"iiv" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable, +/obj/machinery/power/apc{ + areastring = "/area/crew_quarters/theatre"; + dir = 8; + name = "Theatre APC"; + pixel_x = -25 + }, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "ijc" = ( /obj/structure/table, /obj/item/stack/sheet/metal/fifty, /turf/open/floor/plasteel/dark, /area/engine/engineering) +"ijI" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/wood, +/area/hallway/secondary/service) "ink" = ( /obj/effect/turf_decal/tile/purple{ dir = 8 @@ -52524,6 +52598,12 @@ }, /turf/open/floor/plasteel/white, /area/medical/surgery) +"iyi" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall, +/area/maintenance/starboard/fore) "izT" = ( /obj/structure/closet/crate{ icon_state = "crateopen" @@ -52531,6 +52611,12 @@ /obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plasteel, /area/quartermaster/office) +"izV" = ( +/obj/machinery/newscaster{ + pixel_y = -32 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "iBZ" = ( /obj/machinery/power/smes, /obj/structure/cable, @@ -53026,14 +53112,6 @@ }, /turf/open/floor/plating, /area/maintenance/aft) -"khb" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, -/obj/structure/table, -/obj/item/kitchen/rollingpin, -/turf/open/floor/plasteel, -/area/hallway/secondary/service) "khB" = ( /obj/machinery/door/airlock/external{ req_access_txt = "13" @@ -53351,10 +53429,11 @@ /turf/open/floor/plasteel/white, /area/science/mixing) "kPd" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/structure/cable, -/turf/open/floor/plasteel, -/area/hallway/secondary/service) +/obj/machinery/light/small, +/obj/item/trash/can, +/mob/living/simple_animal/mouse/white, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "kPH" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -53445,6 +53524,12 @@ }, /turf/open/floor/plasteel, /area/vacant_room/commissary) +"kWH" = ( +/obj/effect/turf_decal/stripes/white/line{ + dir = 8 + }, +/turf/open/floor/wood, +/area/hallway/secondary/service) "kXf" = ( /obj/structure/window/reinforced{ dir = 1 @@ -53638,6 +53723,14 @@ }, /turf/open/floor/plasteel/dark, /area/science/genetics) +"lHi" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable, +/obj/structure/railing, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "lHR" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -53933,6 +54026,9 @@ }, /turf/closed/wall, /area/medical/morgue) +"myW" = ( +/turf/open/floor/plastic, +/area/hallway/secondary/service) "mBm" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -53963,6 +54059,12 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"mEX" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/fore) "mFt" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -55058,6 +55160,13 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engine_smes) +"pAz" = ( +/obj/structure/marker_beacon{ + icon_state = "markerburgundy-on" + }, +/obj/structure/fluff/fokoff_sign, +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors) "pAR" = ( /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ @@ -55165,6 +55274,10 @@ }, /turf/open/floor/plasteel/dark, /area/science/nanite) +"pKr" = ( +/obj/structure/fermenting_barrel, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "pLn" = ( /obj/machinery/conveyor/inverted{ dir = 5; @@ -55209,6 +55322,16 @@ }, /turf/open/floor/plasteel/white, /area/science/genetics) +"pOR" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "pPs" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -55355,6 +55478,12 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/lobby) +"qkI" = ( +/obj/effect/turf_decal/stripes/white/line{ + dir = 4 + }, +/turf/open/floor/wood, +/area/hallway/secondary/service) "qnW" = ( /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ @@ -55422,6 +55551,9 @@ }, /turf/open/floor/plating, /area/science/xenobiology) +"qzO" = ( +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "qDH" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 10 @@ -55450,6 +55582,18 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/security/detectives_office) +"qMc" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable, +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -23 + }, +/obj/structure/table, +/obj/item/toner/large, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "qQC" = ( /obj/machinery/portable_atmospherics/canister, /obj/effect/turf_decal/bot, @@ -55482,6 +55626,12 @@ /obj/structure/cable, /turf/open/floor/plating, /area/engine/engine_smes) +"rfI" = ( +/obj/item/pressure_plate, +/obj/item/pressure_plate, +/obj/structure/rack, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "rgu" = ( /obj/effect/turf_decal/trimline/green/filled/line, /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -55529,6 +55679,12 @@ }, /turf/open/floor/engine, /area/science/xenobiology) +"rrd" = ( +/obj/machinery/newscaster{ + pixel_y = 32 + }, +/turf/open/floor/wood, +/area/hallway/secondary/service) "ruy" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -55721,6 +55877,17 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"rWl" = ( +/obj/item/chair/plastic{ + pixel_y = 10 + }, +/obj/item/chair/plastic{ + pixel_y = 5 + }, +/obj/item/chair/plastic, +/obj/structure/rack, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "rWQ" = ( /obj/structure/extinguisher_cabinet{ pixel_x = -5; @@ -55829,6 +55996,10 @@ /obj/structure/cable, /turf/open/floor/plating, /area/maintenance/port) +"ssv" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "suU" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -55874,12 +56045,6 @@ icon_state = "panelscorched" }, /area/maintenance/port/aft) -"sxs" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/table, -/obj/item/shovel/spade, -/turf/open/floor/plasteel, -/area/hallway/secondary/service) "sxQ" = ( /obj/effect/turf_decal/trimline/blue/filled/warning{ dir = 1 @@ -56047,10 +56212,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/science/xenobiology) -"tal" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall, -/area/hallway/secondary/service) "tav" = ( /turf/closed/wall, /area/vacant_room/commissary) @@ -56110,6 +56271,13 @@ /obj/machinery/dna_scannernew, /turf/open/floor/plasteel/white, /area/science/genetics) +"tdZ" = ( +/obj/structure/frame/computer{ + anchored = 1; + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "tgl" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -56239,12 +56407,28 @@ /obj/structure/cable, /turf/open/floor/plasteel, /area/security/brig) +"tve" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/wood, +/area/hallway/secondary/service) "twh" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 5 }, /turf/open/floor/plasteel/white, /area/science/xenobiology) +"twX" = ( +/obj/structure/chair/plastic{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "tyB" = ( /obj/effect/turf_decal/tile/blue{ dir = 1 @@ -56498,6 +56682,17 @@ }, /turf/open/floor/plasteel, /area/science/misc_lab) +"uoD" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "upN" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -56907,6 +57102,10 @@ /obj/structure/cable, /turf/open/floor/plasteel/grimy, /area/security/detectives_office) +"vvP" = ( +/obj/machinery/light/small/broken, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "vwX" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/dirt, @@ -56931,10 +57130,6 @@ }, /turf/open/floor/plasteel/white, /area/science/mixing) -"vCb" = ( -/obj/machinery/rnd/production/techfab/department/service, -/turf/open/floor/plasteel, -/area/hallway/secondary/service) "vCt" = ( /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -57132,6 +57327,13 @@ }, /turf/open/floor/plasteel, /area/science/mixing) +"wgt" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/plasteel, +/area/maintenance/starboard/fore) "whK" = ( /obj/structure/closet/secure_closet/personal/cabinet, /turf/open/floor/wood, @@ -57166,6 +57368,16 @@ /obj/item/reagent_containers/glass/bottle/epinephrine, /turf/open/floor/plasteel, /area/medical/medbay/central) +"wom" = ( +/obj/machinery/power/apc{ + areastring = "/area/hallway/secondary/service"; + dir = 1; + name = "Service Hall APC"; + pixel_y = 23 + }, +/obj/structure/cable, +/turf/open/floor/plastic, +/area/hallway/secondary/service) "wph" = ( /obj/docking_port/stationary{ dheight = 4; @@ -57187,13 +57399,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel/dark, /area/science/nanite) -"wrp" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/structure/cable, -/turf/open/floor/plasteel, -/area/hallway/secondary/service) "wtb" = ( /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -57247,8 +57452,9 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 6 }, -/turf/closed/wall, -/area/hallway/secondary/service) +/obj/structure/railing, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "wFc" = ( /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -57387,11 +57593,6 @@ }, /turf/open/floor/plasteel/grimy, /area/security/detectives_office) -"wUY" = ( -/obj/structure/table, -/obj/item/reagent_containers/glass/bucket, -/turf/open/floor/plasteel, -/area/hallway/secondary/service) "wVC" = ( /turf/closed/wall/r_wall, /area/medical/storage) @@ -57523,6 +57724,18 @@ /obj/item/plunger, /turf/open/floor/plasteel/white, /area/medical/chemistry) +"xfm" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Service Hallway East"; + dir = 8; + network = list("ss13","prison") + }, +/obj/effect/turf_decal/trimline/white/line, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "xfD" = ( /obj/machinery/power/apc{ areastring = "/area/science/genetics"; @@ -57734,6 +57947,9 @@ /obj/effect/spawner/lootdrop/grille_or_trash, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"xLr" = ( +/turf/open/floor/wood, +/area/hallway/secondary/service) "xQZ" = ( /obj/structure/chair/stool, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ @@ -57808,6 +58024,17 @@ }, /turf/open/floor/plasteel/dark, /area/medical/virology) +"xVA" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/brown/filled/line, +/turf/open/floor/wood, +/area/hallway/secondary/service) "xWd" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, @@ -57821,6 +58048,13 @@ }, /turf/open/floor/plasteel/dark, /area/medical/morgue) +"xWM" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/plasteel/showroomfloor, +/area/hallway/secondary/service) "xXe" = ( /obj/structure/closet/radiation, /obj/machinery/airalarm{ @@ -89751,7 +89985,7 @@ auU avG awr awr -azV +akV aAh aAh aFg @@ -93351,9 +93585,9 @@ axW azo aAp aBC -aCt +iiv aEA -aCt +qMc aGz aIb aCr @@ -93609,8 +93843,8 @@ azf aAo apX aBB -aBB -aBB +ssv +ssv aGy aIa cNE @@ -93865,9 +94099,9 @@ axY azh gsz arj -boP -boP -alP +cVb +fPh +myW aGI aId bke @@ -94123,9 +94357,9 @@ azg azp azp aCu -boP -alP -aGH +cVb +wom +uoD aIc aJC aKO @@ -94380,9 +94614,9 @@ aro aro aro aCv -boP -alP -aGH +fPh +kWH +dlp aIe aJC aJC @@ -94637,9 +94871,9 @@ aro aro aro aCv -boP -alP -aGH +dJS +xLr +xVA aIe aJE aKQ @@ -94894,8 +95128,8 @@ aro aro aro aCv -boP -alP +cVb +gQz aGA aHS aJx @@ -95151,9 +95385,9 @@ aro aro aro aCv -boP -alP -aGH +cVb +rrd +xVA aHM aJm aKz @@ -95408,9 +95642,9 @@ aro aro aro aCv -boP -alP -aGH +cVb +ijI +goT aIe aJC aKS @@ -95665,9 +95899,9 @@ azp azp azp aCw -boP -alP -aGH +dJS +xLr +tve aIg aJH aKR @@ -95919,12 +96153,12 @@ avD awC ayb arj -alP -alP boP boP -alP -aGH +boP +fPh +qkI +hxq aIe aJI aJI @@ -96176,12 +96410,12 @@ avC avC aya arj -arA -alP -alP -alP -alP -aGH +boP +boP +boP +dJS +qzO +pOR aIh aJI aKT @@ -96431,13 +96665,13 @@ arj auB auB arj -arj -arj -anf -anf -anf -awD +aUx alP +alP +boP +boP +fPh +qzO aGB aIf aJA @@ -96687,15 +96921,15 @@ boP boP boP boP +alP +anf +rfI +alP boP boP -alP -ayf -aBD -aCx -aDV -alP -aGH +cVb +cSk +eAT aHY aQj iNn @@ -96944,16 +97178,16 @@ boP boP boP boP +alO +anf +pKr +alO boP boP -alP -aAq -aAq -aCy -aCG -alP -aGH -avI +cVb +xWM +pOR +xfm aJK aKV tMl @@ -97202,15 +97436,15 @@ alO alO alP alP +anf +auC alP alP alP alP alP -aDW -aFn aGP -avI +iyi aJI aJI aJI @@ -97457,13 +97691,13 @@ arp alO awD anf +gjD anf -awD anf -aoP -alP +atw aBE alP +tdZ aDX alP aGH @@ -97717,12 +97951,12 @@ anf anf aEl anf -cVb -cVb -cVb -cVb -cVb -cVb +anf +anf +alP +twX +fDD +alP aGQ aIk aIp @@ -97972,15 +98206,15 @@ alO anf auC alP +auD anf anf -cVb -bBI -wrp +anf +atB fnC kPd -bjD -aCl +alP +fCu aDZ aIp aKH @@ -98231,13 +98465,13 @@ anf alP awE anf -cVb -vCb -wUY -khb -sxs -tal -aCI +anf +anf +alP +alP +alP +alP +aCG aIj aJB aKD @@ -98488,11 +98722,11 @@ apC apC alP anf -cVb -cVb -cVb -cVb -cVb +anf +anf +anf +anf +anf wBd aFm aIl @@ -98745,12 +98979,12 @@ auD apC awF anf -alP -arA +anf +anf anf aCz arr -awx +lHi aFr aIn aIp @@ -99260,7 +99494,7 @@ apC awG arr alP -alP +atB alP alP alP @@ -99510,17 +99744,17 @@ aoO apB aqx art -anf -anf +aoP +atw arr apC awH arr -alP -aAr +apE anf -alP -boP +ezU +dHJ +pAz bKs bKK aIp @@ -99766,16 +100000,16 @@ aof aof aof aof -anf -aoP -atw +atB +alP +aty arr apC aoP arr -azr +apE anf -atw +izV alP alP aFo @@ -100024,15 +100258,15 @@ boP apC aqy anf -anf +alP aty arr apC alP arr alP -alP -alP +anf +vvP alP ayf aFm @@ -100279,7 +100513,7 @@ boP boP boP apC -anf +rWl anf alP atx @@ -100289,7 +100523,7 @@ auD arr alP aAs -anf +mEX alP aCG aFr @@ -100537,7 +100771,7 @@ boP boP apC anf -alP +anf alP apE auG @@ -100545,8 +100779,8 @@ apC aoP arr apE -anf -anf +dlx +wgt alP aCG aDZ @@ -100795,7 +101029,7 @@ boP apC arA anf -asx +alP anf arr alP diff --git a/_maps/map_files/Mafia/mafia_necropolis.dmm b/_maps/map_files/Mafia/mafia_necropolis.dmm deleted file mode 100644 index 9e2ab3c0c61..00000000000 --- a/_maps/map_files/Mafia/mafia_necropolis.dmm +++ /dev/null @@ -1,802 +0,0 @@ -//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"a" = ( -/turf/closed/indestructible/riveted, -/area/mafia) -"b" = ( -/turf/closed/indestructible/riveted/boss, -/area/mafia) -"c" = ( -/turf/closed/wall/mineral/cult, -/area/mafia) -"d" = ( -/turf/open/indestructible/necropolis/air, -/area/mafia) -"e" = ( -/obj/structure/grille/indestructable, -/turf/open/indestructible/necropolis/air, -/area/mafia) -"f" = ( -/obj/effect/mapping_helpers/airlock/locked, -/obj/machinery/door/airlock{ - icon = 'icons/obj/doors/airlocks/cult/runed/cult.dmi'; - name = "Maintenance"; - overlays_file = 'icons/obj/doors/airlocks/cult/runed/overlays.dmi' - }, -/turf/open/indestructible/necropolis/air, -/area/mafia) -"g" = ( -/obj/structure/stone_tile/slab, -/obj/structure/closet/crate/necropolis{ - anchored = 1 - }, -/turf/open/lava/smooth, -/area/mafia) -"h" = ( -/obj/structure/stone_tile/block/burnt{ - dir = 8 - }, -/obj/structure/stone_tile/block/burnt{ - dir = 4 - }, -/obj/effect/landmark/mafia, -/turf/open/lava/smooth, -/area/mafia) -"i" = ( -/turf/open/floor/plating/asteroid/basalt, -/area/mafia) -"j" = ( -/obj/structure/closet/crate/necropolis{ - anchored = 1 - }, -/turf/open/floor/plating/asteroid/basalt, -/area/mafia) -"k" = ( -/obj/machinery/door/poddoor/preopen{ - desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; - id = "mafia"; - max_integrity = 99999; - name = "Station Night Shutters" - }, -/turf/closed/indestructible/riveted/boss/see_through{ - color = "#add8e6" - }, -/area/mafia) -"l" = ( -/obj/structure/stone_tile/block/cracked, -/obj/structure/stone_tile/burnt{ - dir = 1 - }, -/turf/open/lava/smooth, -/area/mafia) -"m" = ( -/obj/structure/stone_tile/slab/burnt, -/turf/open/lava/smooth, -/area/mafia) -"n" = ( -/obj/structure/stone_tile/surrounding/cracked, -/turf/open/lava/smooth, -/area/mafia) -"o" = ( -/obj/structure/stone_tile/block/cracked, -/turf/open/lava/smooth, -/area/mafia) -"p" = ( -/obj/effect/landmark/mafia, -/turf/open/floor/plating/asteroid/basalt, -/area/mafia) -"q" = ( -/obj/structure/stone_tile/slab/cracked, -/turf/open/lava/smooth, -/area/mafia) -"r" = ( -/obj/structure/stone_tile/surrounding, -/turf/open/lava/smooth, -/area/mafia) -"s" = ( -/obj/machinery/door/poddoor/preopen{ - desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; - id = "mafia"; - max_integrity = 99999; - name = "Station Night Shutters" - }, -/turf/closed/indestructible/riveted/hierophant{ - opacity = 0 - }, -/area/mafia) -"t" = ( -/obj/structure/stone_tile/surrounding/cracked, -/obj/structure/stone_tile/surrounding_tile/burnt, -/obj/structure/stone_tile/center/cracked, -/obj/effect/landmark/mafia, -/turf/open/lava/smooth, -/area/mafia) -"u" = ( -/obj/structure/stone_tile/block/cracked, -/obj/structure/stone_tile/surrounding_tile/burnt{ - dir = 4 - }, -/turf/open/lava/smooth, -/area/mafia) -"v" = ( -/obj/structure/stone_tile/block/burnt, -/obj/structure/stone_tile/burnt{ - dir = 4 - }, -/turf/open/lava/smooth, -/area/mafia) -"w" = ( -/turf/open/indestructible/hierophant, -/area/mafia) -"x" = ( -/obj/mafia_game_board, -/turf/open/indestructible/necropolis/air, -/area/mafia) -"y" = ( -/obj/structure/stone_tile/block/burnt, -/turf/open/lava/smooth, -/area/mafia) -"z" = ( -/obj/structure/stone_tile/block/cracked, -/obj/structure/stone_tile/block{ - dir = 1 - }, -/turf/open/lava/smooth, -/area/mafia) -"A" = ( -/obj/structure/stone_tile/surrounding_tile/burnt, -/obj/structure/stone_tile/surrounding_tile/burnt{ - dir = 8 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/effect/landmark/mafia, -/turf/open/lava/smooth, -/area/mafia) -"B" = ( -/obj/effect/mapping_helpers/airlock/locked{ - max_integrity = 99999 - }, -/obj/machinery/door/airlock{ - icon = 'icons/obj/doors/airlocks/cult/runed/cult.dmi'; - name = "Maintenance"; - overlays_file = 'icons/obj/doors/airlocks/cult/runed/overlays.dmi' - }, -/turf/open/indestructible/necropolis/air, -/area/mafia) -"C" = ( -/obj/structure/stone_tile/slab/cracked{ - dir = 6 - }, -/turf/open/lava/smooth, -/area/mafia) -"D" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/block, -/turf/open/lava/smooth, -/area/mafia) -"E" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/block{ - dir = 1 - }, -/turf/open/lava/smooth, -/area/mafia) -"F" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/surrounding_tile/burnt{ - dir = 4 - }, -/turf/open/lava/smooth, -/area/mafia) -"G" = ( -/obj/structure/stone_tile/block/burnt{ - dir = 4 - }, -/turf/open/lava/smooth, -/area/mafia) -"H" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked, -/obj/effect/landmark/mafia, -/turf/open/lava/smooth, -/area/mafia) -"I" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/surrounding_tile/burnt, -/obj/effect/landmark/mafia, -/turf/open/lava/smooth, -/area/mafia) -"J" = ( -/obj/structure/stone_tile/block/burnt, -/obj/effect/landmark/mafia, -/turf/open/lava/smooth, -/area/mafia) -"K" = ( -/obj/effect/baseturf_helper/asteroid, -/obj/effect/hierophant, -/obj/effect/landmark/mafia/town_center, -/turf/open/indestructible/hierophant/two, -/area/mafia) - -(1,1,1) = {" -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -"} -(2,1,1) = {" -a -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -a -"} -(3,1,1) = {" -a -b -b -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -b -b -a -"} -(4,1,1) = {" -a -b -b -c -x -e -d -d -d -d -d -d -d -d -d -d -d -e -x -c -b -b -a -"} -(5,1,1) = {" -a -b -b -c -e -d -d -d -b -b -f -b -f -b -b -d -d -d -e -c -b -b -a -"} -(6,1,1) = {" -a -b -b -c -d -b -b -f -b -g -A -b -p -j -b -f -b -b -d -c -b -b -a -"} -(7,1,1) = {" -a -b -c -c -d -b -j -p -k -r -u -k -i -i -k -D -g -b -d -c -c -b -a -"} -(8,1,1) = {" -a -b -c -d -d -b -i -i -b -b -v -b -i -b -b -E -I -b -d -d -c -b -a -"} -(9,1,1) = {" -a -b -c -d -b -b -k -i -i -k -q -k -i -k -q -F -k -b -b -d -c -b -a -"} -(10,1,1) = {" -a -b -c -d -b -g -k -b -k -s -s -s -s -s -k -b -k -j -b -d -c -b -a -"} -(11,1,1) = {" -a -b -c -d -f -h -l -m -q -s -w -w -w -s -i -i -i -p -f -d -c -b -a -"} -(12,1,1) = {" -a -b -c -d -b -b -k -b -k -s -w -K -w -s -k -b -k -b -b -d -c -b -a -"} -(13,1,1) = {" -a -b -c -d -f -p -i -i -i -s -w -w -w -s -q -G -C -J -f -d -c -b -a -"} -(14,1,1) = {" -a -b -c -d -b -j -k -b -k -s -s -s -s -s -k -b -k -g -b -d -c -b -a -"} -(15,1,1) = {" -a -b -c -d -b -b -k -n -q -k -i -k -q -k -i -i -k -b -b -d -c -b -a -"} -(16,1,1) = {" -a -b -c -d -d -b -m -o -b -b -i -b -y -b -b -i -p -b -d -d -c -b -a -"} -(17,1,1) = {" -a -b -c -c -d -b -g -t -k -i -i -k -z -C -k -i -j -b -d -c -c -b -a -"} -(18,1,1) = {" -a -b -b -c -d -b -b -f -b -j -p -b -H -g -b -f -b -b -d -c -b -b -a -"} -(19,1,1) = {" -a -b -b -c -e -d -d -d -b -b -f -b -B -b -b -d -d -d -e -c -b -b -a -"} -(20,1,1) = {" -a -b -b -c -x -e -d -d -d -d -d -d -d -d -d -d -d -e -x -c -b -b -a -"} -(21,1,1) = {" -a -b -b -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -b -b -a -"} -(22,1,1) = {" -a -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b -a -"} -(23,1,1) = {" -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -a -"} diff --git a/_maps/map_files/Mafia/mafia_snow.dmm b/_maps/map_files/Mafia/mafia_snow.dmm index ae9a4775600..079f985380b 100644 --- a/_maps/map_files/Mafia/mafia_snow.dmm +++ b/_maps/map_files/Mafia/mafia_snow.dmm @@ -97,11 +97,12 @@ /turf/open/floor/holofloor/snow, /area/mafia) "w" = ( -/turf/open/lava/plasma, +/turf/open/lava/plasma/mafia, /area/mafia) "x" = ( /obj/machinery/door/airlock/external{ - max_integrity = 9999 + max_integrity = 9999; + opacity = 0 }, /obj/machinery/door/poddoor/preopen{ desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; @@ -118,7 +119,7 @@ /area/mafia) "z" = ( /obj/structure/lattice/catwalk, -/turf/open/lava/plasma, +/turf/open/lava/plasma/mafia, /area/mafia) "A" = ( /obj/machinery/door/airlock/external{ @@ -136,7 +137,7 @@ "B" = ( /obj/effect/landmark/mafia, /obj/structure/lattice/catwalk, -/turf/open/lava/plasma, +/turf/open/lava/plasma/mafia, /area/mafia) "C" = ( /obj/mafia_game_board, @@ -153,7 +154,7 @@ /obj/structure/closet/crate/critter, /obj/item/clothing/suit/hooded/wintercoat/miner, /obj/item/clothing/shoes/winterboots, -/turf/open/lava/plasma, +/turf/open/lava/plasma/mafia, /area/mafia) "F" = ( /turf/open/floor/holofloor/wood, diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 29a40a64e4c..d8ee12ca2f3 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -316,14 +316,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) -"aaL" = ( -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel, -/area/crew_quarters/bar) "aaM" = ( /obj/structure/table/wood, /turf/open/floor/wood, @@ -659,8 +651,8 @@ /area/maintenance/central) "abq" = ( /obj/machinery/light_switch{ - pixel_y = -25; - pixel_x = -4 + pixel_x = -4; + pixel_y = -25 }, /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ @@ -15959,8 +15951,8 @@ /obj/effect/decal/cleanable/dirt, /obj/structure/table, /obj/machinery/microwave{ - pixel_y = 6; - pixel_x = 0 + pixel_x = 0; + pixel_y = 6 }, /turf/open/floor/plasteel, /area/quartermaster/warehouse) @@ -17076,8 +17068,8 @@ /obj/structure/cable, /obj/machinery/computer/security/telescreen/interrogation{ name = "isolation room monitor"; - pixel_y = 31; - network = list("isolation") + network = list("isolation"); + pixel_y = 31 }, /turf/open/floor/plasteel, /area/security/prison) @@ -18148,8 +18140,8 @@ pixel_y = 15 }, /obj/item/stack/cable_coil{ - pixel_y = 18; - pixel_x = 0 + pixel_x = 0; + pixel_y = 18 }, /obj/machinery/requests_console{ department = "Tool Storage"; @@ -19754,8 +19746,8 @@ pixel_x = -8 }, /obj/item/assembly/prox_sensor{ - pixel_y = 12; - pixel_x = 0 + pixel_x = 0; + pixel_y = 12 }, /obj/machinery/light{ dir = 4 @@ -25350,8 +25342,8 @@ pixel_y = 9 }, /obj/item/cartridge/quartermaster{ - pixel_y = 0; - pixel_x = 9 + pixel_x = 9; + pixel_y = 0 }, /obj/item/cartridge/quartermaster{ pixel_x = 5; @@ -26318,8 +26310,8 @@ /area/quartermaster/sorting) "biI" = ( /obj/machinery/firealarm{ - pixel_y = 0; - pixel_x = 30 + pixel_x = 30; + pixel_y = 0 }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 @@ -27038,8 +27030,8 @@ "bku" = ( /obj/machinery/disposal/bin, /obj/machinery/firealarm{ - pixel_y = 0; - pixel_x = -31 + pixel_x = -31; + pixel_y = 0 }, /obj/machinery/light{ dir = 8 @@ -47107,6 +47099,9 @@ name = "Cryogenics"; req_access_txt = "5" }, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, /turf/open/floor/plasteel/white, /area/medical/cryo) "cgV" = ( @@ -47126,6 +47121,9 @@ }, /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, /turf/open/floor/plasteel/white, /area/medical/cryo) "cgX" = ( @@ -49923,6 +49921,9 @@ dir = 4 }, /obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 8 + }, /turf/open/floor/plasteel/white, /area/medical/sleeper) "cnA" = ( @@ -50592,6 +50593,9 @@ dir = 4 }, /obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 8 + }, /turf/open/floor/plasteel/white, /area/medical/sleeper) "coN" = ( @@ -70125,9 +70129,9 @@ dir = 8 }, /obj/structure/sink{ - pixel_y = 29; dir = 2; - pixel_x = 0 + pixel_x = 0; + pixel_y = 29 }, /mob/living/simple_animal/mouse/brown/tom, /turf/open/floor/plating, @@ -71494,9 +71498,9 @@ }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/button/flasher{ - pixel_y = 8; id = "IsolationFlash"; - pixel_x = -23 + pixel_x = -23; + pixel_y = 8 }, /obj/structure/cable, /turf/open/floor/plasteel, @@ -74725,10 +74729,10 @@ dir = 4 }, /obj/machinery/button/door{ - name = "Panic Button"; - pixel_y = -24; id = "PermaLockdown"; + name = "Panic Button"; pixel_x = -1; + pixel_y = -24; req_access_txt = "2" }, /obj/structure/cable, diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index d5105e652ac..552001c60ca 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -101,6 +101,7 @@ #define ADMIN_PUNISHMENT_CRACK ":B:oneless" #define ADMIN_PUNISHMENT_BLEED ":B:loodless" #define ADMIN_PUNISHMENT_SCARIFY "Scarify" +#define ADMIN_PUNISHMENT_SHOES "Knot Shoes" #define AHELP_ACTIVE 1 #define AHELP_CLOSED 2 diff --git a/code/__DEFINES/cargo.dm b/code/__DEFINES/cargo.dm index 6b6c1325972..2939952f863 100644 --- a/code/__DEFINES/cargo.dm +++ b/code/__DEFINES/cargo.dm @@ -13,23 +13,35 @@ #define STYLE_GONDOLA 13 #define STYLE_SEETHROUGH 14 -#define POD_ICON_STATE 1 -#define POD_NAME 2 -#define POD_DESC 3 +#define POD_SHAPE 1 +#define POD_BASE 2 +#define POD_DECAL 3 +#define POD_GLOW 4 +#define POD_RUBBLE_TYPE 5 +#define POD_NAME 6 +#define POD_DESC 7 + +#define RUBBLE_NONE 1 +#define RUBBLE_NORMAL 2 +#define RUBBLE_WIDE 3 +#define RUBBLE_THIN 4 + +#define POD_SHAPE_NORML 1 +#define POD_SHAPE_OTHER 2 #define POD_STYLES list(\ - list("supplypod", "supply pod", "A Nanotrasen supply drop pod."),\ - list("bluespacepod", "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\ - list("centcompod", "\improper CentCom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to CentCom after delivery."),\ - list("syndiepod", "blood-red supply pod", "A dark, intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\ - list("squadpod", "\improper MK. II supply pod", "A Nanotrasen supply pod. This one has been marked the markings of some sort of elite strike team."),\ - list("cultpod", "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\ - list("missilepod", "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxiliary payload hatch on the side, though manually opening it is likely impossible."),\ - list("smissilepod", "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxiliary payload hatch on the side, though manually opening it is likely impossible."),\ - list("boxpod", "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\ - list("honkpod", "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\ - list("fruitpod", "\improper Orange", "An angry orange."),\ - list("", "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\ - list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency."),\ - list("", "", "")\ + list(POD_SHAPE_NORML, "pod", "default", "yellow", RUBBLE_NORMAL, "supply pod", "A Nanotrasen supply drop pod."),\ + list(POD_SHAPE_NORML, "advpod", "bluespace", "blue", RUBBLE_NORMAL, "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\ + list(POD_SHAPE_NORML, "advpod", "centcom", "blue", RUBBLE_NORMAL, "\improper CentCom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to CentCom after delivery."),\ + list(POD_SHAPE_NORML, "darkpod", "syndicate", "red", RUBBLE_NORMAL, "blood-red supply pod", "An intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\ + list(POD_SHAPE_NORML, "darkpod", "deathsquad", "blue", RUBBLE_NORMAL, "\improper Deathsquad drop pod", "A Nanotrasen drop pod. This one has been marked the markings of Nanotrasen's elite strike team."),\ + list(POD_SHAPE_NORML, "pod", "cultist", "red", RUBBLE_NORMAL, "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\ + list(POD_SHAPE_OTHER, "missile", null, "yellow", RUBBLE_THIN, "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\ + list(POD_SHAPE_OTHER, "smissile", null, "yellow", RUBBLE_THIN, "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\ + list(POD_SHAPE_OTHER, "box", null, "yellow", RUBBLE_WIDE, "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\ + list(POD_SHAPE_NORML, "clownpod", "clown", "green", RUBBLE_NORMAL, "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\ + list(POD_SHAPE_OTHER, "orange", null, "yellow", RUBBLE_NONE, "\improper Orange", "An angry orange."),\ + list(POD_SHAPE_OTHER, "", null, "yellow", RUBBLE_NONE, "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\ + list(POD_SHAPE_OTHER, "gondola", null, "yellow", RUBBLE_NONE, "gondola", "The silent walker. This one seems to be part of a delivery agency."),\ + list(POD_SHAPE_OTHER, "", null, "yellow", RUBBLE_NONE, "", "")\ ) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 2742c4a619c..dec82ddda9d 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -132,7 +132,7 @@ #define COMPONENT_RAD_WAVE_HANDLED (1<<0) ///from internal loop in atom/movable/proc/CanReach(): (list/next) #define COMSIG_ATOM_CANREACH "atom_can_reach" - #define COMPONENT_BLOCK_REACH (1<<0) + #define COMPONENT_ALLOW_REACH (1<<0) ///from base of atom/screwdriver_act(): (mob/living/user, obj/item/I) #define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" ///from base of atom/wrench_act(): (mob/living/user, obj/item/I) @@ -312,6 +312,10 @@ #define COMSIG_MOB_THROW "mob_throw" ///from base of /mob/verb/examinate(): (atom/target) #define COMSIG_MOB_EXAMINATE "mob_examinate" +///from /mob/living/handle_eye_contact(): (mob/living/other_mob) +#define COMSIG_MOB_EYECONTACT "mob_eyecontact" + /// return this if you want to block printing this message to this person, if you want to print your own (does not affect the other person's message) + #define COMSIG_BLOCK_EYECONTACT (1<<0) ///from base of /mob/update_sight(): () #define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" ////from /mob/living/say(): () diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 2a807aecd47..3ac969e4cd4 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -120,6 +120,12 @@ #define SHOES_TIED 1 #define SHOES_KNOTTED 2 +//how fast a disposal machinery thing is ejecting things +#define EJECT_SPEED_SLOW 1 +#define EJECT_SPEED_MED 2 +#define EJECT_SPEED_FAST 4 +#define EJECT_SPEED_YEET 6 + //Cache of bloody footprint images //Key: //"entered-[blood_state]-[dir_of_image]" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 6171edbd3d4..8ca527c802f 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -366,5 +366,7 @@ /// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine() #define EXAMINE_MORE_TIME 1 SECONDS +/// How far away you can be to make eye contact with someone while examining +#define EYE_CONTACT_RANGE 5 #define SILENCE_RANGED_MESSAGE (1<<0) diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index b73d5bc5252..633df072511 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -10,7 +10,10 @@ #define UNIQUE_RENAME (1<<6) // can you customize the description/name of the thing? #define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI. #define FROZEN (1<<8) -#define BLOCK_Z_FALL (1<<9) // Should this object block z falling? +#define BLOCK_Z_OUT_DOWN (1<<9) // Should this object block z falling from loc? +#define BLOCK_Z_OUT_UP (1<<10) // Should this object block z uprise from loc? +#define BLOCK_Z_IN_DOWN (1<<11) // Should this object block z falling from above? +#define BLOCK_Z_IN_UP (1<<12) // Should this object block z uprise from below? // If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support diff --git a/code/__DEFINES/research.dm b/code/__DEFINES/research.dm index a0e2fa9d9f9..47e95102c5d 100644 --- a/code/__DEFINES/research.dm +++ b/code/__DEFINES/research.dm @@ -85,3 +85,6 @@ #define SLIME_RESEARCH_TIER_4 2000 #define SLIME_RESEARCH_TIER_5 2500 #define SLIME_RESEARCH_TIER_RAINBOW 5000 + +///Amount of points gained per second by a single R&D server, see: [/controllers/subsystem/research.dm][research] +#define TECHWEB_SINGLE_SERVER_INCOME 52.3 diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 69fba583577..a77d984d8e6 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -21,6 +21,7 @@ #define ROLE_BLOB "Blob" #define ROLE_NINJA "Space Ninja" #define ROLE_MONKEY "Monkey" +#define ROLE_MONKEY_HELMET "Monkey Mind Magnification Helmet" #define ROLE_ABDUCTOR "Abductor" #define ROLE_REVENANT "Revenant" #define ROLE_DEVIL "Devil" diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index 0994e37686c..660e1986cf0 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -92,3 +92,7 @@ // Audio/Visual Flags. Used to determine what sense are required to notice a message. #define MSG_VISUAL (1<<0) #define MSG_AUDIBLE (1<<1) + +#define INVOCATION_SHOUT "shout" +#define INVOCATION_EMOTE "emote" +#define INVOCATION_WHISPER "whisper" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 799435a5339..f9ac1d51a9c 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -187,6 +187,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_SILENT_FOOTSTEPS "silent_footsteps" //makes your footsteps completely silent #define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good.... #define TRAIT_TUMOR_SUPPRESSED "brain_tumor_suppressed" //prevents the damage done by a brain tumor +#define TRAIT_PERMANENTLY_ONFIRE "permanently_onfire" //overrides the update_fire proc to always add fire (for lava) //non-mob traits #define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it @@ -263,6 +264,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define INNATE_TRAIT "innate" #define CRIT_HEALTH_TRAIT "crit_health" #define OXYLOSS_TRAIT "oxyloss" +#define TURF_TRAIT "turf" // unique trait sources, still defines #define CLONING_POD_TRAIT "cloning-pod" diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index f78f95db29b..12a2c733c42 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -712,9 +712,9 @@ world /// appearance system (overlays/underlays, etc.) is not available. /// /// Only the first argument is required. -/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE) +/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = TRUE) //Define... defines. - var/static/icon/flat_template = icon('icons/effects/effects.dmi', "nothing") + var/static/icon/flat_template = icon('icons/blanks/32x32.dmi', "nothing") #define BLANK icon(flat_template) #define SET_SELF(SETVAR) do { \ diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index a991fe57e0e..2f7c4452a67 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -109,7 +109,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_GIANT" = TRAIT_GIANT, "TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS, "TRAIT_NICE_SHOT" = TRAIT_NICE_SHOT, - "TRAIT_TUMOR_SUPPRESSION" = TRAIT_TUMOR_SUPPRESSED + "TRAIT_TUMOR_SUPPRESSION" = TRAIT_TUMOR_SUPPRESSED, + "TRAIT_PERMANENTLY_ONFIRE" = TRAIT_PERMANENTLY_ONFIRE ), /obj/item/bodypart = list( "TRAIT_PARALYSIS" = TRAIT_PARALYSIS diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 061b5a3b990..ab70cc4a286 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -203,7 +203,8 @@ if (!target.loc) continue - if(!(SEND_SIGNAL(target.loc, COMSIG_ATOM_CANREACH, next) & COMPONENT_BLOCK_REACH)) + //Storage and things with reachable internal atoms need add to next here. Or return COMPONENT_ALLOW_REACH. + if(SEND_SIGNAL(target.loc, COMSIG_ATOM_CANREACH, next) & COMPONENT_ALLOW_REACH) next += target.loc checking = next diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index dbe11d5683a..63ca1e14e5c 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -338,7 +338,7 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table . = run_query(async) var/timed_out = !. && findtext(last_error, "Operation timed out") if(!. && log_error) - log_sql("[last_error] | Query used: [sql]") + log_sql("[last_error] | Query used: [sql] | Arguments: [json_encode(arguments)]") if(!async && timed_out) log_query_debug("Query execution started at [start_time]") log_query_debug("Query execution ended at [REALTIMEOFDAY]") diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm index efd247be6e0..a512dac4fb4 100644 --- a/code/controllers/subsystem/research.dm +++ b/code/controllers/subsystem/research.dm @@ -32,7 +32,7 @@ SUBSYSTEM_DEF(research) var/list/point_types = list() //typecache style type = TRUE list var/list/slime_already_researched = list() //Slime cores that have already been researched //---------------------------------------------- - var/list/single_server_income = list(TECHWEB_POINT_TYPE_GENERIC = 52.3) + var/list/single_server_income = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_SINGLE_SERVER_INCOME) var/multiserver_calculation = FALSE var/last_income //^^^^^^^^ ALL OF THESE ARE PER SECOND! ^^^^^^^^ diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 430e9b6d45e..9c3dee55b4f 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -229,6 +229,8 @@ SUBSYSTEM_DEF(vote) C.player_details.player_actions += V V.Grant(C.mob) generated_actions += V + if(C.prefs.toggles & SOUND_ANNOUNCEMENTS) + SEND_SOUND(C, sound('sound/misc/bloop.ogg')) return TRUE return FALSE diff --git a/code/datums/brain_damage/creepy_trauma.dm b/code/datums/brain_damage/creepy_trauma.dm index 8c0e49d5e6a..d3b38fb17f6 100644 --- a/code/datums/brain_damage/creepy_trauma.dm +++ b/code/datums/brain_damage/creepy_trauma.dm @@ -29,6 +29,7 @@ owner.mind.add_antag_datum(/datum/antagonist/obsessed) antagonist = owner.mind.has_antag_datum(/datum/antagonist/obsessed) antagonist.trauma = src + RegisterSignal(obsession, COMSIG_MOB_EYECONTACT, .proc/stare) ..() //antag stuff// antagonist.forge_objectives(obsession.mind) @@ -65,6 +66,8 @@ /datum/brain_trauma/special/obsessed/on_lose() ..() owner.mind.remove_antag_datum(/datum/antagonist/obsessed) + if(obsession) + UnregisterSignal(obsession, COMSIG_MOB_EYECONTACT) /datum/brain_trauma/special/obsessed/handle_speech(datum/source, list/speech_args) if(!viewing) @@ -100,6 +103,13 @@ fail = TRUE return fail +// if the creep examines first, then the obsession examines them, have a 50% chance to possibly blow their cover. wearing a mask avoids this risk +/datum/brain_trauma/special/obsessed/proc/stare(datum/source, mob/living/examining_mob, triggering_examiner) + if(examining_mob != owner || !triggering_examiner || prob(50)) + return + + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, obsession, "You catch [examining_mob] staring at you...", 3)) + return COMSIG_BLOCK_EYECONTACT /datum/brain_trauma/special/obsessed/proc/find_obsession() var/chosen_victim diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 367fbc42d8d..9458e4153e0 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -173,7 +173,7 @@ var/datum/component/storage/concrete/master = master() if(!master) return - . = COMPONENT_BLOCK_REACH + . = COMPONENT_ALLOW_REACH next += master.parent for(var/i in master.slaves) var/datum/component/storage/slave = i diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index f20892cd36c..fa703ded705 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -366,6 +366,7 @@ user.adjustBruteLoss(30) playsound(user, 'sound/effects/blobattack.ogg', 60, TRUE) playsound(user, 'sound/effects/splat.ogg', 70, TRUE) + playsound(user, 'sound/effects/crack2.ogg', 70, TRUE) user.emote("scream") user.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic) // oopsie indeed! shake_camera(user, 7, 7) @@ -434,13 +435,13 @@ W.obj_destruction() user.adjustStaminaLoss(10 * speed) user.Paralyze(30) - user.visible_message("[user] slams into [W] and shatters it, shredding [user.p_them()]self with glass!", "You slam into [W] and shatter it, shredding yourself with glass!") + user.visible_message("[user] smacks into [W] and shatters it, shredding [user.p_them()]self with glass!", "You smacks into [W] and shatter it, shredding yourself with glass!") else - user.visible_message("[user] slams into [W] like a bug, then slowly slides off it!", "You slam into [W] like a bug, then slowly slide off it!") + user.visible_message("[user] smacks into [W] like a bug!", "You smacks into [W] like a bug!") user.Paralyze(10) user.Knockdown(30) - W.take_damage(20 * speed) + W.take_damage(30 * speed) user.adjustStaminaLoss(10 * speed) user.adjustBruteLoss(5 * speed) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 2143ed7bec4..f966ab1e8f9 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -77,8 +77,6 @@ if (success) log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]") tele_play_specials(teleatom, destturf, effectout, asoundout) - if(ismegafauna(teleatom)) - message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_VERBOSEJMP(curturf)] to [ADMIN_VERBOSEJMP(destturf)].") if(ismob(teleatom)) var/mob/M = teleatom diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm index 1d05a8b31bc..4dcb91e660b 100644 --- a/code/datums/mutations/actions.dm +++ b/code/datums/mutations/actions.dm @@ -180,7 +180,7 @@ clothes_req = FALSE charge_max = 600 invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT action_icon_state = "void_magnet" /obj/effect/proc_holder/spell/self/void/can_cast(mob/user = usr) diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index c7a434524c7..459762c07be 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -77,5 +77,5 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) pod.explosionSize = list(0,0,0,0) to_chat(mind.current, "My legendary skill has attracted the attention of the Professional [title] Association. It seems they are sending me a status symbol to commemorate my abilities.") var/turf/T = get_turf(mind.current) - new /obj/effect/dp_target(T, pod , new skill_cape_path(T)) + new /obj/effect/pod_landingzone(T, pod , new skill_cape_path(T)) LAZYADD(mind.skills_rewarded, src.type) diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index d1460bbc11c..1d20bec1fd7 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -96,7 +96,6 @@ /datum/quirk/brainproblems/on_process() if(HAS_TRAIT(quirk_holder, TRAIT_TUMOR_SUPPRESSED)) return - quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2) /datum/quirk/deafness @@ -484,6 +483,13 @@ hardcore_value = 4 var/dumb_thing = TRUE +/datum/quirk/social_anxiety/add() + RegisterSignal(quirk_holder, COMSIG_MOB_EYECONTACT, .proc/eye_contact) + RegisterSignal(quirk_holder, COMSIG_MOB_EXAMINATE, .proc/looks_at_floor) + +/datum/quirk/social_anxiety/remove() + UnregisterSignal(quirk_holder, list(COMSIG_MOB_EYECONTACT, COMSIG_MOB_EXAMINATE)) + /datum/quirk/social_anxiety/on_process() var/nearby_people = 0 for(var/mob/living/carbon/human/H in oview(3, quirk_holder)) @@ -501,6 +507,43 @@ if(prob(1)) new/obj/item/reagent_containers/food/snacks/spaghetti/pastatomato(get_turf(H)) //now that's what I call spaghetti code +// small chance to make eye contact with inanimate objects/mindless mobs because of nerves +/datum/quirk/social_anxiety/proc/looks_at_floor(datum/source, atom/A) + var/mob/living/mind_check = A + if(prob(85) || (istype(mind_check) && mind_check.mind)) + return + + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, quirk_holder, "You make eye contact with [A]."), 3) + +/datum/quirk/social_anxiety/proc/eye_contact(datum/source, mob/living/other_mob, triggering_examiner) + if(prob(75)) + return + var/msg + if(triggering_examiner) + msg = "You make eye contact with [other_mob], " + else + msg = "[other_mob] makes eye contact with you, " + + switch(rand(1,3)) + if(1) + quirk_holder.Jitter(10) + msg += "causing you to start fidgeting!" + if(2) + quirk_holder.stuttering = max(3, quirk_holder.stuttering) + msg += "causing you to start stuttering!" + if(3) + quirk_holder.Stun(2 SECONDS) + msg += "causing you to freeze up!" + + SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "anxiety_eyecontact", /datum/mood_event/anxiety_eyecontact) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, quirk_holder, "[msg]"), 3) // so the examine signal has time to fire and this will print after + return COMSIG_BLOCK_EYECONTACT + +/datum/mood_event/anxiety_eyecontact + description = "Sometimes eye contact makes me so nervous...\n" + mood_change = -5 + timeout = 3 MINUTES + /datum/quirk/junkie name = "Junkie" desc = "You can't get enough of hard drugs." diff --git a/code/datums/wires/conveyor.dm b/code/datums/wires/conveyor.dm new file mode 100644 index 00000000000..0e82fb13cfb --- /dev/null +++ b/code/datums/wires/conveyor.dm @@ -0,0 +1,17 @@ +/datum/wires/conveyor + holder_type = /obj/machinery/conveyor_switch + proper_name = "conveyor" + /// var holder that logs who put the assembly inside and gets transfered to the switch on pulse + var/mob/fingerman + +/datum/wires/conveyor/New(atom/holder) + add_duds(1) + ..() + +/datum/wires/conveyor/on_pulse(wire) + var/obj/machinery/conveyor_switch/C = holder + C.interact(fingerman) + +/datum/wires/conveyor/interactable(mob/user) + fingerman = user + return TRUE diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 51cd935a45e..2981d69ba7c 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -71,6 +71,8 @@ var/safe = FALSE /// If false, loading multiple maps with this area type will create multiple instances. var/unique = TRUE + /// If people are allowed to suicide in it. Mostly for OOC stuff like minigames + var/block_suicide = FALSE var/no_air = null diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1ab512d18f9..cb2671aa9a5 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1407,3 +1407,19 @@ */ /atom/proc/rust_heretic_act() return + +/** + * Used to set something as 'open' if it's being used as a supplypod + * + * Override this if you want an atom to be usable as a supplypod. + */ +/atom/proc/setOpened() + return + +/** + * Used to set something as 'closed' if it's being used as a supplypod + * + * Override this if you want an atom to be usable as a supplypod. + */ +/atom/proc/setClosed() + return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index b5fd76c2e0a..f3292b260ab 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -574,7 +574,7 @@ if(impact_signal & COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH) hitpush = FALSE // hacky, tie this to something else or a proper workaround later - if(impact_signal & ~COMPONENT_MOVABLE_IMPACT_NEVERMIND) // in case a signal interceptor broke or deleted the thing before we could process our hit + if(!(impact_signal && (impact_signal & COMPONENT_MOVABLE_IMPACT_NEVERMIND))) // in case a signal interceptor broke or deleted the thing before we could process our hit return hit_atom.hitby(src, throwingdatum=throwingdatum, hitpush=hitpush) /atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 0529bc3ea18..50995a6a995 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -407,7 +407,7 @@ Class Procs: for(var/obj/item/I in component_parts) I.forceMove(loc) component_parts.Cut() - qdel(src) + return ..() /obj/machinery/proc/spawn_frame(disassembled) var/obj/structure/frame/machine/M = new /obj/structure/frame/machine(loc) @@ -437,6 +437,7 @@ Class Procs: occupant = null update_icon() updateUsrDialog() + return ..() /obj/machinery/CanAllowThrough(atom/movable/mover, turf/target) . = ..() diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index dd2f1a1e47f..002fabb9f8b 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -597,14 +597,13 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( return ..() //well boys we did it, lists are no more /obj/machinery/computer/arcade/battle/examine_more(mob/user) - to_chat(user, "Scribbled on the side of the Arcade Machine you notice some writing...\ - \nmagical -> >=50 power\ - \nsmart -> defend, defend, light attack\ - \nshotgun -> defend, defend, power attack\ - \nshort temper -> counter, counter, counter\ - \npoisonous -> light attack, light attack, light attack\ - \nchonker -> power attack, power attack, power attack") - return ..() + var/list/msg = list("You notice some writing scribbled on the side of [src]...") + msg += "\tsmart -> defend, defend, light attack" + msg += "\tshotgun -> defend, defend, power attack" + msg += "\tshort temper -> counter, counter, counter" + msg += "\tpoisonous -> light attack, light attack, light attack" + msg += "\tchonker -> power attack, power attack, power attack" + return msg /obj/machinery/computer/arcade/battle/emag_act(mob/user) if(obj_flags & EMAGGED) diff --git a/code/game/machinery/defibrillator_mount.dm b/code/game/machinery/defibrillator_mount.dm index a936d4a3793..44ba25086b3 100644 --- a/code/game/machinery/defibrillator_mount.dm +++ b/code/game/machinery/defibrillator_mount.dm @@ -27,6 +27,12 @@ QDEL_NULL(defib) . = ..() +/obj/machinery/defibrillator_mount/handle_atom_del(atom/A) + if(A == defib) + defib = null + end_processing() + return ..() + /obj/machinery/defibrillator_mount/examine(mob/user) . = ..() if(defib) @@ -171,6 +177,8 @@ /obj/machinery/defibrillator_mount/charging/process() var/obj/item/stock_parts/cell/C = get_cell() + if(!C) + return PROCESS_KILL if(C.charge < C.maxcharge && is_operational()) use_power(100) C.give(80) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 06ff08ee5fb..fba36205143 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -37,6 +37,7 @@ #define AIRLOCK_DAMAGE_DEFLECTION_N 21 // Normal airlock damage deflection #define AIRLOCK_DAMAGE_DEFLECTION_R 30 // Reinforced airlock damage deflection +#define DOOR_CLOSE_WAIT 60 /// Time before a door closes, if not overridden /obj/machinery/door/airlock name = "airlock" icon = 'icons/obj/doors/airlocks/station/public.dmi' @@ -1076,7 +1077,7 @@ if(safe) for(var/atom/movable/M in get_turf(src)) if(M.density && M != src) //something is blocking the door - autoclose_in(60) + autoclose_in(DOOR_CLOSE_WAIT) return if(forced < 2) @@ -1496,3 +1497,5 @@ #undef AIRLOCK_INTEGRITY_MULTIPLIER #undef AIRLOCK_DAMAGE_DEFLECTION_N #undef AIRLOCK_DAMAGE_DEFLECTION_R + +#undef DOOR_CLOSE_WAIT diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index fbee034949d..2f4746eff31 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -1,3 +1,4 @@ +#define DOOR_CLOSE_WAIT 60 ///Default wait until doors autoclose /obj/machinery/door name = "door" desc = "It opens and closes." @@ -301,7 +302,7 @@ air_update_turf(1) update_freelook_sight() if(autoclose) - addtimer(CALLBACK(src, .proc/close), autoclose) + autoclose_in(DOOR_CLOSE_WAIT) return 1 /obj/machinery/door/proc/close() @@ -313,7 +314,7 @@ for(var/atom/movable/M in get_turf(src)) if(M.density && M != src) //something is blocking the door if(autoclose) - autoclose_in(60) + autoclose_in(DOOR_CLOSE_WAIT) return operating = TRUE @@ -424,4 +425,6 @@ /obj/machinery/door/power_change() . = ..() if(. && !(machine_stat & NOPOWER)) - autoclose_in(rand(0.5 SECONDS, 3 SECONDS)) + autoclose_in(DOOR_CLOSE_WAIT) + +#undef DOOR_CLOSE_WAIT diff --git a/code/game/machinery/roulette_machine.dm b/code/game/machinery/roulette_machine.dm index 8023b366a5b..61bd80508e9 100644 --- a/code/game/machinery/roulette_machine.dm +++ b/code/game/machinery/roulette_machine.dm @@ -409,7 +409,7 @@ new /obj/machinery/roulette(toLaunch) - new /obj/effect/dp_target(drop_location(), toLaunch) + new /obj/effect/pod_landingzone(drop_location(), toLaunch) qdel(src) #undef ROULETTE_SINGLES_PAYOUT diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 2a4c40f88a5..448f43d68a2 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -102,6 +102,10 @@ step_towards(M,src) for(var/obj/O in range(0,src)) if(!O.anchored) + if(isturf(O.loc)) + var/turf/T = O.loc + if(T.intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) + continue var/mob/living/target = locate() in view(4,src) if(target && !target.stat) O.throw_at(target, 5, 10) diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm index 71df7a03727..4ae0288006f 100644 --- a/code/game/objects/effects/contraband.dm +++ b/code/game/objects/effects/contraband.dm @@ -164,7 +164,7 @@ return to_chat(user, "The poster falls down!") - D.roll_and_drop(temp_loc) + D.roll_and_drop(get_turf(user)) // Various possible posters follow diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 0207633bf23..41355e1bad0 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -141,6 +141,10 @@ for(var/obj/O in range(0,src)) if(O.type == src.type) continue + if(isturf(O.loc)) + var/turf/T = O.loc + if(T.intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) + continue if(lifetime % reagent_divisor) reagents.expose(O, VAPOR, fraction) var/hit = 0 diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index 80ff9c7e8aa..dafca92532f 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -232,6 +232,8 @@ for(var/atom/movable/AM in T) if(AM.type == src.type) continue + if(T.intact && HAS_TRAIT(AM, TRAIT_T_RAY_VISIBLE)) + continue reagents.expose(AM, TOUCH, fraction) reagents.expose(T, TOUCH, fraction) diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm index 2d28d3a041b..bdf7285f9aa 100644 --- a/code/game/objects/effects/glowshroom.dm +++ b/code/game/objects/effects/glowshroom.dm @@ -45,11 +45,6 @@ . = ..() . += "This is a [generation]\th generation [name]!" -/obj/structure/glowshroom/Destroy() - if(myseed) - QDEL_NULL(myseed) - return ..() - /** * Creates a new glowshroom structure. * @@ -142,6 +137,8 @@ continue Decay(TRUE, 2) // Decay before spawning new mushrooms to reduce their endurance + if(QDELETED(src)) //Decay can end us + return var/obj/structure/glowshroom/child = new type(newLoc, myseed, TRUE, TRUE) child.generation = generation + 1 shrooms_planted++ diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 56d322a04a9..0643363c6d9 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -154,8 +154,6 @@ return FALSE if(!force && (!ismecha(M) && !istype(M, /obj/projectile) && M.anchored && !allow_anchored)) return - if(ismegafauna(M)) - message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].") var/no_effect = FALSE if(last_effect == world.time) no_effect = TRUE diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index a04f9724b25..2a38b4020b3 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -45,10 +45,6 @@ w_class = WEIGHT_CLASS_SMALL item_flags = NO_MAT_REDEMPTION -/obj/item/bodybag/bluespace/Initialize() - . = ..() - RegisterSignal(src, COMSIG_ATOM_CANREACH, .proc/CanReachReact) - /obj/item/bodybag/bluespace/examine(mob/user) . = ..() if(contents.len) @@ -62,9 +58,6 @@ to_chat(A, "You suddenly feel the space around you torn apart! You're free!") return ..() -/obj/item/bodybag/bluespace/proc/CanReachReact(atom/movable/source, list/next) - return COMPONENT_BLOCK_REACH - /obj/item/bodybag/bluespace/deploy_bodybag(mob/user, atom/location) var/obj/structure/closet/body_bag/R = new unfoldedbag_path(location) for(var/atom/movable/A in contents) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 3c3c899e749..245a044286c 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -15,7 +15,7 @@ var/energy = 10 var/max_energy = 10 var/effectchance = 30 - var/recharging = 0 + var/recharging = FALSE var/recharge_locked = FALSE var/obj/item/stock_parts/micro_laser/diode //used for upgrading! @@ -178,7 +178,7 @@ energy -= 1 if(energy <= max_energy) if(!recharging) - recharging = 1 + recharging = TRUE START_PROCESSING(SSobj, src) if(energy <= 0) to_chat(user, "[src]'s battery is overused, it needs time to recharge!") @@ -188,10 +188,13 @@ icon_state = "pointer" /obj/item/laser_pointer/process() + if(!diode) + recharging = FALSE + return PROCESS_KILL if(prob(20 + diode.rating*20 - recharge_locked*2)) //t1 is 20, 2 40 energy += 1 if(energy >= max_energy) energy = max_energy - recharging = 0 + recharging = FALSE recharge_locked = FALSE - ..() + return ..() diff --git a/code/game/objects/items/devices/portable_chem_mixer.dm b/code/game/objects/items/devices/portable_chem_mixer.dm index 56955ee97f8..01bbd3d47e3 100644 --- a/code/game/objects/items/devices/portable_chem_mixer.dm +++ b/code/game/objects/items/devices/portable_chem_mixer.dm @@ -3,6 +3,7 @@ desc = "A portable device that dispenses and mixes chemicals. Requires a vortex anomaly core. All necessary reagents need to be supplied with beakers. A label indicates that a screwdriver is required to open it for refills. This device can be worn on a belt. The letters 'S&T' are imprinted on the side." icon = 'icons/obj/chemical.dmi' icon_state = "portablechemicalmixer_open" + worn_icon_state = "portable_chem_mixer" w_class = WEIGHT_CLASS_HUGE slot_flags = ITEM_SLOT_BELT equip_sound = 'sound/items/equip/toolbelt_equip.ogg' diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 83e0bc9431a..78f841d5cea 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -67,8 +67,7 @@ GENE SCANNER return var/list/t_ray_images = list() for(var/obj/O in orange(distance, viewer) ) - - if(O.invisibility == INVISIBILITY_MAXIMUM || HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) + if(HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) var/image/I = new(loc = get_turf(O)) var/mutable_appearance/MA = new(O) MA.alpha = 128 diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm index 2fde0d20022..874a31f6726 100644 --- a/code/game/objects/items/miscellaneous.dm +++ b/code/game/objects/items/miscellaneous.dm @@ -61,7 +61,7 @@ msg = "You hear something crackle in your ears for a moment before a voice speaks. \"Please stand by for a message from Central Command. Message as follows: Item request received. Your package is inbound, please stand back from the landing site. Message ends.\"" to_chat(M, msg) - new /obj/effect/dp_target(get_turf(src), pod) + new /obj/effect/pod_landingzone(get_turf(src), pod) /obj/item/choice_beacon/hero name = "heroic beacon" diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 0ea8b83e065..0099c33e6ec 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -275,6 +275,17 @@ qdel(I) //BubbleWrap END +/obj/item/stack/vv_edit_var(vname, vval) + if(vname == NAMEOF(src, amount)) + add(clamp(vval, 1-amount, max_amount - amount)) //there must always be one. + return TRUE + else if(vname == NAMEOF(src, max_amount)) + max_amount = max(vval, 1) + add((max_amount < amount) ? (max_amount - amount) : 0) //update icon, weight, ect + return TRUE + return ..() + + /obj/item/stack/proc/building_checks(datum/stack_recipe/R, multiplier) if (get_amount() < R.req_amount*multiplier) if (R.req_amount*multiplier>1) diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 0cc2aec899c..76bf10f1c0a 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -102,6 +102,7 @@ desc = "This little bugger can be used to store and transport ores." icon = 'icons/obj/mining.dmi' icon_state = "satchel" + worn_icon_state = "satchel" slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_POCKETS w_class = WEIGHT_CLASS_NORMAL component_type = /datum/component/storage/concrete/stack @@ -188,6 +189,7 @@ name = "plant bag" icon = 'icons/obj/hydroponics/equipment.dmi' icon_state = "plantbag" + worn_icon_state = "plantbag" resistance_flags = FLAMMABLE /obj/item/storage/bag/plants/ComponentInitialize() @@ -230,6 +232,7 @@ desc = "A patented Nanotrasen storage system designed for any kind of mineral sheet." icon = 'icons/obj/mining.dmi' icon_state = "sheetsnatcher" + worn_icon_state = "satchel" var/capacity = 300; //the number of sheets it can carry. component_type = /datum/component/storage/concrete/stack @@ -271,6 +274,7 @@ desc = "A bag for books." icon = 'icons/obj/library.dmi' icon_state = "bookbag" + worn_icon_state = "bookbag" resistance_flags = FLAMMABLE /obj/item/storage/bag/books/ComponentInitialize() @@ -361,6 +365,7 @@ name = "chemistry bag" icon = 'icons/obj/chemical.dmi' icon_state = "bag" + worn_icon_state = "chembag" desc = "A bag for storing pills, patches, and bottles." resistance_flags = FLAMMABLE @@ -389,6 +394,7 @@ name = "bio bag" icon = 'icons/obj/chemical.dmi' icon_state = "biobag" + worn_icon_state = "biobag" desc = "A bag for the safe transportation and disposal of biowaste and other biological materials." resistance_flags = FLAMMABLE @@ -420,6 +426,7 @@ name = "construction bag" icon = 'icons/obj/tools.dmi' icon_state = "construction_bag" + worn_icon_state = "construction_bag" desc = "A bag for storing small construction components." resistance_flags = FLAMMABLE diff --git a/code/game/objects/items/toy_mechs.dm b/code/game/objects/items/toy_mechs.dm new file mode 100644 index 00000000000..7f39b8f8869 --- /dev/null +++ b/code/game/objects/items/toy_mechs.dm @@ -0,0 +1,632 @@ +/** + * Mech prizes + MECHA COMBAT!! + */ + +/// Mech battle special attack types. +#define SPECIAL_ATTACK_HEAL 1 +#define SPECIAL_ATTACK_DAMAGE 2 +#define SPECIAL_ATTACK_UTILITY 3 +#define SPECIAL_ATTACK_OTHER 4 + +/// Max length of a mech battle +#define MAX_BATTLE_LENGTH 50 + +/obj/item/toy/prize + icon = 'icons/obj/toy.dmi' + icon_state = "ripleytoy" + verb_say = "beeps" + verb_ask = "beeps" + verb_exclaim = "beeps" + verb_yell = "beeps" + w_class = WEIGHT_CLASS_SMALL + /// Timer when it'll be off cooldown + var/timer = 0 + /// Cooldown between play sessions + var/cooldown = 1.5 SECONDS + /// Cooldown multiplier after a battle (by default: battle cooldowns are 30 seconds) + var/cooldown_multiplier = 20 + /// If it makes noise when played with + var/quiet = FALSE + /// TRUE = Offering battle to someone || FALSE = Not offering battle + var/wants_to_battle = FALSE + /// TRUE = in combat currently || FALSE = Not in combat + var/in_combat = FALSE + /// The mech's health in battle + var/combat_health = 0 + /// The mech's max combat health + var/max_combat_health = 0 + /// TRUE = the special attack is charged || FALSE = not charged + var/special_attack_charged = FALSE + /// What type of special attack they use - SPECIAL_ATTACK_DAMAGE, SPECIAL_ATTACK_HEAL, SPECIAL_ATTACK_UTILITY, SPECIAL_ATTACK_OTHER + var/special_attack_type = 0 + /// What message their special move gets on examining + var/special_attack_type_message = "" + /// The battlecry when using the special attack + var/special_attack_cry = "*flip" + /// Current cooldown of their special attack + var/special_attack_cooldown = 0 + /// This mech's win count in combat + var/wins = 0 + /// ...And their loss count in combat + var/losses = 0 + +/obj/item/toy/prize/Initialize() + . = ..() + desc = "Mini-Mecha action figure! Collect them all! Attack your friends or another mech with one to initiate epic mech combat! [desc]." + combat_health = max_combat_health + switch(special_attack_type) + if(SPECIAL_ATTACK_DAMAGE) + special_attack_type_message = "an aggressive move, which deals bonus damage." + if(SPECIAL_ATTACK_HEAL) + special_attack_type_message = "a defensive move, which grants bonus healing." + if(SPECIAL_ATTACK_UTILITY) + special_attack_type_message = "a utility move, which heals the user and damages the opponent." + if(SPECIAL_ATTACK_OTHER) + special_attack_type_message = "a special move, which [special_attack_type_message]" + else + special_attack_type_message = "a mystery move, even I don't know." + +/** + * this proc combines "sleep" while also checking for if the battle should continue + * + * this goes through some of the checks - the toys need to be next to each other to fight! + * if it's player vs themself: They need to be able to "control" both mechs (either must be adjacent or using TK) + * if it's player vs player: Both players need to be able to "control" their mechs (either must be adjacent or using TK) + * if it's player vs mech (suicide): the mech needs to be in range of the player + * if all the checks are TRUE, it does the sleeps, and returns TRUE. Otherwise, it returns FALSE. + * Arguments: + * * delay - the amount of time the sleep at the end of the check will sleep for + * * attacker - the attacking toy in the battle. + * * attacker_controller - the controller of the attacking toy. there should ALWAYS be an attacker_controller + * * opponent - (optional) the defender controller in the battle, for PvP + */ +/obj/item/toy/prize/proc/combat_sleep(var/delay, obj/item/toy/prize/attacker, mob/living/carbon/attacker_controller, mob/living/carbon/opponent) + if(!attacker_controller) + return FALSE + + if(!attacker) //if there's no attacker, then attacker_controller IS the attacker + if(!in_range(src, attacker_controller)) + attacker_controller.visible_message("[attacker_controller] is running from [src]! The coward!") + return FALSE + else // if there's an attacker, we can procede as normal + if(!in_range(src, attacker)) //and the two toys aren't next to each other, the battle ends + attacker_controller.visible_message(" [attacker] and [src] separate, ending the battle. ", \ + " [attacker] and [src] separate, ending the battle. ") + return FALSE + + //dead men tell no tales, incapacitated men fight no fights + if(attacker_controller.incapacitated()) + return FALSE + //if the attacker_controller isn't next to the attacking toy (and doesn't have telekinesis), the battle ends + if(!in_range(attacker, attacker_controller) && !(attacker_controller.dna.check_mutation(TK))) + attacker_controller.visible_message(" [attacker_controller.name] seperates from [attacker], ending the battle.", \ + " You separate from [attacker], ending the battle. ") + return FALSE + + //if it's PVP and the opponent is not next to the defending(src) toy (and doesn't have telekinesis), the battle ends + if(opponent) + if(opponent.incapacitated()) + return FALSE + if(!in_range(src, opponent) && !(opponent.dna.check_mutation(TK))) + opponent.visible_message(" [opponent.name] seperates from [src], ending the battle.", \ + " You separate from [src], ending the battle. ") + return FALSE + //if it's not PVP and the attacker_controller isn't next to the defending toy (and doesn't have telekinesis), the battle ends + else + if (!in_range(src, attacker_controller) && !(attacker_controller.dna.check_mutation(TK))) + attacker_controller.visible_message(" [attacker_controller.name] seperates from [src] and [attacker], ending the battle.", \ + " You separate [attacker] and [src], ending the battle. ") + return FALSE + + //if all that is good, then we can sleep peacefully + sleep(delay) + return TRUE + +//all credit to skasi for toy mech fun ideas +/obj/item/toy/prize/attack_self(mob/user) + if(timer < world.time) + to_chat(user, "You play with [src].") + timer = world.time + cooldown + if(!quiet) + playsound(user, 'sound/mecha/mechstep.ogg', 20, TRUE) + else + . = ..() + +/obj/item/toy/prize/attack_hand(mob/user) + . = ..() + if(.) + return + if(loc == user) + attack_self(user) + +/** + * If you attack a mech with a mech, initiate combat between them + */ +/obj/item/toy/prize/attackby(obj/item/user_toy, mob/living/user) + if(istype(user_toy, /obj/item/toy/prize)) + var/obj/item/toy/prize/P = user_toy + if(check_battle_start(user, P)) + mecha_brawl(P, user) + ..() + +/** + * Attack is called from the user's toy, aimed at target(another human), checking for target's toy. + */ +/obj/item/toy/prize/attack(mob/living/carbon/human/target, mob/living/carbon/human/user) + if(target == user) + to_chat(user, "Target another toy mech if you want to start a battle with yourself.") + return + else if(user.a_intent != INTENT_HARM) + if(wants_to_battle) //prevent spamming someone with offers + to_chat(user, "You already are offering battle to someone!") + return + if(!check_battle_start(user)) //if the user's mech isn't ready, don't bother checking + return + + for(var/obj/item/I in target.held_items) + if(istype(I, /obj/item/toy/prize)) //if you attack someone with a mech who's also holding a mech, offer to battle them + var/obj/item/toy/prize/P = I + if(!P.check_battle_start(target, null, user)) //check if the attacker mech is ready + break + + //slap them with the metaphorical white glove + if(P.wants_to_battle) //if the target mech wants to battle, initiate the battle from their POV + mecha_brawl(P, target, user) //P = defender's mech / SRC = attacker's mech / target = defender / user = attacker + P.wants_to_battle = FALSE + return + + //extend the offer of battle to the other mech + to_chat(user, "You offer battle to [target.name]!") + to_chat(target, "[user.name] wants to battle with [user.p_their()] [name]! Attack them with a toy mech to initiate combat.") + wants_to_battle = TRUE + addtimer(CALLBACK(src, .proc/withdraw_offer, user), 6 SECONDS) + return + + ..() + +/** + * Overrides attack_tk - Sorry, you have to be face to face to initiate a battle, it's good sportsmanship + */ +/obj/item/toy/prize/attack_tk(mob/user) + if(timer < world.time) + to_chat(user, "You telekinetically play with [src].") + timer = world.time + cooldown + if(!quiet) + playsound(user, 'sound/mecha/mechstep.ogg', 20, TRUE) + +/** + * Resets the request for battle. + * + * For use in a timer, this proc resets the wants_to_battle variable after a short period. + * Arguments: + * * user - the user wanting to do battle + */ +/obj/item/toy/prize/proc/withdraw_offer(mob/living/carbon/user) + if(wants_to_battle) + wants_to_battle = FALSE + to_chat(user, "You get the feeling they don't want to battle.") +/** + * Starts a battle, toy mech vs player. Player... doesn't win. + */ +/obj/item/toy/prize/suicide_act(mob/living/carbon/user) + if(in_combat) + to_chat(user, "[src] is in battle, let it finish first.") + return + + user.visible_message("[user] begins a fight [user.p_they()] can't win with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + + in_combat = TRUE + sleep(1.5 SECONDS) + for(var/i in 1 to 4) + switch(i) + if(1, 3) + SpinAnimation(5, 0) + playsound(src, 'sound/mecha/mechstep.ogg', 30, TRUE) + user.adjustBruteLoss(25) + user.adjustStaminaLoss(50) + if(2) + user.SpinAnimation(5, 0) + playsound(user, 'sound/weapons/smash.ogg', 20, TRUE) + combat_health-- //we scratched it! + if(4) + say(special_attack_cry + "!!") + user.adjustStaminaLoss(25) + + if(!combat_sleep(1 SECONDS, null, user)) + say("PATHETIC.") + combat_health = max_combat_health + in_combat = FALSE + return SHAME + + sleep(0.5 SECONDS) + user.adjustBruteLoss(450) + + in_combat = FALSE + say("AN EASY WIN. MY POWER INCREASES.") // steal a soul, become swole + add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY) + max_combat_health = round(max_combat_health*1.5 + 0.1) + combat_health = max_combat_health + wins++ + return BRUTELOSS + +/obj/item/toy/prize/examine() + . = ..() + . += "This toy's special attack is [special_attack_cry], [special_attack_type_message] " + if(in_combat) + . += "This toy has a maximum health of [max_combat_health]. Currently, it's [combat_health]." + . += "Its special move light is [special_attack_cooldown? "flashing red." : "green and is ready!"]" + else + . += "This toy has a maximum health of [max_combat_health]." + + if(wins || losses) + . += "This toy has [wins] wins, and [losses] losses." + +/** + * Override the say proc if they're mute + */ +/obj/item/toy/prize/say() + if(!quiet) + . = ..() + +/** + * The 'master' proc of the mech battle. Processes the entire battle's events and makes sure it start and finishes correctly. + * + * src is the defending toy, and the battle proc is called on it to begin the battle. + * After going through a few checks at the beginning to ensure the battle can start properly, the battle begins a loop that lasts + * until either toy has no more health. During this loop, it also ensures the mechs stay in combat range of each other. + * It will then randomly decide attacks for each toy, occasionally making one or the other use their special attack. + * When either mech has no more health, the loop ends, and it displays the victor and the loser while updating their stats and resetting them. + * Arguments: + * * attacker - the attacking toy, the toy in the attacker_controller's hands + * * attacker_controller - the user, the one who is holding the toys / controlling the fight + * * opponent - optional arg used in Mech PvP battles: the other person who is taking part in the fight (controls src) + */ +/obj/item/toy/prize/proc/mecha_brawl(obj/item/toy/prize/attacker, mob/living/carbon/attacker_controller, mob/living/carbon/opponent) + //A GOOD DAY FOR A SWELL BATTLE! + attacker_controller.visible_message(" [attacker_controller.name] collides [attacker] with [src]! Looks like they're preparing for a brawl! ", \ + " You collide [attacker] into [src], sparking a fierce battle! ", \ + " You hear hard plastic smacking into hard plastic.", COMBAT_MESSAGE_RANGE) + + /// Who's in control of the defender (src)? + var/mob/living/carbon/src_controller = (opponent)? opponent : attacker_controller + /// How long has the battle been going? + var/battle_length = 0 + + in_combat = TRUE + attacker.in_combat = TRUE + + //1.5 second cooldown * 20 = 30 second cooldown after a fight + timer = world.time + cooldown*cooldown_multiplier + attacker.timer = world.time + attacker.cooldown*attacker.cooldown_multiplier + + sleep(1 SECONDS) + //--THE BATTLE BEGINS-- + while(combat_health > 0 && attacker.combat_health > 0 && battle_length < MAX_BATTLE_LENGTH) + if(!combat_sleep(0.5 SECONDS, attacker, attacker_controller, opponent)) //combat_sleep checks everything we need to have checked for combat to continue + break + + //before we do anything - deal with charged attacks + if(special_attack_charged) + src_controller.visible_message(" [src] unleashes its special attack!! ", \ + " You unleash [src]'s special attack! ") + special_attack_move(attacker) + else if(attacker.special_attack_charged) + + attacker_controller.visible_message(" [attacker] unleashes its special attack!! ", \ + " You unleash [attacker]'s special attack! ") + attacker.special_attack_move(src) + else + //process the cooldowns + if(special_attack_cooldown > 0) + special_attack_cooldown-- + if(attacker.special_attack_cooldown > 0) + attacker.special_attack_cooldown-- + + //combat commences + switch(rand(1,8)) + if(1 to 3) //attacker wins + if(attacker.special_attack_cooldown == 0 && attacker.combat_health <= round(attacker.max_combat_health/3)) //if health is less than 1/3 and special off CD, use it + attacker.special_attack_charged = TRUE + attacker_controller.visible_message(" [attacker] begins charging its special attack!! ", \ + " You begin charging [attacker]'s special attack! ") + else //just attack + attacker.SpinAnimation(5, 0) + playsound(attacker, 'sound/mecha/mechstep.ogg', 30, TRUE) + combat_health-- + attacker_controller.visible_message(" [attacker] devastates [src]! ", \ + " You ram [attacker] into [src]! ", \ + " You hear hard plastic smacking hard plastic.", COMBAT_MESSAGE_RANGE) + if(prob(5)) + combat_health-- + playsound(src, 'sound/effects/meteorimpact.ogg', 20, TRUE) + attacker_controller.visible_message(" ...and lands a CRIPPLING BLOW! ", \ + " ...and you land a CRIPPLING blow on [src]! ", null, COMBAT_MESSAGE_RANGE) + + if(4) //both lose + attacker.SpinAnimation(5, 0) + SpinAnimation(5, 0) + combat_health-- + attacker.combat_health-- + do_sparks(2, FALSE, src) + do_sparks(2, FALSE, attacker) + if(prob(50)) + attacker_controller.visible_message(" [attacker] and [src] clash dramatically, causing sparks to fly! ", \ + " [attacker] and [src] clash dramatically, causing sparks to fly! ", \ + " You hear hard plastic rubbing against hard plastic.", COMBAT_MESSAGE_RANGE) + else + src_controller.visible_message(" [src] and [attacker] clash dramatically, causing sparks to fly! ", \ + " [src] and [attacker] clash dramatically, causing sparks to fly! ", \ + " You hear hard plastic rubbing against hard plastic.", COMBAT_MESSAGE_RANGE) + if(5) //both win + playsound(attacker, 'sound/weapons/parry.ogg', 20, TRUE) + if(prob(50)) + attacker_controller.visible_message(" [src]'s attack deflects off of [attacker]. ", \ + " [src]'s attack deflects off of [attacker]. ", \ + " You hear hard plastic bouncing off hard plastic.", COMBAT_MESSAGE_RANGE) + else + src_controller.visible_message(" [attacker]'s attack deflects off of [src]. ", \ + " [attacker]'s attack deflects off of [src]. ", \ + " You hear hard plastic bouncing off hard plastic.", COMBAT_MESSAGE_RANGE) + + if(6 to 8) //defender wins + if(special_attack_cooldown == 0 && combat_health <= round(max_combat_health/3)) //if health is less than 1/3 and special off CD, use it + special_attack_charged = TRUE + src_controller.visible_message(" [src] begins charging its special attack!! ", \ + " You begin charging [src]'s special attack! ") + else //just attack + SpinAnimation(5, 0) + playsound(src, 'sound/mecha/mechstep.ogg', 30, TRUE) + attacker.combat_health-- + src_controller.visible_message(" [src] smashes [attacker]! ", \ + " You smash [src] into [attacker]! ", \ + " You hear hard plastic smashing hard plastic.", COMBAT_MESSAGE_RANGE) + if(prob(5)) + attacker.combat_health-- + playsound(attacker, 'sound/effects/meteorimpact.ogg', 20, TRUE) + src_controller.visible_message(" ...and lands a CRIPPLING BLOW! ", \ + " ...and you land a CRIPPLING blow on [attacker]! ", null, COMBAT_MESSAGE_RANGE) + else + attacker_controller.visible_message(" [src] and [attacker] stand around awkwardly.", \ + " You don't know what to do next.") + + battle_length++ + sleep(0.5 SECONDS) + + /// Lines chosen for the winning mech + var/list/winlines = list("YOU'RE NOTHING BUT SCRAP!", "I'LL YIELD TO NONE!", "GLORY IS MINE!", "AN EASY FIGHT.", "YOU SHOULD HAVE NEVER FACED ME.", "ROCKED AND SOCKED.") + + if(attacker.combat_health <= 0 && combat_health <= 0) //both lose + playsound(src, 'sound/machines/warning-buzzer.ogg', 20, TRUE) + attacker_controller.visible_message(" MUTUALLY ASSURED DESTRUCTION!! [src] and [attacker] both end up destroyed!", \ + " Both [src] and [attacker] are destroyed!") + else if(attacker.combat_health <= 0) //src wins + wins++ + attacker.losses++ + playsound(attacker, 'sound/effects/light_flicker.ogg', 20, TRUE) + attacker_controller.visible_message(" [attacker] falls apart!", \ + " [attacker] falls apart!", null, COMBAT_MESSAGE_RANGE) + say("[pick(winlines)]") + src_controller.visible_message(" [src] destroys [attacker] and walks away victorious!", \ + " You raise up [src] victoriously over [attacker]!") + else if (combat_health <= 0) //attacker wins + attacker.wins++ + losses++ + playsound(src, 'sound/effects/light_flicker.ogg', 20, TRUE) + src_controller.visible_message(" [src] collapses!", \ + " [src] collapses!", null, COMBAT_MESSAGE_RANGE) + attacker.say("[pick(winlines)]") + attacker_controller.visible_message(" [attacker] demolishes [src] and walks away victorious!", \ + " You raise up [attacker] proudly over [src]!") + else //both win? + say("NEXT TIME.") + //don't want to make this a one sided conversation + quiet? attacker.say("I WENT EASY ON YOU.") : attacker.say("OF COURSE.") + + in_combat = FALSE + attacker.in_combat = FALSE + + combat_health = max_combat_health + attacker.combat_health = attacker.max_combat_health + + return + +/** + * This proc checks if a battle can be initiated between src and attacker. + * + * Both SRC and attacker (if attacker is included) timers are checked if they're on cooldown, and + * both SRC and attacker (if attacker is included) are checked if they are in combat already. + * If any of the above are true, the proc returns FALSE and sends a message to user (and target, if included) otherwise, it returns TRUE + * Arguments: + * * user: the user who is initiating the battle + * * attacker: optional arg for checking two mechs at once + * * target: optional arg used in Mech PvP battles (if used, attacker is target's toy) + */ +/obj/item/toy/prize/proc/check_battle_start(mob/living/carbon/user, obj/item/toy/prize/attacker, mob/living/carbon/target) + if(attacker && attacker.in_combat) + to_chat(user, "[target?target.p_their() : "Your" ] [attacker.name] is in combat.") + target?.to_chat(target, "Your [attacker.name] is in combat.") + return FALSE + if(in_combat) + to_chat(user, "Your [name] is in combat.") + target?.to_chat(target, "[target.p_their()] [name] is in combat.") + return FALSE + if(attacker && attacker.timer > world.time) + to_chat(user, "[target?target.p_their() : "Your" ] [attacker.name] isn't ready for battle.") + target?.to_chat(target, "Your [attacker.name] isn't ready for battle.") + return FALSE + if(timer > world.time) + to_chat(user, "Your [name] isn't ready for battle.") + target?.to_chat(target, "[target.p_their()] [name] isn't ready for battle.") + return FALSE + + return TRUE + +/** + * Processes any special attack moves that happen in the battle (called in the mechaBattle proc). + * + * Makes the toy shout their special attack cry and updates its cooldown. Then, does the special attack. + * Arguments: + * * victim - the toy being hit by the special move + */ +/obj/item/toy/prize/proc/special_attack_move(obj/item/toy/prize/victim) + say(special_attack_cry + "!!") + + special_attack_charged = FALSE + special_attack_cooldown = 3 + + switch(special_attack_type) + if(SPECIAL_ATTACK_DAMAGE) //+2 damage + victim.combat_health-=2 + playsound(src, 'sound/weapons/marauder.ogg', 20, TRUE) + if(SPECIAL_ATTACK_HEAL) //+2 healing + combat_health+=2 + playsound(src, 'sound/mecha/mech_shield_raise.ogg', 20, TRUE) + if(SPECIAL_ATTACK_UTILITY) //+1 heal, +1 damage + victim.combat_health-- + combat_health++ + playsound(src, 'sound/mecha/mechmove01.ogg', 30, TRUE) + if(SPECIAL_ATTACK_OTHER) //other + super_special_attack(victim) + else + say("I FORGOT MY SPECIAL ATTACK...") + +/** + * Base proc for 'other' special attack moves. + * + * This one is only for inheritance, each mech with an 'other' type move has their procs below. + * Arguments: + * * victim - the toy being hit by the super special move (doesn't necessarily need to be used) + */ +/obj/item/toy/prize/proc/super_special_attack(obj/item/toy/prize/victim) + visible_message(" [src] does a cool flip.") + +/obj/item/toy/prize/ripley + name = "toy Ripley" + desc = "1/13" + max_combat_health = 4 //200 integrity + special_attack_type = SPECIAL_ATTACK_DAMAGE + special_attack_cry = "GIGA DRILL BREAK" + +/obj/item/toy/prize/fireripley //rip + name = "toy Firefighting Ripley" + desc = "2/13" + icon_state = "fireripleytoy" + max_combat_health = 5 //250 integrity? + special_attack_type = SPECIAL_ATTACK_UTILITY + special_attack_cry = "FIRE SHIELD" + +/obj/item/toy/prize/deathripley + name = "toy Deathsquad Ripley" + desc = "3/13" + icon_state = "deathripleytoy" + max_combat_health = 5 //250 integrity + special_attack_type = SPECIAL_ATTACK_OTHER + special_attack_type_message = "instantly destroys the opposing mech if its health is less than this mech's health." + special_attack_cry = "KILLER CLAMP" + +/obj/item/toy/prize/deathripley/super_special_attack(obj/item/toy/prize/victim) + playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 20, TRUE) + if(victim.combat_health < combat_health) //Instantly kills the other mech if it's health is below our's. + say("EXECUTE!!") + victim.combat_health = 0 + else //Otherwise, just deal one damage. + victim.combat_health-- + +/obj/item/toy/prize/gygax + name = "toy Gygax" + desc = "4/13" + icon_state = "gygaxtoy" + max_combat_health = 5 //250 integrity + special_attack_type = SPECIAL_ATTACK_UTILITY + special_attack_cry = "SUPER SERVOS" + +/obj/item/toy/prize/durand + name = "toy Durand" + desc = "5/13" + icon_state = "durandtoy" + max_combat_health = 6 //400 integrity + special_attack_type = SPECIAL_ATTACK_HEAL + special_attack_cry = "SHIELD OF PROTECTION" + +/obj/item/toy/prize/honk + name = "toy H.O.N.K." + desc = "6/13" + icon_state = "honktoy" + max_combat_health = 4 //140 integrity + special_attack_type = SPECIAL_ATTACK_OTHER + special_attack_type_message = "puts the opposing mech's special move on cooldown and heals this mech." + special_attack_cry = "MEGA HORN" + +/obj/item/toy/prize/honk/super_special_attack(obj/item/toy/prize/victim) + playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 20, TRUE) + victim.special_attack_cooldown += 3 //Adds cooldown to the other mech and gives a minor self heal + combat_health++ + +/obj/item/toy/prize/marauder + name = "toy Marauder" + desc = "7/13" + icon_state = "maraudertoy" + max_combat_health = 7 //500 integrity + special_attack_type = SPECIAL_ATTACK_DAMAGE + special_attack_cry = "BEAM BLAST" + +/obj/item/toy/prize/seraph + name = "toy Seraph" + desc = "8/13" + icon_state = "seraphtoy" + max_combat_health = 8 //550 integrity + special_attack_type = SPECIAL_ATTACK_DAMAGE + special_attack_cry = "ROCKET BARRAGE" + +/obj/item/toy/prize/mauler + name = "toy Mauler" + desc = "9/13" + icon_state = "maulertoy" + max_combat_health = 7 //500 integrity + special_attack_type = SPECIAL_ATTACK_DAMAGE + special_attack_cry = "BULLET STORM" + +/obj/item/toy/prize/odysseus + name = "toy Odysseus" + desc = "10/13" + icon_state = "odysseustoy" + max_combat_health = 4 //120 integrity + special_attack_type = SPECIAL_ATTACK_HEAL + special_attack_cry = "MECHA BEAM" + +/obj/item/toy/prize/phazon + name = "toy Phazon" + desc = "11/13" + icon_state = "phazontoy" + max_combat_health = 6 //200 integrity + special_attack_type = SPECIAL_ATTACK_UTILITY + special_attack_cry = "NO-CLIP" + +/obj/item/toy/prize/reticence + name = "toy Reticence" + desc = "12/13" + icon_state = "reticencetoy" + quiet = TRUE + max_combat_health = 4 //100 integrity + special_attack_type = SPECIAL_ATTACK_OTHER + special_attack_type_message = "has a lower cooldown than normal special moves, increases the opponent's cooldown, and deals damage." + special_attack_cry = "*wave" + +/obj/item/toy/prize/reticence/super_special_attack(obj/item/toy/prize/victim) + special_attack_cooldown-- //Has a lower cooldown... + victim.special_attack_cooldown++ //and increases the opponent's cooldown by 1... + victim.combat_health-- //and some free damage. + +/obj/item/toy/prize/clarke + name = "toy Clarke" + desc = "13/13" + icon_state = "clarketoy" + max_combat_health = 4 //200 integrity + special_attack_type = SPECIAL_ATTACK_UTILITY + special_attack_cry = "ROLL OUT" + +#undef SPECIAL_ATTACK_HEAL +#undef SPECIAL_ATTACK_DAMAGE +#undef SPECIAL_ATTACK_UTILITY +#undef SPECIAL_ATTACK_OTHER +#undef MAX_BATTLE_LENGTH diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index c3e0071d980..ef2a6697ff8 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -7,7 +7,6 @@ * Toy swords * Crayons * Snap pops - * Mech prizes * AI core prizes * Toy codex gigas * Skeleton toys @@ -26,7 +25,6 @@ * Broken Radio */ - /obj/item/toy throwforce = 0 throw_speed = 3 @@ -519,100 +517,6 @@ new /obj/item/toy/snappop/phoenix(get_turf(src)) qdel(src) - -/* - * Mech prizes - */ -/obj/item/toy/prize - icon = 'icons/obj/toy.dmi' - icon_state = "ripleytoy" - var/timer = 0 - var/cooldown = 30 - var/quiet = 0 - w_class = WEIGHT_CLASS_SMALL - -//all credit to skasi for toy mech fun ideas -/obj/item/toy/prize/attack_self(mob/user) - if(timer < world.time) - to_chat(user, "You play with [src].") - timer = world.time + cooldown - if(!quiet) - playsound(user, 'sound/mecha/mechstep.ogg', 20, TRUE) - else - . = ..() - -/obj/item/toy/prize/attack_hand(mob/user) - . = ..() - if(.) - return - if(loc == user) - attack_self(user) - -/obj/item/toy/prize/ripley - name = "toy Ripley" - desc = "Mini-Mecha action figure! Collect them all! 1/13." - -/obj/item/toy/prize/fireripley - name = "toy firefighting Ripley" - desc = "Mini-Mecha action figure! Collect them all! 2/13." - icon_state = "fireripleytoy" - -/obj/item/toy/prize/deathripley - name = "toy deathsquad Ripley" - desc = "Mini-Mecha action figure! Collect them all! 3/13." - icon_state = "deathripleytoy" - -/obj/item/toy/prize/gygax - name = "toy Gygax" - desc = "Mini-Mecha action figure! Collect them all! 4/13." - icon_state = "gygaxtoy" - -/obj/item/toy/prize/durand - name = "toy Durand" - desc = "Mini-Mecha action figure! Collect them all! 5/13." - icon_state = "durandtoy" - -/obj/item/toy/prize/honk - name = "toy H.O.N.K." - desc = "Mini-Mecha action figure! Collect them all! 6/13." - icon_state = "honktoy" - -/obj/item/toy/prize/marauder - name = "toy Marauder" - desc = "Mini-Mecha action figure! Collect them all! 7/13." - icon_state = "maraudertoy" - -/obj/item/toy/prize/seraph - name = "toy Seraph" - desc = "Mini-Mecha action figure! Collect them all! 8/13." - icon_state = "seraphtoy" - -/obj/item/toy/prize/mauler - name = "toy Mauler" - desc = "Mini-Mecha action figure! Collect them all! 9/13." - icon_state = "maulertoy" - -/obj/item/toy/prize/odysseus - name = "toy Odysseus" - desc = "Mini-Mecha action figure! Collect them all! 10/13." - icon_state = "odysseustoy" - -/obj/item/toy/prize/phazon - name = "toy Phazon" - desc = "Mini-Mecha action figure! Collect them all! 11/13." - icon_state = "phazontoy" - -/obj/item/toy/prize/reticence - name = "toy Reticence" - desc = "Mini-Mecha action figure! Collect them all! 12/13." - icon_state = "reticencetoy" - quiet = 1 - -/obj/item/toy/prize/clarke - name = "toy Clarke" - desc = "Mini-Mecha action figure! Collect them all! 13/13." - icon_state = "clarketoy" - /obj/item/toy/talking name = "talking action figure" desc = "A generic action figure modeled after nothing in particular." diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 9679a682316..e6bf3cc5bb6 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -91,6 +91,10 @@ return TRUE /obj/blob_act(obj/structure/blob/B) + if(isturf(loc)) + var/turf/T = loc + if(T.intact && HAS_TRAIT(src, TRAIT_T_RAY_VISIBLE)) + return take_damage(400, BRUTE, "melee", 0, get_dir(src, B)) /obj/proc/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, armor_penetration = 0) //used by attack_alien, attack_animal, and attack_slime @@ -198,6 +202,10 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e ///Called when the obj is exposed to fire. /obj/fire_act(exposed_temperature, exposed_volume) + if(isturf(loc)) + var/turf/T = loc + if(T.intact && HAS_TRAIT(src, TRAIT_T_RAY_VISIBLE)) + return if(exposed_temperature && !(resistance_flags & FIRE_PROOF)) take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, "fire", 0) if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE) && !(resistance_flags & FIRE_PROOF)) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index eb8de6fa75e..a698dc2c0a7 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -46,11 +46,6 @@ update_icon() PopulateContents() - RegisterSignal(src, COMSIG_ATOM_CANREACH, .proc/canreach_react) - -/obj/structure/closet/proc/canreach_react(datum/source, list/next) - return COMPONENT_BLOCK_REACH //closed block, open have nothing inside. - //USE THIS TO FILL IT, NOT INITIALIZE OR NEW /obj/structure/closet/proc/PopulateContents() return @@ -61,6 +56,8 @@ /obj/structure/closet/update_icon() . = ..() + if (istype(src, /obj/structure/closet/supplypod)) + return if(!opened) layer = OBJ_LAYER else @@ -337,8 +334,11 @@ var/mob/living/L = O if(!issilicon(L)) L.Paralyze(40) - O.forceMove(T) - close() + if(istype(src, /obj/structure/closet/supplypod/extractionpod)) + O.forceMove(src) + else + O.forceMove(T) + close() else O.forceMove(T) return 1 diff --git a/code/game/objects/structures/divine.dm b/code/game/objects/structures/divine.dm index d81a6ac4a86..5ce0f75850d 100644 --- a/code/game/objects/structures/divine.dm +++ b/code/game/objects/structures/divine.dm @@ -1,22 +1,22 @@ /obj/structure/sacrificealtar name = "sacrificial altar" - desc = "An altar designed to perform blood sacrifice for a deity." + desc = "An altar designed to perform blood sacrifice for a deity. Alt-click it to sacrifice a buckled creature." icon = 'icons/obj/hand_of_god_structures.dmi' icon_state = "sacrificealtar" anchored = TRUE density = FALSE can_buckle = 1 -/obj/structure/sacrificealtar/attack_hand(mob/living/user) - . = ..() - if(.) +/obj/structure/sacrificealtar/AltClick(mob/living/user) + ..() + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE)) return if(!has_buckled_mobs()) return var/mob/living/L = locate() in buckled_mobs if(!L) return - to_chat(user, "You attempt to sacrifice [L] by invoking the sacrificial ritual.") + to_chat(user, "Invoking the sacred ritual, you sacrifice [L].") L.gib() message_admins("[ADMIN_LOOKUPFLW(user)] has sacrificed [key_name_admin(L)] on the sacrificial altar at [AREACOORD(src)].") diff --git a/code/game/objects/structures/headpike.dm b/code/game/objects/structures/headpike.dm index ffdaf86bde5..df5ce50d5da 100644 --- a/code/game/objects/structures/headpike.dm +++ b/code/game/objects/structures/headpike.dm @@ -13,15 +13,46 @@ icon_state = "headpike-bone" bonespear = TRUE +/obj/structure/headpike/Initialize(mapload) + . = ..() + if(mapload) + CheckParts() + /obj/structure/headpike/CheckParts(list/parts_list) ..() victim = locate(/obj/item/bodypart/head) in parts_list - name = "[victim.name] on a spear" + if(!victim) //likely a mapspawned one + victim = new(src) + victim.real_name = random_unique_name(prob(50)) + name = "[victim.real_name] on a spear" update_icon() - if(bonespear) - spear = locate(/obj/item/spear/bonespear) in parts_list - else - spear = locate(/obj/item/spear) in parts_list + spear = locate(bonespear ? /obj/item/spear/bonespear : /obj/item/spear) in parts_list + if(!spear) + spear = bonespear ? new/obj/item/spear/bonespear(src) : new/obj/item/spear(src) + +/obj/structure/headpike/Destroy() + QDEL_NULL(victim) + QDEL_NULL(spear) + return ..() + +/obj/structure/headpike/handle_atom_del(atom/A) + if(A == victim) + victim = null + if(A == spear) + spear = null + deconstruct(TRUE) + return ..() + +/obj/structure/headpike/deconstruct(disassembled) + if(!disassembled) + return ..() + if(victim) + victim.forceMove(drop_location()) + victim = null + if(spear) + spear.forceMove(drop_location()) + spear = null + return ..() /obj/structure/headpike/Initialize() . = ..() @@ -41,9 +72,4 @@ if(.) return to_chat(user, "You take down [src].") - if(victim) - victim.forceMove(drop_location()) - victim = null - spear.forceMove(drop_location()) - spear = null - qdel(src) + deconstruct(TRUE) diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index 63fae9f4548..a1bdf9fa198 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -7,6 +7,7 @@ anchored = TRUE var/obj/structure/ladder/down //the ladder below this one var/obj/structure/ladder/up //the ladder above this one + obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN /obj/structure/ladder/Initialize(mapload, obj/structure/ladder/up, obj/structure/ladder/down) ..() diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index a977b077a4c..75595234a14 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -17,6 +17,7 @@ /obj/structure/falsewall) smooth = SMOOTH_MORE // flags = CONDUCT_1 + obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN /obj/structure/lattice/examine(mob/user) . = ..() @@ -77,7 +78,7 @@ number_of_mats = 2 smooth = SMOOTH_TRUE canSmoothWith = null - obj_flags = CAN_BE_HIT | BLOCK_Z_FALL + obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP /obj/structure/lattice/catwalk/deconstruction_hints(mob/user) return "The supporting rods look like they could be cut." @@ -103,7 +104,7 @@ color = "#5286b9ff" smooth = SMOOTH_TRUE canSmoothWith = null - obj_flags = CAN_BE_HIT | BLOCK_Z_FALL + obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP resistance_flags = FIRE_PROOF | LAVA_PROOF /obj/structure/lattice/lava/deconstruction_hints(mob/user) diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index 19a943d20f4..d7b0958e8c5 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -67,20 +67,21 @@ return TRUE /obj/structure/railing/CanPass(atom/movable/mover, turf/target) - ..() + . = ..() if(get_dir(loc, target) & dir) - var/checking = UNSTOPPABLE | FLYING | FLOATING - return !density || mover.movement_type & checking + var/checking = FLYING | FLOATING + return . || mover.movement_type & checking return TRUE /obj/structure/railing/corner/CanPass() ..() return TRUE -/obj/structure/railing/CheckExit(atom/movable/O, turf/target) +/obj/structure/railing/CheckExit(atom/movable/mover, turf/target) ..() if(get_dir(loc, target) & dir) - return FALSE + var/checking = UNSTOPPABLE | FLYING | FLOATING + return !density || mover.movement_type & checking || mover.move_force >= MOVE_FORCE_EXTREMELY_STRONG return TRUE /obj/structure/railing/corner/CheckExit() diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index 29d560d952f..eada9138ebd 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -18,11 +18,21 @@ //direction is direction of travel of A /turf/open/zPassIn(atom/movable/A, direction, turf/source) - return (direction == DOWN) + if(direction == DOWN) + for(var/obj/O in contents) + if(O.obj_flags & BLOCK_Z_IN_DOWN) + return FALSE + return TRUE + return FALSE //direction is direction of travel of A /turf/open/zPassOut(atom/movable/A, direction, turf/destination) - return (direction == UP) + if(direction == UP) + for(var/obj/O in contents) + if(O.obj_flags & BLOCK_Z_OUT_UP) + return FALSE + return TRUE + return FALSE //direction is direction of travel of air /turf/open/zAirIn(direction, turf/source) diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index 6a1e793f711..ae4ed0d5044 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -44,7 +44,9 @@ . = ..() if(isliving(Obj)) var/mob/living/L = Obj - if(!islava(newloc) && !L.on_fire) + if(!islava(newloc)) + REMOVE_TRAIT(L, TRAIT_PERMANENTLY_ONFIRE, TURF_TRAIT) + if(!L.on_fire) L.update_fire() /turf/open/lava/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) @@ -156,9 +158,6 @@ if("lava" in live.weather_immunities) continue - if(!L.on_fire) - L.update_fire() - if(iscarbon(L)) var/mob/living/carbon/C = L var/obj/item/clothing/S = C.get_item_by_slot(ITEM_SLOT_OCLOTHING) @@ -170,6 +169,9 @@ if("lava" in L.weather_immunities) continue + ADD_TRAIT(L, TRAIT_PERMANENTLY_ONFIRE,TURF_TRAIT) + L.update_fire() + L.adjustFireLoss(20) if(L) //mobs turning into object corpses could get deleted here. L.adjust_fire_stacks(20) diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm index 359450d994a..9c4ed110e4c 100644 --- a/code/game/turfs/open/openspace.dm +++ b/code/game/turfs/open/openspace.dm @@ -51,15 +51,32 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr return TRUE /turf/open/transparent/openspace/zPassIn(atom/movable/A, direction, turf/source) - return TRUE + if(direction == DOWN) + for(var/obj/O in contents) + if(O.obj_flags & BLOCK_Z_IN_DOWN) + return FALSE + return TRUE + if(direction == UP) + for(var/obj/O in contents) + if(O.obj_flags & BLOCK_Z_IN_UP) + return FALSE + return TRUE + return FALSE /turf/open/transparent/openspace/zPassOut(atom/movable/A, direction, turf/destination) if(A.anchored) return FALSE - for(var/obj/O in contents) - if(O.obj_flags & BLOCK_Z_FALL) - return FALSE - return TRUE + if(direction == DOWN) + for(var/obj/O in contents) + if(O.obj_flags & BLOCK_Z_OUT_DOWN) + return FALSE + return TRUE + if(direction == UP) + for(var/obj/O in contents) + if(O.obj_flags & BLOCK_Z_OUT_UP) + return FALSE + return TRUE + return FALSE /turf/open/transparent/openspace/proc/CanCoverUp() return can_cover_up @@ -80,6 +97,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr return if(L) if(R.use(1)) + qdel(L) to_chat(user, "You construct a catwalk.") playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) new/obj/structure/lattice/catwalk(src) diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index acdd4c364ce..65e369d9181 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -115,6 +115,7 @@ return if(L) if(R.use(1)) + qdel(L) to_chat(user, "You construct a catwalk.") playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) new/obj/structure/lattice/catwalk(src) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 30ca4c4604e..12aacf7d943 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -389,7 +389,7 @@ GLOBAL_LIST_EMPTY(station_turfs) /turf/singularity_act() if(intact) for(var/obj/O in contents) //this is for deleting things like wires contained in the turf - if(O.invisibility == INVISIBILITY_MAXIMUM) + if(HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) O.singularity_act() ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return(2) @@ -473,6 +473,8 @@ GLOBAL_LIST_EMPTY(station_turfs) acid_type = /obj/effect/acid/alien var/has_acid_effect = FALSE for(var/obj/O in src) + if(intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) + return if(istype(O, acid_type)) var/obj/effect/acid/A = O A.acid_level = min(acid_volume * acidpwr, 12000)//capping acid level to limit power of the acid diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 951daece2d3..e2eb887d05e 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -717,7 +717,7 @@ var/obj/structure/closet/supplypod/centcompod/pod = new() var/atom/A = new chosen(pod) A.flags_1 |= ADMIN_SPAWNED_1 - new /obj/effect/dp_target(T, pod) + new /obj/effect/pod_landingzone(T, pod) log_admin("[key_name(usr)] pod-spawned [chosen] at [AREACOORD(usr)]") SSblackbox.record_feedback("tally", "admin_verb", 1, "Podspawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/sql_ban_system.dm b/code/modules/admin/sql_ban_system.dm index d4922e8299c..fe592767843 100644 --- a/code/modules/admin/sql_ban_system.dm +++ b/code/modules/admin/sql_ban_system.dm @@ -838,12 +838,12 @@ var/datum/db_query/query_edit_ban = SSdbcore.NewQuery({" UPDATE [format_table_name("ban")] SET - expiration_time = IF(:duration IS NULL, NULL, bantime + INTERVAL :duration [interval]) + expiration_time = IF(:duration IS NULL, NULL, bantime + INTERVAL :duration [interval]), applies_to_admins = :applies_to_admins, reason = :reason, ckey = :ckey, ip = INET_ATON(:ip), - computerid = :ci + computerid = :cid, edits = CONCAT(IFNULL(edits,''), :change_message) WHERE [where] "}, arguments) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 12cc7d03783..ccc0d86fffe 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1701,7 +1701,7 @@ R.activate_module(I) if(pod) - new /obj/effect/dp_target(target, pod) + new /obj/effect/pod_landingzone(target, pod) if (number == 1) log_admin("[key_name(usr)] created a [english_list(paths)]") diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 6598df12c60..ad557217dc4 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1069,7 +1069,8 @@ Traitors and the like can also be revived with the previous role mostly intact. ADMIN_PUNISHMENT_NUGGET, ADMIN_PUNISHMENT_CRACK, ADMIN_PUNISHMENT_BLEED, - ADMIN_PUNISHMENT_SCARIFY + ADMIN_PUNISHMENT_SCARIFY, + ADMIN_PUNISHMENT_SHOES ) var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in sortList(punishment_list) @@ -1116,7 +1117,7 @@ Traitors and the like can also be revived with the previous role mostly intact. alert("ERROR: Incorrect / improper path given.") return new delivery(pod) - new /obj/effect/dp_target(get_turf(target), pod) + new /obj/effect/pod_landingzone(get_turf(target), pod) if(ADMIN_PUNISHMENT_SUPPLYPOD) var/datum/centcom_podlauncher/plaunch = new(usr) if(!holder) @@ -1180,6 +1181,16 @@ Traitors and the like can also be revived with the previous role mostly intact. var/mob/living/carbon/C = target C.generate_fake_scars(rand(1, 4)) to_chat(C, "You feel your body grow jaded and torn...") + if(ADMIN_PUNISHMENT_SHOES) + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) + return + var/mob/living/carbon/C = target + var/obj/item/clothing/shoes/sick_kicks = C.shoes + if(!sick_kicks?.can_be_tied) + to_chat(usr,"[C] does not have knottable shoes!", confidential = TRUE) + return + sick_kicks.adjust_laces(SHOES_KNOTTED) punish_log(target, punishment) diff --git a/code/modules/antagonists/blob/blob_mobs.dm b/code/modules/antagonists/blob/blob_mobs.dm index bb79a4e9eef..31d1ca09393 100644 --- a/code/modules/antagonists/blob/blob_mobs.dm +++ b/code/modules/antagonists/blob/blob_mobs.dm @@ -34,12 +34,17 @@ verbs -= /mob/living/verb/pulled else pass_flags &= ~PASSBLOB - + /mob/living/simple_animal/hostile/blob/Destroy() if(overmind) overmind.blob_mobs -= src return ..() +/mob/living/simple_animal/hostile/blob/Stat() + ..() + if(overmind && statpanel("Status")) + stat(null, "Blobs to Win: [overmind.blobs_legit.len]/[overmind.blobwincount]") + /mob/living/simple_animal/hostile/blob/blob_act(obj/structure/blob/B) if(stat != DEAD && health < maxHealth) for(var/i in 1 to 2) @@ -112,12 +117,12 @@ var/is_zombie = FALSE /mob/living/simple_animal/hostile/blob/blobspore/Initialize(mapload, obj/structure/blob/factory/linked_node) + . = ..() if(istype(linked_node)) factory = linked_node factory.spores += src - . = ..() - if(linked_node.overmind && istype(linked_node.overmind.blobstrain, /datum/blobstrain/reagent/distributed_neurons) && !istype(src, /mob/living/simple_animal/hostile/blob/blobspore/weak)) - notify_ghosts("A controllable spore has been created in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Sentient Spore Created") + if(linked_node.overmind && istype(linked_node.overmind.blobstrain, /datum/blobstrain/reagent/distributed_neurons) && !istype(src, /mob/living/simple_animal/hostile/blob/blobspore/weak)) + notify_ghosts("A controllable spore has been created in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Sentient Spore Created") /mob/living/simple_animal/hostile/blob/blobspore/Life() if(!is_zombie && isturf(src.loc)) @@ -127,8 +132,8 @@ break if(factory && z != factory.z) death() - ..() - + return ..() + /mob/living/simple_animal/hostile/blob/blobspore/attack_ghost(mob/user) . = ..() if(.) @@ -201,9 +206,9 @@ /mob/living/simple_animal/hostile/blob/blobspore/Destroy() if(factory) factory.spores -= src - factory = null + factory = null if(oldguy) - oldguy.forceMove(get_turf(src)) + oldguy.forceMove(loc) oldguy = null return ..() diff --git a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm index c3c80c08cbf..345d767e0e4 100644 --- a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm +++ b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm @@ -2,9 +2,9 @@ /datum/blobstrain/reagent/reactive_spines name = "Reactive Spines" description = "will do medium brute damage through armor and bio resistance." - effectdesc = "will also react when attacked with close up burn or brute damage, attacking all near the attacked blob." + effectdesc = "will also react when attacked with burn or brute damage, attacking everything in melee range." analyzerdescdamage = "Does medium brute damage, ignoring armor and bio resistance." - analyzerdesceffect = "When attacked with brute damage, will lash out, attacking everything near it." + analyzerdesceffect = "When attacked with burn or brute damage it violently lashes out, attacking everything nearby." color = "#9ACD32" complementary_color = "#FFA500" blobbernaut_message = "stabs" @@ -12,7 +12,7 @@ reagent = /datum/reagent/blob/reactive_spines /datum/blobstrain/reagent/reactive_spines/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag) - if(damage && ((damage_type == BRUTE) || (damage_type == BURN)) && B.obj_integrity - damage > 0) //is there any damage, is it brute, and will we be alive + if(damage && ((damage_type == BRUTE) || (damage_type == BURN)) && B.obj_integrity - damage > 0) //is there any damage, is it burn or brute, and will we be alive if(damage_flag == "melee") B.visible_message("The blob retaliates, lashing out!") for(var/atom/A in range(1, B)) diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index 750bd15dbbe..8425029cace 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -81,7 +81,7 @@ if(chosen_node) forceMove(chosen_node.loc) -/mob/camera/blob/proc/createSpecial(price, blobstrain, nearEquals, needsNode, turf/T) +/mob/camera/blob/proc/createSpecial(price, blobstrain, minSeparation, needsNode, turf/T) if(!T) T = get_turf(src) var/obj/structure/blob/B = (locate(/obj/structure/blob) in T) @@ -91,14 +91,18 @@ if(!istype(B, /obj/structure/blob/normal)) to_chat(src, "Unable to use this blob, find a normal one.") return - if(needsNode && nodes_required) - if(!(locate(/obj/structure/blob/node) in orange(3, T)) && !(locate(/obj/structure/blob/core) in orange(4, T))) + if(needsNode) + var/area/A = get_area(src) + if(!A.blob_allowed) //factory and resource blobs must be legit + to_chat(src, "This type of blob must be placed on the station!") + return + if(nodes_required && !(locate(/obj/structure/blob/node) in orange(3, T)) && !(locate(/obj/structure/blob/core) in orange(4, T))) to_chat(src, "You need to place this blob closer to a node or core!") return //handholdotron 2000 - if(nearEquals) - for(var/obj/structure/blob/L in orange(nearEquals, T)) + if(minSeparation) + for(var/obj/structure/blob/L in orange(minSeparation, T)) if(L.type == blobstrain) - to_chat(src, "There is a similar blob nearby, move more than [nearEquals] tiles away from it!") + to_chat(src, "There is a similar blob nearby, move more than [minSeparation] tiles away from it!") return if(!can_buy(price)) return @@ -133,25 +137,25 @@ to_chat(src, "You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced integrity.") S.change_to(/obj/structure/blob/shield/reflective, src) else - createSpecial(15, /obj/structure/blob/shield, 0, 0, T) + createSpecial(15, /obj/structure/blob/shield, 0, FALSE, T) /mob/camera/blob/verb/create_resource() set category = "Blob" set name = "Create Resource Blob (40)" set desc = "Create a resource tower which will generate resources for you." - createSpecial(40, /obj/structure/blob/resource, 4, 1) + createSpecial(40, /obj/structure/blob/resource, 4, TRUE) /mob/camera/blob/verb/create_node() set category = "Blob" set name = "Create Node Blob (50)" set desc = "Create a node, which will power nearby factory and resource blobs." - createSpecial(50, /obj/structure/blob/node, 5, 0) + createSpecial(50, /obj/structure/blob/node, 5, FALSE) /mob/camera/blob/verb/create_factory() set category = "Blob" set name = "Create Factory Blob (60)" set desc = "Create a spore tower that will spawn spores to harass your enemies." - createSpecial(60, /obj/structure/blob/factory, 7, 1) + createSpecial(60, /obj/structure/blob/factory, 7, TRUE) /mob/camera/blob/verb/create_blobbernaut() set category = "Blob" diff --git a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm index e28174ea994..b5ca7c2c330 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm @@ -9,6 +9,7 @@ var/give_equipment = TRUE var/list/researched_knowledge = list() var/total_sacrifices = 0 + var/ascended = FALSE /datum/antagonist/heretic/admin_add(datum/mind/new_owner,mob/admin) give_equipment = FALSE @@ -159,11 +160,13 @@ parts += "Objective #[count]: [objective.explanation_text] Fail." cultiewin = FALSE count++ - - if(cultiewin) - parts += "The heretic was successful!" + if(ascended) + parts += "HERETIC HAS ASCENDED!" else - parts += "The heretic has failed." + if(cultiewin) + parts += "The heretic was successful!" + else + parts += "The heretic has failed." parts += "Knowledge Researched: " diff --git a/code/modules/antagonists/eldritch_cult/eldritch_effects.dm b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm index eac2c97d490..26c5daf3d93 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_effects.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm @@ -5,6 +5,8 @@ icon_state = "" resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF layer = SIGIL_LAYER + ///Used mainly for summoning ritual to prevent spamming the rune to create millions of monsters. + var/is_in_use = FALSE /obj/effect/eldritch/attack_hand(mob/living/user) . = ..() @@ -15,7 +17,8 @@ /obj/effect/eldritch/proc/try_activate(mob/living/user) if(!IS_HERETIC(user)) return - activate(user) + if(!is_in_use) + INVOKE_ASYNC(src, .proc/activate , user) /obj/effect/eldritch/attacked_by(obj/item/I, mob/living/user) . = ..() @@ -23,6 +26,7 @@ qdel(src) /obj/effect/eldritch/proc/activate(mob/living/user) + is_in_use = TRUE // Have fun trying to read this proc. var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic) var/list/knowledge = cultie.get_all_knowledge() @@ -39,7 +43,6 @@ if(living_in_range.stat != DEAD || living_in_range == user) // we only accept corpses, no living beings allowed. continue atoms_in_range += atom_in_range - for(var/X in knowledge) var/datum/eldritch_knowledge/current_eldritch_knowledge = knowledge[X] @@ -70,9 +73,23 @@ flick("[icon_state]_active",src) playsound(user, 'sound/magic/castsummon.ogg', 75, TRUE) + //we are doing this since some on_finished_recipe subtract the atoms from selected_atoms making them invisible permanently. + var/list/atoms_to_disappear = selected_atoms.Copy() + for(var/to_disappear in atoms_to_disappear) + var/atom/atom_to_disappear = to_disappear + //temporary so we dont have to deal with the bs of someone picking those up when they may be deleted + atom_to_disappear.invisibility = INVISIBILITY_ABSTRACT if(current_eldritch_knowledge.on_finished_recipe(user,selected_atoms,loc)) current_eldritch_knowledge.cleanup_atoms(selected_atoms) + is_in_use = FALSE + + for(var/to_appear in atoms_to_disappear) + var/atom/atom_to_appear = to_appear + //we need to reappear the item just in case the ritual didnt consume everything... or something. + atom_to_appear.invisibility = initial(atom_to_appear.invisibility) + return + is_in_use = FALSE to_chat(user,"Your ritual failed! You used either wrong components or are missing something important!") /obj/effect/eldritch/big diff --git a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm index 29387e08b78..20bebbe7a41 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm @@ -88,6 +88,7 @@ for(var/X in atoms) var/atom/A = X if(!isliving(A)) + atoms -= A qdel(A) return @@ -187,9 +188,7 @@ var/datum/antagonist/heretic_monster/heretic_monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster) var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic) heretic_monster.set_owner(master) - //delaying the returning makes the cleanup_atoms break on the rune base, so we are calling it here. - cleanup_atoms(atoms) - return FALSE + return TRUE //Ascension knowledge /datum/eldritch_knowledge/final @@ -213,6 +212,7 @@ /datum/eldritch_knowledge/final/cleanup_atoms(list/atoms) . = ..() for(var/mob/living/carbon/human/H in atoms) + atoms -= H H.gib() diff --git a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm index a2fed5549f4..bac3767ce42 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm @@ -3,7 +3,7 @@ desc = "Low range spell allowing you to pass through a few walls." school = "transmutation" invocation = "ASH'N P'SSG'" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER charge_max = 150 range = -1 action_icon = 'icons/mob/actions/actions_ecult.dmi' @@ -83,7 +83,7 @@ charge_max = 300 //twice as long as mansus grasp clothes_req = FALSE invocation = "A'GRSV SPR'D" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER range = 3 action_icon = 'icons/mob/actions/actions_ecult.dmi' action_icon_state = "corrode" @@ -111,7 +111,7 @@ charge_max = 150 clothes_req = FALSE invocation = "FL'MS O'ET'RN'ITY" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER action_icon = 'icons/mob/actions/actions_ecult.dmi' action_icon_state = "blood_siphon" action_background_icon_state = "bg_ecult" @@ -164,7 +164,7 @@ action_icon_state = "rust_wave" action_background_icon_state = "bg_ecult" invocation = "SPR'D TH' WO'D" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER /obj/projectile/magic/spell/rust_wave name = "Patron's Reach" @@ -211,7 +211,7 @@ charge_max = 350 clothes_req = FALSE invocation = "CL'VE" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER range = 9 action_icon = 'icons/mob/actions/actions_ecult.dmi' action_icon_state = "cleave" @@ -240,10 +240,9 @@ target.visible_message("[target]'s veins are shredded from within as an unholy blaze erupts from their blood!", \ "Your veins burst from within and unholy flame erupts from your blood!") - for(var/repetition in 0 to 2) - var/obj/item/bodypart/bodypart = pick(target.bodyparts) - var/datum/wound/brute/cut/critical/crit_wound = new - crit_wound.apply_wound(bodypart) + var/obj/item/bodypart/bodypart = pick(target.bodyparts) + var/datum/wound/brute/cut/critical/crit_wound = new + crit_wound.apply_wound(bodypart) target.adjustFireLoss(20) new /obj/effect/temp_visual/cleave(target.drop_location()) @@ -299,7 +298,7 @@ desc = "Powerful spell that releases 5 streams of fire away from you." school = "transmutation" invocation = "F'RE" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER charge_max = 300 range = 15 clothes_req = FALSE @@ -362,7 +361,7 @@ /obj/effect/proc_holder/spell/targeted/shapeshift/eldritch invocation = "SH'PE" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER clothes_req = FALSE action_background_icon_state = "bg_ecult" possible_shapes = list(/mob/living/simple_animal/mouse,\ @@ -375,7 +374,7 @@ /obj/effect/proc_holder/spell/targeted/emplosion/eldritch name = "Energetic Pulse" invocation = "E'P" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER clothes_req = FALSE action_background_icon_state = "bg_ecult" range = -1 @@ -391,7 +390,7 @@ charge_max = 300 //twice as long as mansus grasp clothes_req = FALSE invocation = "C'SC'DE" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER range = 4 action_icon = 'icons/mob/actions/actions_ecult.dmi' action_icon_state = "fire_ring" @@ -415,7 +414,7 @@ /obj/effect/proc_holder/spell/targeted/telepathy/eldritch invocation = "" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER clothes_req = FALSE action_background_icon_state = "bg_ecult" @@ -423,7 +422,7 @@ name = "Oath of Fire" desc = "For a minute you will passively create a ring of fire around you." invocation = "FL'MS" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER clothes_req = FALSE action_background_icon_state = "bg_ecult" range = -1 @@ -489,7 +488,7 @@ name = "Nightwatcher's Rebirth" desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off." invocation = "GL'RY T' TH' N'GHT'W'TCH'ER" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER clothes_req = FALSE action_background_icon_state = "bg_ecult" range = -1 diff --git a/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm index e78f0f4eedb..b6e2d17feea 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm @@ -176,6 +176,8 @@ var/mob/living/carbon/human/H = user H.physiology.brute_mod *= 0.5 H.physiology.burn_mod *= 0.5 + var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic) + ascension.ascended = TRUE for(var/X in trait_list) ADD_TRAIT(user,X,MAGIC_TRAIT) return ..() diff --git a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm index 6ff9a54fbd9..3d579853ba9 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm @@ -236,6 +236,7 @@ var/datum/antagonist/heretic_monster/monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster) var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic) monster.set_owner(master) + master.ascended = TRUE if("Yes") var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy/prime(loc,TRUE,10) summoned.ghostize(0) @@ -243,6 +244,9 @@ priority_announce("$^@*$^@(#&$(@^$^@# Fear the dark, for king of arms has ascended! Lord of the night has come! $^@*$^@(#&$(@^$^@#","#$^@*$^@(#&$(@^$^@#", 'sound/ai/spanomalies.ogg') log_game("[user.real_name] ascended as [summoned.real_name]") var/mob/living/carbon/carbon_user = user + var/datum/antagonist/heretic/ascension = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic) + ascension.ascended = TRUE carbon_user.mind.transfer_to(summoned, TRUE) carbon_user.gib() + return ..() diff --git a/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm index 8435fb867c1..e59b098a8db 100644 --- a/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm +++ b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm @@ -130,6 +130,8 @@ H.physiology.burn_mod *= 0.5 priority_announce("$^@*$^@(#&$(@^$^@# Fear the decay, for Rustbringer [user.real_name] has come! $^@*$^@(#&$(@^$^@#","#$^@*$^@(#&$(@^$^@#", 'sound/ai/spanomalies.ogg') new /datum/rust_spread(loc) + var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic) + ascension.ascended = TRUE return ..() diff --git a/code/modules/antagonists/gang/outfits.dm b/code/modules/antagonists/gang/outfits.dm index 439247d187a..c3546c062b2 100644 --- a/code/modules/antagonists/gang/outfits.dm +++ b/code/modules/antagonists/gang/outfits.dm @@ -18,7 +18,7 @@ shoes = /obj/item/clothing/shoes/combat/swat gloves = null glasses = /obj/item/clothing/glasses/hud/spacecop - ears = /obj/item/radio/headset/headset_sec + ears = /obj/item/radio/headset/headset_sec/alt mask = null head = /obj/item/clothing/head/spacepolice belt = /obj/item/gun/ballistic/automatic/pistol/m1911 @@ -30,8 +30,8 @@ /obj/item/storage/box/flashbangs = 1, /obj/item/shield/riot/tele = 1, /obj/item/ammo_box/magazine/m45 = 3, - /obj/item/ammo_box/c45 = 2) - + /obj/item/ammo_box/c45 = 2, + /obj/item/storage/box/survival/security) /datum/outfit/families_police/beatcop/armored name = "Families: Armored Beat Cop" @@ -42,7 +42,8 @@ /obj/item/storage/box/teargas = 1, /obj/item/storage/box/flashbangs = 1, /obj/item/shield/riot/tele = 1, - /obj/item/storage/box/lethalshot = 2) + /obj/item/storage/box/lethalshot = 2, + /obj/item/storage/box/survival/security) /datum/outfit/families_police/beatcop/swat name = "Families: SWAT Beat Cop" @@ -54,7 +55,8 @@ /obj/item/storage/box/teargas = 1, /obj/item/storage/box/flashbangs = 1, /obj/item/shield/riot/tele = 1, - /obj/item/storage/box/lethalshot = 2) + /obj/item/storage/box/lethalshot = 2, + /obj/item/storage/box/survival/security) /datum/outfit/families_police/beatcop/fbi name = "Families: Space FBI Officer" @@ -67,7 +69,8 @@ /obj/item/storage/box/flashbangs = 1, /obj/item/shield/riot/tele = 1, /obj/item/ammo_box/magazine/smgm9mm = 3, - /obj/item/ammo_box/c9mm = 2) + /obj/item/ammo_box/c9mm = 2, + /obj/item/storage/box/survival/security) /datum/outfit/families_police/beatcop/military name = "Families: Space Military" @@ -79,4 +82,5 @@ backpack_contents = list(/obj/item/storage/box/handcuffs = 1, /obj/item/storage/box/teargas = 1, /obj/item/storage/box/flashbangs = 1, - /obj/item/shield/riot/tele = 1) + /obj/item/shield/riot/tele = 1, + /obj/item/storage/box/survival/security) diff --git a/code/modules/antagonists/traitor/equipment/contractor.dm b/code/modules/antagonists/traitor/equipment/contractor.dm index cd72eb4957d..5b9b6183601 100644 --- a/code/modules/antagonists/traitor/equipment/contractor.dm +++ b/code/modules/antagonists/traitor/equipment/contractor.dm @@ -229,7 +229,7 @@ to_chat(partner_mind.current, "\n[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.") to_chat(partner_mind.current, "Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.\n\n") - new /obj/effect/dp_target(free_location, arrival_pod) + new /obj/effect/pod_landingzone(free_location, arrival_pod) /datum/contractor_item/blackout name = "Blackout" diff --git a/code/modules/antagonists/traitor/syndicate_contract.dm b/code/modules/antagonists/traitor/syndicate_contract.dm index 4936aca541c..8a6d633a668 100644 --- a/code/modules/antagonists/traitor/syndicate_contract.dm +++ b/code/modules/antagonists/traitor/syndicate_contract.dm @@ -68,7 +68,7 @@ empty_pod.explosionSize = list(0,0,0,1) empty_pod.leavingSound = 'sound/effects/podwoosh.ogg' - new /obj/effect/dp_target(empty_pod_turf, empty_pod) + new /obj/effect/pod_landingzone(empty_pod_turf, empty_pod) /datum/syndicate_contract/proc/enter_check(datum/source, sent_mob) if (istype(source, /obj/structure/closet/supplypod/extractionpod)) @@ -111,7 +111,7 @@ var/obj/structure/closet/supplypod/extractionpod/pod = source // Handle the pod returning - pod.send_up(pod) + pod.depart(pod) if (ishuman(M)) var/mob/living/carbon/human/target = M @@ -226,7 +226,7 @@ M.Dizzy(35) M.confused += 20 - new /obj/effect/dp_target(possible_drop_loc[pod_rand_loc], return_pod) + new /obj/effect/pod_landingzone(possible_drop_loc[pod_rand_loc], return_pod) else to_chat(M, "A million voices echo in your head... \"Seems where you got sent here from won't \ be able to handle our pod... You will die here instead.\"") diff --git a/code/modules/awaymissions/away_props.dm b/code/modules/awaymissions/away_props.dm index 9a12d14ff2a..6c58238bb00 100644 --- a/code/modules/awaymissions/away_props.dm +++ b/code/modules/awaymissions/away_props.dm @@ -60,7 +60,7 @@ icon_state = "lattice" plane = FLOOR_PLANE anchored = TRUE - obj_flags = CAN_BE_HIT | BLOCK_Z_FALL + obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP var/id var/open = FALSE var/hidden = FALSE @@ -87,10 +87,10 @@ var/talpha if(open) talpha = 0 - obj_flags &= ~BLOCK_Z_FALL + obj_flags &= ~(BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP) else talpha = 255 - obj_flags |= BLOCK_Z_FALL + obj_flags |= BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP plane = BYOND_LIGHTING_LAYER //What matters it's one above openspace, so our animation is not dependant on what's there. Up to revision with 513 animate(src,alpha = talpha,time = 10) addtimer(CALLBACK(src,.proc/reset_plane),10) diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm index f08b52e252d..60afed5bb0d 100644 --- a/code/modules/awaymissions/mission_code/Academy.dm +++ b/code/modules/awaymissions/mission_code/Academy.dm @@ -363,7 +363,7 @@ charge_max = 100 clothes_req = 0 invocation = "JE VES" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER range = -1 level_max = 0 //cannot be improved cooldown_min = 100 diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index f02f7a95149..23f2b907516 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -246,6 +246,11 @@ PP.visible_message("[L] bursts into a brilliant purple flame as [L.p_their()] entire body is that of a skeleton!", \ "Your senses numb as all of your remaining flesh is turned into a purple slurry, sloshing off your body and leaving only your bones to show in a vibrant purple!") +//mafia specific tame happy plasma (normal atmos, no slowdown) +/turf/open/lava/plasma/mafia + initial_gas_mix = OPENTURF_DEFAULT_ATMOS + baseturfs = /turf/open/lava/plasma/mafia + slowdown = 0 /obj/vehicle/ridden/lavaboat/plasma name = "plasma boat" diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index 48db4feb9d6..5fe8d968920 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -19,7 +19,7 @@ //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 - var/static/list/ignored_atoms = typecacheof(list(null, /mob/dead, /obj/effect/landmark, /obj/docking_port, /atom/movable/lighting_object, /obj/effect/particle_effect/sparks, /obj/effect/dp_target, /obj/effect/supplypod_selector )) + var/static/list/ignored_atoms = typecacheof(list(null, /mob/dead, /obj/effect/landmark, /obj/docking_port, /atom/movable/lighting_object, /obj/effect/particle_effect/sparks, /obj/effect/pod_landingzone, /obj/effect/supplypod_selector )) 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/bay //What bay we're using to launch shit from. @@ -135,8 +135,8 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm return //Only teleport if the list isn't empty var/turf/T = pick(turfs) M.forceMove(T) //Perform the actual teleport - log_admin("[key_name(usr)] jumped to [AREACOORD(A)]") - message_admins("[key_name_admin(usr)] jumped to [AREACOORD(A)]") + log_admin("[key_name(usr)] jumped to [AREACOORD(T)]") + message_admins("[key_name_admin(usr)] jumped to [AREACOORD(T)]") . = TRUE if("teleportBack") //After teleporting to centcom, this button allows the user to teleport to the last spot they were at. var/mob/M = holder.mob @@ -587,7 +587,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm else for (var/atom/movable/O in launchList) //If we aren't cloning the objects, just go through the launchList O.forceMove(toLaunch) //and forceMove any atom/moveable into the supplypod - new /obj/effect/dp_target(A, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to it's location + new /obj/effect/pod_landingzone(A, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to it's 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 diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm index ab8ebeb7a95..549b61dfe19 100644 --- a/code/modules/cargo/expressconsole.dm +++ b/code/modules/cargo/expressconsole.dm @@ -192,7 +192,7 @@ LZ = pick(empty_turfs) if (SO.pack.cost <= points_to_check && LZ)//we need to call the cost check again because of the CHECK_TICK call D.adjust_money(-SO.pack.cost) - new /obj/effect/dp_target(LZ, podType, SO) + new /obj/effect/pod_landingzone(LZ, podType, SO) . = TRUE update_icon() else @@ -210,7 +210,7 @@ for(var/i in 1 to MAX_EMAG_ROCKETS) var/LZ = pick(empty_turfs) LAZYREMOVE(empty_turfs, LZ) - new /obj/effect/dp_target(LZ, podType, SO) + new /obj/effect/pod_landingzone(LZ, podType, SO) . = TRUE update_icon() CHECK_TICK diff --git a/code/modules/cargo/gondolapod.dm b/code/modules/cargo/gondolapod.dm index 1216c55fca6..81c1795418b 100644 --- a/code/modules/cargo/gondolapod.dm +++ b/code/modules/cargo/gondolapod.dm @@ -10,9 +10,9 @@ response_harm_simple = "kick" faction = list("gondola") turns_per_move = 10 - icon = 'icons/mob/gondolapod.dmi' - icon_state = "gondolapod" - icon_living = "gondolapod" + icon = 'icons/obj/supplypods.dmi' + icon_state = "pod_gondola" + icon_living = "pod_gondola" pixel_x = -16//2x2 sprite pixel_y = -5 layer = TABLE_LAYER//so that deliveries dont appear underneath it @@ -30,13 +30,13 @@ /mob/living/simple_animal/pet/gondola/gondolapod/Initialize(mapload, pod) linked_pod = pod name = linked_pod.name + desc = linked_pod.desc . = ..() -/mob/living/simple_animal/pet/gondola/gondolapod/update_icon_state() +/mob/living/simple_animal/pet/gondola/gondolapod/update_overlays() + . = ..() if(opened) - icon_state = "gondolapod_open" - else - icon_state = "gondolapod" + . += "[icon_state]_open" /mob/living/simple_animal/pet/gondola/gondolapod/verb/deliver() set name = "Release Contents" @@ -61,12 +61,12 @@ else to_chat(src, "A closer look inside yourself reveals... nothing.") -/mob/living/simple_animal/pet/gondola/gondolapod/proc/setOpened() +/mob/living/simple_animal/pet/gondola/gondolapod/setOpened() opened = TRUE update_icon() - addtimer(CALLBACK(src, .proc/setClosed), 50) + addtimer(CALLBACK(src, /atom/.proc/setClosed), 50) -/mob/living/simple_animal/pet/gondola/gondolapod/proc/setClosed() +/mob/living/simple_animal/pet/gondola/gondolapod/setClosed() opened = FALSE update_icon() diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index 0efe6662816..8833d3b9c9f 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -1411,6 +1411,14 @@ crate_type = /obj/structure/closet/crate/secure/science dangerous = TRUE +/datum/supply_pack/science/monkey_helmets + name = "Monkey Mind Magnification Helmet crate" + desc = "Some research is best done with monkeys, yet sometimes they're just too dumb to complete more complicated tasks. These helmets should help." + cost = 1500 + contains = list(/obj/item/clothing/head/helmet/monkey_sentience, + /obj/item/clothing/head/helmet/monkey_sentience) + crate_name = "monkey mind magnification crate" + ////////////////////////////////////////////////////////////////////////////// /////////////////////////////// Service ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index be02785d09d..21ad6273059 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -1,13 +1,14 @@ -//The "BDPtarget" temp visual is created by anything that "launches" a supplypod. It makes two things: a falling droppod animation, and the droppod itself. +#define SUPPLYPOD_X_OFFSET -16 + +//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 = "A Nanotrasen supply drop pod." icon = 'icons/obj/supplypods.dmi' - icon_state = "supplypod" - pixel_x = -16 //2x2 sprite - pixel_y = -5 - layer = TABLE_LAYER //So that the crate inside doesn't appear underneath + 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 allow_objects = TRUE allow_dense = TRUE delivery_icon = null @@ -16,6 +17,9 @@ anchored = TRUE //So it cant slide around after landing anchorable = FALSE flags_1 = PREVENT_CONTENTS_EXPLOSION_1 + appearance_flags = KEEP_TOGETHER | PIXEL_SCALE + density = FALSE + //*****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 @@ -43,7 +47,13 @@ var/bay //Used specifically for the centcom_podlauncher datum. Holds the current bay the user is launching objects from. Bays are specific rooms on the centcom map. var/list/explosionSize = list(0,0,2,3) var/stay_after_drop = FALSE - var/specialised = TRUE // It's not a general use pod for cargo/admin use + 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/projectile/bullet/shrapnel var/shrapnel_magnitude = 3 @@ -56,7 +66,7 @@ /obj/structure/closet/supplypod/extractionpod name = "Syndicate Extraction Pod" - desc = "A specalised, blood-red styled pod for extracting high-value targets out of active mission areas." + desc = "A specalised, blood-red styled pod for extracting high-value targets out of active mission areas. Targets must be manually stuffed inside the pod for proper delivery." specialised = TRUE style = STYLE_SYNDICATE bluespace = TRUE @@ -70,39 +80,73 @@ landingDelay = 20 //Very speedy! resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - -/obj/structure/closet/supplypod/proc/specialisedPod() - return 1 - -/obj/structure/closet/supplypod/extractionpod/specialisedPod(atom/movable/holder) - holder.forceMove(pick(GLOB.holdingfacility)) // land in ninja jail - open_pod(holder, forced = TRUE) - /obj/structure/closet/supplypod/Initialize() . = ..() setStyle(style, TRUE) //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/update_overlays() - . = ..() - if (style == STYLE_SEETHROUGH || style == STYLE_INVISIBLE) //If we're invisible, we dont bother adding any overlays - return - else - if (opened) - . += "[icon_state]_open" - else - . += "[icon_state]_door" - -/obj/structure/closet/supplypod/proc/setStyle(chosenStyle, duringInit = FALSE) //Used to give the sprite an icon state, name, and description +/obj/structure/closet/supplypod/proc/setStyle(chosenStyle, duringInit = FALSE) //Used to give the sprite an icon state, name, and description. Should only be called once if (!duringInit && style == chosenStyle) //Check if the input style is already the same as the pod's style. This happens in centcom_podlauncher, and as such we set the style to STYLE_CENTCOM. setStyle(STYLE_CENTCOM) //We make sure to not check this during initialize() so the standard supplypod works correctly. return style = chosenStyle - icon_state = POD_STYLES[chosenStyle][POD_ICON_STATE] //POD_STYLES is a 2D array we treat as a dictionary. The style represents the verticle index, with the icon state, name, and desc being stored in the horizontal indexes of the 2D array. + var/base = POD_STYLES[chosenStyle][POD_BASE] //POD_STYLES is a 2D array we treat as a dictionary. The style represents the verticle index, with the icon state, name, and desc being stored in the horizontal indexes of the 2D array. + icon_state = base + decal = POD_STYLES[chosenStyle][POD_DECAL] + rubble_type = POD_STYLES[chosenStyle][POD_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 = POD_STYLES[chosenStyle][POD_NAME] desc = POD_STYLES[chosenStyle][POD_DESC] + door = "[base]_door" update_icon() +/obj/structure/closet/supplypod/proc/SetReverseIcon() + fin_mask = "bottomfin" + if (POD_STYLES[style][POD_SHAPE] == POD_SHAPE_NORML) + icon_state = POD_STYLES[style][POD_BASE] + "_reverse" + pixel_x = initial(pixel_x) + transform = matrix() + update_icon() + +/obj/structure/closet/supplypod/closet_update_overlays(list/new_overlays) + return + +/obj/structure/closet/supplypod/update_overlays() + . = ..() + if (style == STYLE_INVISIBLE) + return + if (rubble) + . += rubble.getForeground(src) + if (style == 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 + 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("#000000", ICON_SUBTRACT) + masked_decal.Blend(door_masker, ICON_ADD) + . += masked_decal + else //If we're closed + if (POD_STYLES[style][POD_SHAPE] != POD_SHAPE_NORML) //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("#000000", ICON_SUBTRACT) + masked_door.Blend(fin_masker, ICON_ADD) + . += masked_door + if (decal) + . += decal + /obj/structure/closet/supplypod/tool_interact(obj/item/W, mob/user) if(bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways. return FALSE @@ -118,40 +162,34 @@ /obj/structure/closet/supplypod/toggle(mob/living/user) return -/obj/structure/closet/supplypod/open(mob/living/user, force = TRUE) //Supplypods shouldn't be able to be manually opened under any circumstances +/obj/structure/closet/supplypod/open(mob/living/user, force = TRUE) return -/obj/structure/closet/supplypod/proc/handleReturningClose(atom/movable/holder, returntobay) - opened = FALSE - INVOKE_ASYNC(holder, .proc/setClosed) //Use the INVOKE_ASYNC proc to call setClosed() on whatever the holder may be, without giving the atom/movable base class a setClosed() proc definition - for (var/atom/movable/O in get_turf(holder)) - if ((ismob(O) && !isliving(O)) || (is_type_in_typecache(O, GLOB.blacklisted_cargo_types) && !isliving(O))) //We dont want to take ghosts with us, and we don't want blacklisted items going, but we allow mobs. - continue - O.forceMove(holder) //Put objects inside before we close - var/obj/effect/temp_visual/risingPod = new /obj/effect/dp_fall(get_turf(holder), src) //Make a nice animation of flying back up - risingPod.pixel_z = 0 //The initial value of risingPod's pixel_z is 200 because it normally comes down from a high spot - animate(risingPod, pixel_z = 200, time = 10, easing = LINEAR_EASING) //Animate our rising pod - if (returntobay) - holder.forceMove(bay) //Move the pod back to centcom, where it belongs - QDEL_IN(risingPod, 10) - 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() ) - bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever - open_pod(holder, forced = TRUE) - else - 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() ) - bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever +/obj/structure/closet/supplypod/extractionpod/handleReturningClose(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 + audible_message("The pod hisses, closing quickly and launching itself away from the station.", "The ground vibrates.") + stay_after_drop = FALSE + holder.forceMove(pick(GLOB.holdingfacility)) // land in ninja jail + holder.pixel_z = initial(holder.pixel_z) + open_pod(holder, forced = TRUE) - QDEL_IN(risingPod, 10) - audible_message("The pod hisses, closing quickly and launching itself away from the station.", "The ground vibrates, the nearby pod launching away from the station.") +/obj/structure/closet/supplypod/proc/handleReturningClose(atom/movable/holder = src) + holder.forceMove(bay) //Move the pod back to centcom, where it belongs + holder.pixel_z = initial(holder.pixel_z) + 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 + open_pod(holder, forced = TRUE) - stay_after_drop = FALSE - specialisedPod(holder) // Do special actions for specialised pods - this is likely if we were already doing manual launches - -/obj/structure/closet/supplypod/proc/preOpen() //Called before the open() proc. Handles anything that occurs right as the pod lands. +/obj/structure/closet/supplypod/proc/preOpen() //Called before the open_pod() proc. Handles anything that occurs right as the pod lands. var/turf/T = get_turf(src) var/list/B = explosionSize //Mostly because B is more readable than explosionSize :p + density = TRUE //Density is originally false so the pod doesn't block anything while it's still falling through the air if (landingSound) playsound(get_turf(src), landingSound, soundVolume, FALSE, FALSE) + AddComponent(/datum/component/pellet_cloud, projectile_type=shrapnel_type, magnitude=shrapnel_magnitude) + if(effectShrapnel) + SEND_SIGNAL(src, COMSIG_SUPPLYPOD_LANDED) for (var/mob/living/M in T) if (effectLimb && iscarbon(M)) //If effectLimb is true (which means we pop limbs off when we hit people): var/mob/living/carbon/CM = M @@ -193,7 +231,7 @@ var/mob/living/simple_animal/pet/gondola/gondolapod/benis = new(get_turf(src), src) benis.contents |= contents //Move the contents of this supplypod into the gondolapod mob. moveToNullspace() - addtimer(CALLBACK(src, .proc/open, benis), openingDelay) //After the openingDelay passes, we use the open proc from this supplyprod while referencing the contents of the "holder", in this case the gondolapod mob + addtimer(CALLBACK(src, .proc/open_pod, benis), openingDelay) //After the openingDelay passes, we use the open proc from this supplyprod while referencing the contents of the "holder", in this case the gondolapod mob else if (style == STYLE_SEETHROUGH) open_pod(src) else @@ -204,7 +242,7 @@ return if (opened) //This is to ensure we don't open something that has already been opened return - opened = TRUE + holder.setOpened() var/turf/T = get_turf(holder) //Get the turf of whoever's contents we're talking about var/mob/M 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 @@ -213,9 +251,6 @@ return if (openingSound) playsound(get_turf(holder), openingSound, soundVolume, FALSE, FALSE) //Special admin sound to play - INVOKE_ASYNC(holder, .proc/setOpened) //Use the INVOKE_ASYNC proc to call setOpened() on whatever the holder may be, without giving the atom/movable base class a setOpened() proc definition - if (style == STYLE_SEETHROUGH) - update_icon() for (var/atom/movable/O in holder.contents) //Go through the contents of the holder O.forceMove(T) //move everything from the contents of the holder to the turf of the holder if (!effectQuiet && !openingSound && style != STYLE_SEETHROUGH) //If we aren't being quiet, play the default pod open sound @@ -225,89 +260,227 @@ if (style == STYLE_SEETHROUGH) depart(src) else + if (reversing) + addtimer(CALLBACK(src, .proc/SetReverseIcon), departureDelay/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/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time /obj/structure/closet/supplypod/proc/depart(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 seperate holder exists) + deleteRubble() if (!effectQuiet && style != STYLE_INVISIBLE && style != 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/centcompod/close(atom/movable/holder) //Closes the supplypod and sends it back to centcom. Should only ever be called if the "reversing" variable is true - handleReturningClose(holder, TRUE) - -/obj/structure/closet/supplypod/extractionpod/close(atom/movable/holder) //handles closing, and returns pod - deletes itself when returned - . = ..() - return - -/obj/structure/closet/supplypod/extractionpod/proc/send_up(atom/movable/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) - holder = src + return + take_contents(holder) + playsound(holder, close_sound, close_sound_volume, TRUE, -3) + holder.setClosed() + addtimer(CALLBACK(src, .proc/preReturn, holder), 10) //Finish up the pod's duties after a certain amount of time +/obj/structure/closet/supplypod/take_contents(atom/movable/holder) + var/atom/L = holder.drop_location() + for(var/atom/movable/AM in L) + if(AM != src && !insert(AM, holder)) // Can't insert that + continue + +/obj/structure/closet/supplypod/insert(atom/movable/AM, atom/movable/holder) + if(insertion_allowed(AM)) + AM.forceMove(holder) + return TRUE + else + return FALSE + +/obj/structure/closet/supplypod/insertion_allowed(atom/movable/AM) + if(ismob(AM)) + if(!isliving(AM)) //let's not put ghosts or camera mobs inside closets... + return FALSE + var/mob/living/L = AM + if(L.anchored || L.incorporeal_move) + return FALSE + L.stop_pulling() + + else if(isobj(AM)) + if((!allow_dense && AM.density) || AM.anchored || AM.has_buckled_mobs()) + return FALSE + else if(isitem(AM) && !HAS_TRAIT(AM, TRAIT_NODROP)) + return TRUE + else if(!allow_objects && !istype(AM, /obj/effect/dummy/chameleon)) + return FALSE + else + return FALSE + + return TRUE + +/obj/structure/closet/supplypod/proc/preReturn(atom/movable/holder) if (leavingSound) playsound(get_turf(holder), leavingSound, soundVolume, FALSE, FALSE) + 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/handleReturningClose, holder), 15) //Finish up the pod's duties after a certain amount of time - handleReturningClose(holder, FALSE) - -/obj/structure/closet/supplypod/proc/setOpened() //Proc exists here, as well as in any atom that can assume the role of a "holder" of a supplypod. Check the open() proc for more details +/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 + density = FALSE update_icon() -/obj/structure/closet/supplypod/proc/setClosed() //Ditto +/obj/structure/closet/supplypod/extractionpod/setOpened() + opened = TRUE + density = TRUE update_icon() +/obj/structure/closet/supplypod/setClosed() //Ditto + opened = FALSE + density = TRUE + update_icon() + +/obj/structure/closet/supplypod/proc/tryMakeRubble(turf/T) //Ditto + if (rubble_type == RUBBLE_NONE) + return + if (rubble) + return + if (effectMissile) + return + if (isspaceturf(T) || isclosedturf(T)) + return + rubble = new /obj/effect/supplypod_rubble(T) + rubble.setStyle(rubble_type, src) + update_icon() + +/obj/structure/closet/supplypod/Moved() + deleteRubble() + return ..() + +/obj/structure/closet/supplypod/proc/deleteRubble() + rubble?.fadeAway() + rubble = null + update_icon() + +/obj/structure/closet/supplypod/proc/addGlow() + if (POD_STYLES[style][POD_SHAPE] != POD_SHAPE_NORML) + return + glow_effect = new(src) + glow_effect.icon_state = "pod_glow_" + POD_STYLES[style][POD_GLOW] + vis_contents += glow_effect + glow_effect.layer = GASFIRE_LAYER + +/obj/structure/closet/supplypod/proc/endGlow() + if(!glow_effect) + return + glow_effect.layer = LOW_ITEM_LAYER + glow_effect.fadeAway(openingDelay) + /obj/structure/closet/supplypod/Destroy() - open_pod(holder = src, broken = TRUE) //Lets dump our contents by opening up - . = ..() - -//------------------------------------FALLING SUPPLY POD-------------------------------------// -/obj/effect/dp_fall //Falling pod - name = "" - icon = 'icons/obj/supplypods.dmi' - pixel_x = -16 - pixel_y = -5 - pixel_z = 200 - desc = "Get out of the way!" - layer = FLY_LAYER//that wasn't flying, that was falling with style! - icon_state = "" - -/obj/effect/dp_fall/Initialize(dropLocation, obj/structure/closet/supplypod/pod) - if (pod.style == STYLE_SEETHROUGH) - pixel_x = -16 - pixel_y = 0 - for (var/atom/movable/O in pod.contents) - var/icon/I = getFlatIcon(O) //im so sorry - add_overlay(I) - else if (pod.style != STYLE_INVISIBLE) //Check to ensure the pod isn't invisible - icon_state = "[pod.icon_state]_falling" - name = pod.name - . = ..() + deleteRubble() + open_pod(src, broken = TRUE) //Lets dump our contents by opening up + return ..() //------------------------------------TEMPORARY_VISUAL-------------------------------------// -/obj/effect/dp_target //This is the object that forceMoves the supplypod to it's location +/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_engineglow" + desc = "" + layer = GASFIRE_LAYER + 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 //This is the object that forceMoves the supplypod to it's location + name = "Debris" + desc = "A small crater of rubble. Closer inspection reveals the debris to be made primarily of space-grade metal fragments. You're pretty sure that this will disperse before too long." + 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 + +/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 (pod.style == STYLE_BOX) + verticle_offset = -2 + else + verticle_offset = initial(verticle_offset) + + pixel_y = verticle_offset + +/obj/effect/supplypod_target_helper + name = "" + desc = "" + icon = 'icons/obj/supplypods_32x32.dmi' + icon_state = "LZ_Slider" + layer = PROJECTILE_HIT_THRESHHOLD_LAYER + +/obj/effect/supplypod_target_helper/Initialize(mapload, obj/structure/closet/supplypod/pod) + transform = matrix() * 1.5 + animate(src, transform = matrix()*0.01, time = pod.landingDelay+pod.fallDuration) + ..() + +/obj/effect/pod_landingzone //This is the object that forceMoves the supplypod to it's location name = "Landing Zone Indicator" desc = "A holographic projection designating the landing zone of something. It's probably best to stand back." - icon = 'icons/mob/actions/actions_items.dmi' - icon_state = "sniper_zoom" + icon = 'icons/obj/supplypods_32x32.dmi' + icon_state = "" layer = PROJECTILE_HIT_THRESHHOLD_LAYER light_range = 2 - var/obj/effect/temp_visual/fallingPod //Temporary "falling pod" that we animate + anchored = TRUE var/obj/structure/closet/supplypod/pod //The supplyPod that will be landing ontop of this target + var/obj/effect/supplypod_target_helper/helper + var/list/smoke_effects = new /list(13) /obj/effect/ex_act() return -/obj/effect/dp_target/Initialize(mapload, podParam, single_order = null) +/obj/effect/pod_landingzone/Initialize(mapload, podParam, single_order = null, clientman) . = ..() 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 + if (!pod.effectStealth) + helper = new (drop_location(), pod) + icon_state = "LZ" + animate(src, transform = matrix().Turn(90), time = pod.landingDelay+pod.fallDuration) if (single_order) if (istype(single_order, /datum/supply_order)) var/datum/supply_order/SO = single_order @@ -316,12 +489,10 @@ var/atom/movable/O = single_order O.forceMove(pod) for (var/mob/living/M in pod) //If there are any mobs in the supplypod, we want to forceMove them into the target. This is so that they can see where they are about to land, AND so that they don't get sent to the nullspace error room (as the pod is currently in nullspace) - M.forceMove(src) + M.reset_perspective(src) if(pod.effectStun) //If effectStun is true, stun any mobs caught on this target until the pod gets a chance to hit them for (var/mob/living/M in get_turf(src)) - M.Stun(pod.landingDelay+10, ignore_canstun = TRUE)//you ain't goin nowhere, kid. - if (pod.effectStealth) //If effectStealth is true we want to be invisible - icon_state = "" + M.Stun(pod.landingDelay+10, ignore_canstun = TRUE)//you aint goin nowhere, kid. if (pod.fallDuration == initial(pod.fallDuration) && pod.landingDelay + pod.fallDuration < 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' @@ -332,34 +503,60 @@ addtimer(CALLBACK(src, .proc/playFallingSound), soundStartTime) addtimer(CALLBACK(src, .proc/beginLaunch, pod.effectCircle), pod.landingDelay) -/obj/effect/dp_target/proc/playFallingSound() +/obj/effect/pod_landingzone/proc/playFallingSound() playsound(src, pod.fallingSound, pod.soundVolume, TRUE, 6) -/obj/effect/dp_target/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 - fallingPod = new /obj/effect/dp_fall(drop_location(), pod) - var/matrix/M = matrix(fallingPod.transform) //Create a new matrix that we can rotate +/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_icon() + if (pod.style != STYLE_INVISIBLE) + pod.add_filter("motionblur",1,list("type"="motion_blur", "x"=0, "y"=3)) + 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 - fallingPod.pixel_x = cos(angle)*400 //Use some ADVANCED MATHEMATICS to set the animated pod's position to somewhere on the edge of a circle with the center being the target - fallingPod.pixel_z = sin(angle)*400 - var/rotation = Get_Pixel_Angle(fallingPod.pixel_z, fallingPod.pixel_x) //CUSTOM HOMEBREWED proc that is just arctan with extra steps - M.Turn(rotation) //Turn our matrix accordingly - fallingPod.transform = M //Transform the animated pod according to the matrix - M = matrix(pod.transform) //Make another matrix based on the pod - M.Turn(rotation) //Turn the matrix - pod.transform = M //Turn the actual pod (Won't be visible until endLaunch() proc tho) - animate(fallingPod, pixel_z = 0, pixel_x = -16, time = pod.fallDuration, , easing = LINEAR_EASING) //Make the pod fall! At an angle! + 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 target + 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 + if (pod.style != STYLE_INVISIBLE) + animate(pod.get_filter("motionblur"), y = 0, time = pod.fallDuration, flags = ANIMATION_PARALLEL) + animate(pod, pixel_z = -1 * abs(sin(rotation))*4, pixel_x = SUPPLYPOD_X_OFFSET + (sin(rotation) * 20), time = pod.fallDuration, easing = LINEAR_EASING, flags = ANIMATION_PARALLEL) //Make the pod fall! At an angle! addtimer(CALLBACK(src, .proc/endLaunch), pod.fallDuration, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation -/obj/effect/dp_target/proc/endLaunch() - pod.update_icon() - pod.forceMove(drop_location()) //The fallingPod animation is over, now's a good time to forceMove the actual pod into position - pod.AddComponent(/datum/component/pellet_cloud, projectile_type=pod.shrapnel_type, magnitude=pod.shrapnel_magnitude) - if(pod.effectShrapnel) - SEND_SIGNAL(pod, COMSIG_SUPPLYPOD_LANDED) - QDEL_NULL(fallingPod) //Delete the falling pod effect, because at this point its animation is over. We dont use temp_visual because we want to manually delete it as soon as the pod appears - for (var/mob/living/M in src) //Remember earlier (initialization) when we moved mobs into the DPTarget so they wouldnt get lost in nullspace? Time to get them out - M.forceMove(pod) +/obj/effect/pod_landingzone/proc/setupSmoke(rotation) + if (pod.style == STYLE_INVISIBLE || pod.style == STYLE_SEETHROUGH) + return + for ( var/i in 1 to length(smoke_effects)) + var/obj/effect/supplypod_smoke/S = new (drop_location()) + if (i == 1) + S.layer = FLY_LAYER + S.icon_state = "smoke_start" + S.transform = matrix().Turn(rotation) + smoke_effects[i] = S + S.pixel_x = sin(rotation)*32 * i + S.pixel_y = abs(cos(rotation))*32 * i + S.filters += filter(type = "blur", size = 4) + var/time = (pod.fallDuration / length(smoke_effects))*(length(smoke_effects)-i) + addtimer(CALLBACK(S, /obj/effect/supplypod_smoke/.proc/drawSelf, i), time, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation + QDEL_IN(S, pod.fallDuration + 35) + +/obj/effect/pod_landingzone/proc/drawSmoke() + if (pod.style == STYLE_INVISIBLE || pod.style == STYLE_SEETHROUGH) + return + for (var/obj/effect/supplypod_smoke/S in smoke_effects) + animate(S, alpha = 0, time = 20, flags = ANIMATION_PARALLEL) + animate(S.filters[1], size = 6, time = 15, easing = CUBIC_EASING|EASE_OUT, flags = ANIMATION_PARALLEL) + +/obj/effect/pod_landingzone/proc/endLaunch() + pod.tryMakeRubble(drop_location()) + pod.layer = initial(pod.layer) + 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 target's purpose is complete. It can rest easy now //------------------------------------UPGRADES-------------------------------------// @@ -370,3 +567,5 @@ icon_state = "cargodisk" inhand_icon_state = "card-id" w_class = WEIGHT_CLASS_SMALL + +#undef SUPPLYPOD_X_OFFSET diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index 2fbb591e889..19b12e4f473 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -241,6 +241,10 @@ log_message("(job: [src.job ? "[src.job]" : "None"]) committed suicide", LOG_ATTACK) /mob/living/proc/canSuicide() + var/area/A = get_area(src) + if(A.block_suicide) + to_chat(src, "You can't commit suicide here! You can ghost if you'd like.") + return switch(stat) if(CONSCIOUS) return TRUE diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 9cec2e37a5c..8bd7eed71cf 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -335,6 +335,99 @@ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF strip_delay = 80 +//monkey sentience caps + +/obj/item/clothing/head/helmet/monkey_sentience + name = "monkey mind magnification helmet" + desc = "A fragile, circuitry embedded helmet for boosting the intelligence of a monkey to a higher level. You see several warning labels..." + + icon_state = "monkeymind" + inhand_icon_state = "monkeymind" + strip_delay = 100 + var/mob/living/carbon/monkey/magnification = null ///if the helmet is on a valid target (just works like a normal helmet if not (cargo please stop)) + var/polling = FALSE///if the helmet is currently polling for targets (special code for removal) + var/light_colors = 1 ///which icon state color this is (red, blue, yellow) + +/obj/item/clothing/head/helmet/monkey_sentience/Initialize() + . = ..() + light_colors = rand(1,3) + update_icon_state() + +/obj/item/clothing/head/helmet/monkey_sentience/examine(mob/user) + . = ..() + . += "---WARNING: REMOVAL OF HELMET ON SUBJECT MAY LEAD TO:---" + . += "BLOOD RAGE" + . += "BRAIN DEATH" + . += "PRIMAL GENE ACTIVATION" + . += "GENETIC MAKEUP MASS SUSCEPTIBILITY" + . += "Ask your CMO if mind magnification is right for you." + +/obj/item/clothing/head/helmet/monkey_sentience/update_icon_state() + icon_state = "[initial(icon_state)][light_colors][magnification ? "up" : ""]" + +/obj/item/clothing/head/helmet/monkey_sentience/equipped(mob/user, slot) + . = ..() + if(slot != ITEM_SLOT_HEAD) + return + if(!ismonkey(user) || user.ckey) + var/mob/living/something = user + to_chat(something, "You feel a stabbing pain in the back of your head for a moment.") + something.apply_damage(5,BRUTE,BODY_ZONE_HEAD,FALSE,FALSE,FALSE) //notably: no damage resist (it's in your helmet), no damage spread (it's in your helmet) + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) + return + magnification = user //this polls ghosts + visible_message("[src] powers up!") + playsound(src, 'sound/machines/ping.ogg', 30, TRUE) + polling = TRUE + var/list/candidates = pollCandidatesForMob("Do you want to play as a mind magnified monkey?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, magnification, POLL_IGNORE_SENTIENCE_POTION) + polling = FALSE + if(!candidates.len) + magnification = null + visible_message("[src] falls silent and drops on the floor. Maybe you should try again later?") + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) + user.dropItemToGround(src) + var/mob/picked = pick(candidates) + magnification.key = picked.key + playsound(src, 'sound/machines/microwave/microwave-end.ogg', 100, FALSE) + to_chat(magnification, "You're a mind magnified monkey! Protect your helmet with your life- if you lose it, your sentience goes with it!") + var/policy = get_policy(ROLE_MONKEY_HELMET) + if(policy) + to_chat(magnification, policy) + icon_state = "[icon_state]up" + +/obj/item/clothing/head/helmet/monkey_sentience/Destroy() + disconnect() + return ..() + +/obj/item/clothing/head/helmet/monkey_sentience/proc/disconnect() + if(!magnification) //not put on a viable head + return + if(!polling)//put on a viable head, but taken off after polling finished. + if(magnification.client) + to_chat(magnification, "You feel your flicker of sentience ripped away from you, as everything becomes dim...") + magnification.ghostize(FALSE) + if(prob(10)) + switch(rand(1,4)) + if(1) //blood rage + magnification.aggressive = TRUE + if(2) //brain death + magnification.apply_damage(500,BRAIN,BODY_ZONE_HEAD,FALSE,FALSE,FALSE) + if(3) //primal gene (gorilla) + magnification.gorillize() + if(4) //genetic mass susceptibility (gib) + magnification.gib() + //either used up correctly or taken off before polling finished (punish this by destroying the helmet) + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) + playsound(src, "sparks", 100, TRUE) + visible_message("[src] fizzles and breaks apart!") + magnification = null + new /obj/effect/decal/cleanable/ash/crematorium(drop_location()) //just in case they're in a locker or other containers it needs to use crematorium ash, see the path itself for an explanation + +/obj/item/clothing/head/helmet/monkey_sentience/dropped(mob/user) + . = ..() + if(magnification || polling) + qdel(src)//runs disconnect code + //LightToggle diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index efdc2057a17..0f2a4c86eb6 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -273,7 +273,8 @@ /obj/item/clothing/head/hunter name = "bounty hunting hat" desc = "Ain't nobody gonna cheat the hangman in my town." - icon_state = "hunter" + icon_state = "cowboy" + worn_icon_state = "hunter" inhand_icon_state = "hunter" armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index f5df2d2b8f2..8ee8d68e70e 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -22,7 +22,7 @@ if(turfs.len) //Pick a turf to spawn at if we can var/turf/T = pick(turfs) - new /datum/spacevine_controller(T, list(pick(subtypesof(/datum/spacevine_mutation))), rand(10,100), rand(5,10), src) //spawn a controller at turf with randomized stats and a single random mutation + new /datum/spacevine_controller(T, list(pick(subtypesof(/datum/spacevine_mutation))), rand(10,100), rand(1,6), src) //spawn a controller at turf with randomized stats and a single random mutation /datum/spacevine_mutation @@ -396,9 +396,9 @@ init_subtypes(/datum/spacevine_mutation/, vine_mutations_list) if(potency != null) mutativeness = potency / 10 - if(production != null) - spread_cap *= production / 5 - spread_multiplier /= production / 5 + if(production != null && production <= 10) //Prevents runtime in case production is set to 11. + spread_cap *= (11 - production) / 5 //Best production speed of 1 doubles spread_cap to 60 while worst speed of 10 lowers it to 6. Even distribution. + spread_multiplier /= (11 - production) / 5 /datum/spacevine_controller/vv_get_dropdown() . = ..() @@ -446,7 +446,7 @@ var/obj/item/seeds/kudzu/KZ = new(S.loc) KZ.mutations |= S.mutations KZ.set_potency(mutativeness * 10) - KZ.set_production((spread_cap / initial(spread_cap)) * 5) + KZ.set_production(11 - (spread_cap / initial(spread_cap)) * 5) //Reverts spread_cap formula so resulting seed gets original production stat or equivalent back. qdel(src) /datum/spacevine_controller/process() diff --git a/code/modules/events/stray_cargo.dm b/code/modules/events/stray_cargo.dm index f9f0f359110..e8e6b90d13a 100644 --- a/code/modules/events/stray_cargo.dm +++ b/code/modules/events/stray_cargo.dm @@ -55,7 +55,7 @@ crate.locked = FALSE //Unlock secure crates crate.update_icon() var/obj/structure/closet/supplypod/pod = make_pod() - new /obj/effect/dp_target(LZ, pod, crate) + new /obj/effect/pod_landingzone(LZ, pod, crate) ///Handles the creation of the pod, in case it needs to be modified beforehand /datum/round_event/stray_cargo/proc/make_pod() diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index e16c061ff8f..0adef27f864 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -319,7 +319,11 @@ GLOBAL_LIST_INIT(hallucination_list, list( /datum/hallucination/oh_yeah/proc/bubble_attack(turf/landing) var/charged = FALSE //only get hit once - while(get_turf(bubblegum) != landing && target && target.stat != DEAD) + while(get_turf(bubblegum) != landing && target?.stat != DEAD) + if(!landing) + break + if((get_turf(bubblegum)).loc.z != landing.loc.z) + break bubblegum.forceMove(get_step_towards(bubblegum, landing)) bubblegum.setDir(get_dir(bubblegum, landing)) target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1) diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm index 260ca1d4a35..d462e7f430c 100644 --- a/code/modules/hydroponics/grown/melon.dm +++ b/code/modules/hydroponics/grown/melon.dm @@ -95,7 +95,7 @@ /obj/item/reagent_containers/food/snacks/grown/barrelmelon seed = /obj/item/seeds/watermelon/barrel name = "barrelmelon" - desc = "The water within this melon has been compressed and fermented into rich alcohol." + desc = "The nutriments within this melon have been compressed and fermented into rich alcohol." icon_state = "barrelmelon" filling_color = "#b47b31" distill_reagent = /datum/reagent/medicine/antihol //You can call it a integer overflow. diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index eccc38e494f..5beea890eb0 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -256,7 +256,8 @@ //This is where stability mutations exist now. if(myseed.instability >= 80) - mutate(0, 0, 0, 0, 0, 0, 0, 5, 0) //Exceedingly low odds of gaining a trait. + var/mutation_chance = myseed.instability - 75 + mutate(0, 0, 0, 0, 0, 0, 0, mutation_chance, 0) //Scaling odds of a random trait or chemical if(myseed.instability >= 60) if(prob((myseed.instability)/2) && !self_sustaining && length(myseed.mutatelist)) //Minimum 30%, Maximum 50% chance of mutating every age tick when not on autogrow. mutatespecie() diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 1201333b677..b112907d80d 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -26,6 +26,7 @@ var/category = "Any" var/author var/search_page = 0 + COOLDOWN_DECLARE(library_visitor_topic_cooldown) /obj/machinery/computer/libraryconsole/ui_interact(mob/user) . = ..() @@ -104,6 +105,9 @@ popup.open() /obj/machinery/computer/libraryconsole/Topic(href, href_list) + if(!COOLDOWN_FINISHED(src, library_visitor_topic_cooldown)) + return + COOLDOWN_START(src, library_visitor_topic_cooldown, 1 SECONDS) . = ..() if(.) usr << browse(null, "window=publiclibrary") @@ -150,39 +154,6 @@ var/getdate var/duedate -/* - * Cachedbook datum - */ -/datum/cachedbook // Datum used to cache the SQL DB books locally in order to achieve a performance gain. - var/id - var/title - var/author - var/category - -GLOBAL_LIST(cachedbooks) // List of our cached book datums - - -/proc/load_library_db_to_cache() - if(GLOB.cachedbooks) - return - if(!SSdbcore.Connect()) - return - GLOB.cachedbooks = list() - var/datum/db_query/query_library_cache = SSdbcore.NewQuery("SELECT id, author, title, category FROM [format_table_name("library")] WHERE isnull(deleted)") - if(!query_library_cache.Execute()) - qdel(query_library_cache) - return - while(query_library_cache.NextRow()) - var/datum/cachedbook/newbook = new() - newbook.id = query_library_cache.item[1] - newbook.author = query_library_cache.item[2] - newbook.title = query_library_cache.item[3] - newbook.category = query_library_cache.item[4] - GLOB.cachedbooks += newbook - qdel(query_library_cache) - - - #define PRINTER_COOLDOWN 60 /* @@ -215,25 +186,9 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums var/list/inventory = list() var/checkoutperiod = 5 // In minutes var/obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive - var/list/libcomp_menu var/page = 1 //current page of the external archives - var/cooldown = 0 - -/obj/machinery/computer/bookmanagement/proc/build_library_menu() - if(libcomp_menu) - return - load_library_db_to_cache() - if(!GLOB.cachedbooks) - return - libcomp_menu = list("") - - for(var/i in 1 to GLOB.cachedbooks.len) - var/datum/cachedbook/C = GLOB.cachedbooks[i] - var/page = round(i/250)+1 - if (libcomp_menu.len < page) - libcomp_menu.len = page - libcomp_menu[page] = "" - libcomp_menu[page] += "
| AUTHOR | TITLE | CATEGORY | |
| <<<< | >>>> | ||
| <<<< | >>>> |
-
-
-
-GoonStation 13 Development Team
- 08 July 2020-ArcaneMusic updated:-
Fikou updated:-
Jared-Fogle updated:-
ShizCalev updated:-
oranges updated:-
07 July 2020-ATHATH updated:-
ArcaneMusic updated:-
EdgeLordExe updated:-
Fikou updated:-
Jared-Fogle updated:-
Jay Smith updated:-
Kathy Ryals updated:-
LemonInTheDark updated:-
Orchian updated:-
ShizCalev updated:-
TetraZeta, NecromancerAnne updated:-
TheVekter updated:-
bobbahbrown updated:-
nightred updated:-
zxaber updated:-
06 July 2020-ATHATH updated:-
Anturk + Arm + other summer ball contributors code, trollbreeder + fikou + jerryderpington mapping updated:-
ArcaneMusic updated:-
Arkatos updated:-
Disco updated:-
EdgeLordExe updated:-
Inept, KathyRyals updated:-
Jay Smith & Michael Trauf updated:-
LemonInTheDark updated:-
Melbert updated:-
MrDoomBringer / Ryll-Ryll updated:-
Ryll/Shaps updated:-
ShizCalev updated:-
Skoglol updated:-
Timberpoes & Kathy Ryals updated:-
Wayland-Smithy updated:-
05 July 2020-Caldony updated:-
Disco updated:-
Firecage updated:-
Fox McCloud updated:-
Iatots updated:-
LemonInTheDark updated:-
XRandomXManX updated:-
anconfuzedrock updated:-
nightred updated:-
04 July 2020-ArcaneMusic updated:-
Tlaltecuhtli updated:-
ivanmixo updated:-
03 July 2020-Jared-Fogle updated:-
ShizCalev updated:-
WarlockD updated:-
bobbahbrown updated:-
zxaber updated:-
01 July 2020-ATH1909 updated:-
ATHATH updated:-
Melbert updated:-
TaF updated:-
Wayland-Smithy updated:-
carshalash updated:-
ivanmixo updated:-
nightred updated:-
30 June 2020-ATH1909 updated:-
Arkatos updated:-
Iatots updated:-
Ryll/Shaps updated:-
ShizCalev updated:-
WarlockD updated:-
sprites, Edge code updated:-
29 June 2020-FloranOtten updated:-
ShizCalev updated:-
anconfuzedrock updated:-
and KathyRyals updated:-
28 June 2020-ATHATH updated:-
ArcaneMusic updated:-
Cyberboss updated:-
EdgeLordExe updated:-
Fikou updated:-
Hopek updated:-
KathyRyals updated:-
ShizCalev updated:-
XRandomXManX updated:-
necromanceranne updated:-
nightred updated:-
silicons updated:-
27 June 2020-Ryll/Shaps updated:-
Tlaltecuhtli updated:-
26 June 2020-Arkatos updated:-
Ryll/Shaps updated:-
ShizCalev updated:-
WarlockD updated:-
coiax updated:-
sergeirocks100 updated:-
25 June 2020-ATHATH updated:-
EdgeLordExe updated:-
Jared-Fogle updated:-
Melbert updated:-
WarlockD updated:-
dearmochi updated:-
24 June 2020-ArcaneMusic updated:-
Arkatos updated:-
Caldony updated:-
EdgeLordExe updated:-
LemonInTheDark updated:-
Maurukas updated:-
ShizCalev updated:-
TemporalOroboros updated:-
Timberpoes updated:-
WarlockD updated:-
tmtmtl30 updated:-
23 June 2020-Kathy Ryals updated:-
LemonInTheDark updated:-
LemonInTheDark, Heather Shadelight updated:-
Paxilmaniac updated:-
ShizCalev updated:-
Timberpoes updated:-
bobbahbrown updated:-
silicons updated:-
zxaber updated:-
22 June 2020-EdgeLordExe updated:-
Gamer025 updated:-
Kathy Ryals updated:-
Melbert updated:-
TemporalOroboros updated:-
WarlockD updated:-
21 June 2020-Jared-Fogle updated:-
20 June 2020-Caldony updated:-
LemonInTheDark updated:-
19 June 2020-Kathy Ryals updated:-
LemonInTheDark updated:-
Ryll/Shaps updated:-
SteelSlayer updated:-
WarlockD updated:-
genessee596 updated:-
18 June 2020-ATHATH updated:-
Iamgoofball updated:-
ShizCalev updated:-
TheSpaghetti updated:-
Timberpoes updated:-
Tlaltecuhtli updated:-
WarlockD updated:-
tralezab updated:-
17 June 2020-EdgeLordExe updated:-
Firecage updated:-
LoserWasTaken updated:-
Melbert updated:-
Mickyan updated:-
Ryll/Shaps updated:-
ShizCalev updated:-
TheChosenEvilOne updated:-
15 June 2020-Cobby kills medbots!!! updated:-
IradT updated:-
Jared-Fogle updated:-
Shadark updated:-
ShizCalev updated:-
14 June 2020-Arkatos updated:-
Fikou updated:-
Iamgoofball updated:-
Jared-Fogle updated:-
a few Sprites from Kryson updated:-
bobbahbrown updated:-
dragomagol updated:-
~~yorii~~ Space updated:-
13 June 2020-ATHATH updated:-
Arkatos updated:-
Ryll/Shaps updated:-
Shadark updated:-
ShizCalev updated:-
tmtmtl30 updated:-
12 June 2020-ATHATH updated:-
Jared-Fogle updated:-
Ryll/Shaps updated:-
Timberpoes updated:-
11 June 2020-Arkatos updated:-
Inept updated:-
ShizCalev updated:-
tmtmtl30 updated:-
10 June 2020-ATHATH updated:-
ArcaneMusic updated:-
Arkatos updated:-
Cobby updated:-
Fox McCloud updated:-
GoldenAlpharex updated:-
Inept updated:-
Jared-Fogle updated:-
Kelenius updated:-
Ryll/Shaps updated:-
ShizCalev updated:-
TheChosenEvilOne updated:-
TiviPlus updated:-
bababooey updated:-
bobbahbrown updated:-
tmtmtl30 updated:-
08 June 2020-IndieanaJones updated:-
SpaceManiac updated:-
07 June 2020-LemonInTheDark updated:-
TheChosenEvilOne updated:-
tmtmtl30 updated:-
06 June 2020-IradT updated:-
Ryll/Shaps updated:-
05 June 2020-LemonInTheDark updated:-
MrDoomBringer updated:-
nemvar updated:-
04 June 2020-ATHATH updated:-
ArcaneMusic updated:-
Fikou updated:-
Ryll/Shaps updated:-
Skoglol updated:-
TheChosenEvilOne updated:-
Tlaltecuhtli updated:-
necromanceranne updated:-
02 June 2020-ArcaneMusic updated:-
EOBGames, ArcaneMusic, LemonInTheDark updated:-
Kelenius updated:-
01 June 2020-Fhaxaris updated:-
Fikou updated:-
PrimordialOoze updated:-
SomeoneYouProbablyKnow updated:-
TemporalOroboros updated:-
Timberpoes updated:-
nemvar updated:-
31 May 2020-Fikou updated:-
Helianthus00 updated:-
MacBlaze1 updated:-
30 May 2020-ArcaneMusic updated:-
Kathy Ryals updated:-
MrDoomBringer updated:-
Ryll/Shaps updated:-
Shadark updated:-
29 May 2020-ArcaneMusic updated:-
AsphaltEvidence updated:-
MrDoomBringer updated:-
Qustinnus updated:-
TheVekter updated:-
nemvar updated:-
willox updated:-
27 May 2020-ArcaneMusic updated:-
ArcaneMusic/Azlan updated:-
Kathy Ryals updated:-
Krysonism updated:-
Kurgis updated:-
LemonInTheDark updated:-
MacBlaze1 updated:-
Qustinnus updated:-
Ryll/Shaps updated:-
WarlockD updated:-
actioninja updated:-
nemvar updated:-
ohnoitsdixie updated:-
willox updated:-
zxaber updated:-
26 May 2020-Fikou, spookydonut made the glove code sane updated:-
JoshAdamPowell updated:-
MrDoomBringer updated:-
Paxilmaniac updated:-
Pumpkinoe updated:-
Ryll/Shaps updated:-
TerraGS updated:-
Timberpoes updated:-
Tlaltecuhtli updated:-
WarlockD updated:-
kevinz000 updated:-
25 May 2020-Cyberboss updated:-
Fikou updated:-
Gamer025 updated:-
Kelenius updated:-
LemonInTheDark updated:-
LemonInTheDark, with thanks to ArcaneDefence for the pointer updated:-
MarioWizard119 updated:-
NewSta updated:-
Ryll/Shaps updated:-
Shadark updated:-
TetraK1 updated:-
TheVekter updated:-
actioninja updated:-
antropod updated:-
kevinz000 updated:-
nemvar updated:-
qustinnus updated:-
spessman-007 updated:-
tralezab updated:-
wesoda25 updated:-
zxaber updated:-
24 May 2020-Cobby updated:-
Fikou updated:-
qustinnus updated:-
22 May 2020-ArcaneMusic updated:-
Dorsidwarf updated:-
Fikou updated:-
Ghilker updated:-
Mickyan updated:-
Whoneedspacee updated:-
kevinz000 updated:-
wesoda25 updated:-
willox updated:-
20 May 2020-Skoglol updated:-
Thebleh updated:-
dootdoom updated:-
17 May 2020-Nebulacrity for the sprites, LemonInTheDark for chopshop job updated:-
15 May 2020-PKPenguin321 updated:-
nemvar updated:-
13 May 2020-ATHATH updated:-
Fikou updated:-
Inept updated:-
ThePainkiller updated:-
rdragan updated:-
12 May 2020-Rodey125 updated:-
TheVekter updated:-
11 May 2020-LemonInTheDark updated:-
Naksu updated:-
antropod updated:-
nemvar updated:-
10 May 2020-Couls updated:-
Fikou updated:-
Inept updated:-
MMMiracles updated:-
MacBlaze1 updated:-
Mickyan updated:-
Nebulacrity for the sprites, LemonInTheDark for the mule work updated:-
NoxVS updated:-
Paxilmaniac updated:-
Qustinnus updated:-
Qustinnus & MrDoomBringer updated:-
Ryll/Shaps updated:-
Shadark updated:-
Skoglol updated:-
SteelSlayer updated:-
TemporalOroboros updated:-
TerraGS updated:-
Thebleh updated:-
Timberpoes updated:-
TiviPlus updated:-
XDTM updated:-
actioninja updated:-
dootdoom updated:-
spessman-007 updated:-
vuonojenmustaturska updated:-
09 May 2020-RaveRadbury updated:-
Ryll/Shaps updated:-
Skoglol updated:-
TheVekter updated:-
nemvar updated:-
08 May 2020-LemonInTheDark updated:-
Tlaltecuhtli updated:-
WarlockD updated:-
redguy999 updated:-
07 May 2020-Cartographer-D updated:-
Fikou updated:-
Qustinnus (sprites from Lohikar) updated:-
Qustinnus, AnturK updated:-
uomo91 updated:-
willox updated:-
- Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
-- Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No - -
Some icons by Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 License. - |
+
+
+
+GoonStation 13 Development Team
+ 13 July 2020+Tlaltecuhtli updated:+
12 July 2020+ATHATH updated:+
Alterist updated:+
Angust updated:+
ArcaneMusic updated:+
Dennok updated:+
EdgeLordExe updated:+
Fikou updated:+
Jay Smith & MrDoomBringer updated:+
Kathy Ryals and ArcaneMusic updated:+
LemonInTheDark updated:+
LoserWasTaken updated:+
Maurukas updated:+
Melbert updated:+
MrDoomBringer updated:+
Ryll/Shaps updated:+
ShizCalev updated:+
Skoglol updated:+
Tlaltecuhtli updated:+
Wayland-Smithy updated:+
YPOQ updated:+
silicons updated:+
tralezab updated:+
uomo91 updated:+
11 July 2020+ShizCalev updated:+
Timberpoes updated:+
nemvar updated:+
tralezab updated:+
09 July 2020+EdgeLordExe updated:+
Jared-Fogle updated:+
Melbert updated:+
Timberpoes updated:+
nightred updated:+
zxaber updated:+
08 July 2020+ArcaneMusic updated:+
Fikou updated:+
FloranOtten updated:+
Jared-Fogle updated:+
Melbert updated:+
ShizCalev updated:+
Tlaltecuhtli updated:+
Wayland-Smithy updated:+
oranges updated:+
tralezab updated:+
07 July 2020+ATHATH updated:+
ArcaneMusic updated:+
EdgeLordExe updated:+
Fikou updated:+
Jared-Fogle updated:+
Jay Smith updated:+
Kathy Ryals updated:+
LemonInTheDark updated:+
Orchian updated:+
ShizCalev updated:+
TetraZeta, NecromancerAnne updated:+
TheVekter updated:+
bobbahbrown updated:+
nightred updated:+
zxaber updated:+
06 July 2020+ATHATH updated:+
Anturk + Arm + other summer ball contributors code, trollbreeder + fikou + jerryderpington mapping updated:+
ArcaneMusic updated:+
Arkatos updated:+
Disco updated:+
EdgeLordExe updated:+
Inept, KathyRyals updated:+
Jay Smith & Michael Trauf updated:+
LemonInTheDark updated:+
Melbert updated:+
MrDoomBringer / Ryll-Ryll updated:+
Ryll/Shaps updated:+
ShizCalev updated:+
Skoglol updated:+
Timberpoes & Kathy Ryals updated:+
Wayland-Smithy updated:+
05 July 2020+Caldony updated:+
Disco updated:+
Firecage updated:+
Fox McCloud updated:+
Iatots updated:+
LemonInTheDark updated:+
XRandomXManX updated:+
anconfuzedrock updated:+
nightred updated:+
04 July 2020+ArcaneMusic updated:+
Tlaltecuhtli updated:+
ivanmixo updated:+
03 July 2020+Jared-Fogle updated:+
ShizCalev updated:+
WarlockD updated:+
bobbahbrown updated:+
zxaber updated:+
01 July 2020+ATH1909 updated:+
ATHATH updated:+
Melbert updated:+
TaF updated:+
Wayland-Smithy updated:+
carshalash updated:+
ivanmixo updated:+
nightred updated:+
30 June 2020+ATH1909 updated:+
Arkatos updated:+
Iatots updated:+
Ryll/Shaps updated:+
ShizCalev updated:+
WarlockD updated:+
sprites, Edge code updated:+
29 June 2020+FloranOtten updated:+
ShizCalev updated:+
anconfuzedrock updated:+
and KathyRyals updated:+
28 June 2020+ATHATH updated:+
ArcaneMusic updated:+
Cyberboss updated:+
EdgeLordExe updated:+
Fikou updated:+
Hopek updated:+
KathyRyals updated:+
ShizCalev updated:+
XRandomXManX updated:+
necromanceranne updated:+
nightred updated:+
silicons updated:+
27 June 2020+Ryll/Shaps updated:+
Tlaltecuhtli updated:+
26 June 2020+Arkatos updated:+
Ryll/Shaps updated:+
ShizCalev updated:+
WarlockD updated:+
coiax updated:+
sergeirocks100 updated:+
25 June 2020+ATHATH updated:+
EdgeLordExe updated:+
Jared-Fogle updated:+
Melbert updated:+
WarlockD updated:+
dearmochi updated:+
24 June 2020+ArcaneMusic updated:+
Arkatos updated:+
Caldony updated:+
EdgeLordExe updated:+
LemonInTheDark updated:+
Maurukas updated:+
ShizCalev updated:+
TemporalOroboros updated:+
Timberpoes updated:+
WarlockD updated:+
tmtmtl30 updated:+
23 June 2020+Kathy Ryals updated:+
LemonInTheDark updated:+
LemonInTheDark, Heather Shadelight updated:+
Paxilmaniac updated:+
ShizCalev updated:+
Timberpoes updated:+
bobbahbrown updated:+
silicons updated:+
zxaber updated:+
22 June 2020+EdgeLordExe updated:+
Gamer025 updated:+
Kathy Ryals updated:+
Melbert updated:+
TemporalOroboros updated:+
WarlockD updated:+
21 June 2020+Jared-Fogle updated:+
20 June 2020+Caldony updated:+
LemonInTheDark updated:+
19 June 2020+Kathy Ryals updated:+
LemonInTheDark updated:+
Ryll/Shaps updated:+
SteelSlayer updated:+
WarlockD updated:+
genessee596 updated:+
18 June 2020+ATHATH updated:+
Iamgoofball updated:+
ShizCalev updated:+
TheSpaghetti updated:+
Timberpoes updated:+
Tlaltecuhtli updated:+
WarlockD updated:+
tralezab updated:+
17 June 2020+EdgeLordExe updated:+
Firecage updated:+
LoserWasTaken updated:+
Melbert updated:+
Mickyan updated:+
Ryll/Shaps updated:+
ShizCalev updated:+
TheChosenEvilOne updated:+
15 June 2020+Cobby kills medbots!!! updated:+
IradT updated:+
Jared-Fogle updated:+
Shadark updated:+
ShizCalev updated:+
14 June 2020+Arkatos updated:+
Fikou updated:+
Iamgoofball updated:+
Jared-Fogle updated:+
a few Sprites from Kryson updated:+
bobbahbrown updated:+
dragomagol updated:+
~~yorii~~ Space updated:+
13 June 2020+ATHATH updated:+
Arkatos updated:+
Ryll/Shaps updated:+
Shadark updated:+
ShizCalev updated:+
tmtmtl30 updated:+
12 June 2020+ATHATH updated:+
Jared-Fogle updated:+
Ryll/Shaps updated:+
Timberpoes updated:+
11 June 2020+Arkatos updated:+
Inept updated:+
ShizCalev updated:+
tmtmtl30 updated:+
10 June 2020+ATHATH updated:+
ArcaneMusic updated:+
Arkatos updated:+
Cobby updated:+
Fox McCloud updated:+
GoldenAlpharex updated:+
Inept updated:+
Jared-Fogle updated:+
Kelenius updated:+
Ryll/Shaps updated:+
ShizCalev updated:+
TheChosenEvilOne updated:+
TiviPlus updated:+
bababooey updated:+
bobbahbrown updated:+
tmtmtl30 updated:+
08 June 2020+IndieanaJones updated:+
SpaceManiac updated:+
07 June 2020+LemonInTheDark updated:+
TheChosenEvilOne updated:+
tmtmtl30 updated:+
06 June 2020+IradT updated:+
Ryll/Shaps updated:+
05 June 2020+LemonInTheDark updated:+
MrDoomBringer updated:+
nemvar updated:+
04 June 2020+ATHATH updated:+
ArcaneMusic updated:+
Fikou updated:+
Ryll/Shaps updated:+
Skoglol updated:+
TheChosenEvilOne updated:+
Tlaltecuhtli updated:+
necromanceranne updated:+
02 June 2020+ArcaneMusic updated:+
EOBGames, ArcaneMusic, LemonInTheDark updated:+
Kelenius updated:+
01 June 2020+Fhaxaris updated:+
Fikou updated:+
PrimordialOoze updated:+
SomeoneYouProbablyKnow updated:+
TemporalOroboros updated:+
Timberpoes updated:+
nemvar updated:+
31 May 2020+Fikou updated:+
Helianthus00 updated:+
MacBlaze1 updated:+
30 May 2020+ArcaneMusic updated:+
Kathy Ryals updated:+
MrDoomBringer updated:+
Ryll/Shaps updated:+
Shadark updated:+
29 May 2020+ArcaneMusic updated:+
AsphaltEvidence updated:+
MrDoomBringer updated:+
Qustinnus updated:+
TheVekter updated:+
nemvar updated:+
willox updated:+
27 May 2020+ArcaneMusic updated:+
ArcaneMusic/Azlan updated:+
Kathy Ryals updated:+
Krysonism updated:+
Kurgis updated:+
LemonInTheDark updated:+
MacBlaze1 updated:+
Qustinnus updated:+
Ryll/Shaps updated:+
WarlockD updated:+
actioninja updated:+
nemvar updated:+
ohnoitsdixie updated:+
willox updated:+
zxaber updated:+
26 May 2020+Fikou, spookydonut made the glove code sane updated:+
JoshAdamPowell updated:+
MrDoomBringer updated:+
Paxilmaniac updated:+
Pumpkinoe updated:+
Ryll/Shaps updated:+
TerraGS updated:+
Timberpoes updated:+
Tlaltecuhtli updated:+
WarlockD updated:+
kevinz000 updated:+
25 May 2020+Cyberboss updated:+
Fikou updated:+
Gamer025 updated:+
Kelenius updated:+
LemonInTheDark updated:+
LemonInTheDark, with thanks to ArcaneDefence for the pointer updated:+
MarioWizard119 updated:+
NewSta updated:+
Ryll/Shaps updated:+
Shadark updated:+
TetraK1 updated:+
TheVekter updated:+
actioninja updated:+
antropod updated:+
kevinz000 updated:+
nemvar updated:+
qustinnus updated:+
spessman-007 updated:+
tralezab updated:+
wesoda25 updated:+
zxaber updated:+
24 May 2020+Cobby updated:+
Fikou updated:+
qustinnus updated:+
22 May 2020+ArcaneMusic updated:+
Dorsidwarf updated:+
Fikou updated:+
Ghilker updated:+
Mickyan updated:+
Whoneedspacee updated:+
kevinz000 updated:+
wesoda25 updated:+
willox updated:+
20 May 2020+Skoglol updated:+
Thebleh updated:+
dootdoom updated:+
17 May 2020+Nebulacrity for the sprites, LemonInTheDark for chopshop job updated:+
15 May 2020+PKPenguin321 updated:+
nemvar updated:+
13 May 2020+ATHATH updated:+
Fikou updated:+
Inept updated:+
ThePainkiller updated:+
rdragan updated:+
12 May 2020+Rodey125 updated:+
TheVekter updated:+
+ Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
++ Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No + +
Some icons by Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 License. + |