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] += "[C.author][C.title][C.category]\[Order\]\n" + var/printer_cooldown = 0 + COOLDOWN_DECLARE(library_console_topic_cooldown) /obj/machinery/computer/bookmanagement/Initialize() . = ..() @@ -295,17 +250,37 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums dat += "(Return to main menu)
" if(4) dat += "

External Archive

" - build_library_menu() - - if(!GLOB.cachedbooks) + if(!SSdbcore.Connect()) dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance." else + var/booksperpage = 50 + var/pagecount + var/datum/db_query/query_library_count_books = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("library")] WHERE isnull(deleted)") + if(!query_library_count_books.Execute()) + qdel(query_library_count_books) + return + if(query_library_count_books.NextRow()) + pagecount = CEILING(text2num(query_library_count_books.item[1]) / booksperpage, 1) + qdel(query_library_count_books) + var/list/booklist = list() + var/datum/db_query/query_library_get_books = SSdbcore.NewQuery({" + SELECT id, author, title, category + FROM [format_table_name("library")] + WHERE isnull(deleted) + LIMIT :skip, :take + "}, list("skip" = booksperpage * (page - 1), "take" = booksperpage)) + if(!query_library_get_books.Execute()) + qdel(query_library_get_books) + return + while(query_library_get_books.NextRow()) + booklist += "[query_library_get_books.item[2]][query_library_get_books.item[3]][query_library_get_books.item[4]]\[Order\]\n" dat += "(Order book by SS13BN)

" dat += "" dat += "" - dat += libcomp_menu[clamp(page,1,libcomp_menu.len)] - dat += "" + dat += jointext(booklist, "") + dat += "" dat += "
AUTHORTITLECATEGORY
<<<< >>>>
<<<< >>>>
" + qdel(query_library_get_books) dat += "
(Return to main menu)
" if(5) dat += "

Upload a New Title

" @@ -377,6 +352,9 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums obj_flags |= EMAGGED /obj/machinery/computer/bookmanagement/Topic(href, href_list) + if(!COOLDOWN_FINISHED(src, library_console_topic_cooldown)) + return + COOLDOWN_START(src, library_console_topic_cooldown, 1 SECONDS) if(..()) usr << browse(null, "window=library") onclose(usr, "library") @@ -474,7 +452,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums GLOB.news_network.SubmitArticle(scanner.cache.dat, "[scanner.cache.name]", "Nanotrasen Book Club", null) alert("Upload complete. Your uploaded title is now available on station newscasters.") if(href_list["orderbyid"]) - if(cooldown > world.time) + if(printer_cooldown > world.time) say("Printer unavailable. Please allow a short time before attempting to print.") else var/orderid = input("Enter your order:") as num|null @@ -486,10 +464,10 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums var/id = href_list["targetid"] if (!SSdbcore.Connect()) alert("Connection to Archive has been severed. Aborting.") - if(cooldown > world.time) + if(printer_cooldown > world.time) say("Printer unavailable. Please allow a short time before attempting to print.") else - cooldown = world.time + PRINTER_COOLDOWN + printer_cooldown = world.time + PRINTER_COOLDOWN var/datum/db_query/query_library_print = SSdbcore.NewQuery( "SELECT * FROM [format_table_name("library")] WHERE id=:id AND isnull(deleted)", list("id" = id) @@ -513,20 +491,20 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums break qdel(query_library_print) if(href_list["printbible"]) - if(cooldown < world.time) + if(printer_cooldown < world.time) var/obj/item/storage/book/bible/B = new /obj/item/storage/book/bible(src.loc) if(GLOB.bible_icon_state && GLOB.bible_inhand_icon_state) B.icon_state = GLOB.bible_icon_state B.inhand_icon_state = GLOB.bible_inhand_icon_state B.name = GLOB.bible_name B.deity_name = GLOB.deity - cooldown = world.time + PRINTER_COOLDOWN + printer_cooldown = world.time + PRINTER_COOLDOWN else say("Printer currently unavailable, please wait a moment.") if(href_list["printposter"]) - if(cooldown < world.time) + if(printer_cooldown < world.time) new /obj/item/poster/random_official(src.loc) - cooldown = world.time + PRINTER_COOLDOWN + printer_cooldown = world.time + PRINTER_COOLDOWN else say("Printer currently unavailable, please wait a moment.") add_fingerprint(usr) diff --git a/code/modules/mafia/_defines.dm b/code/modules/mafia/_defines.dm index 5925f15586b..b862ce63c5c 100644 --- a/code/modules/mafia/_defines.dm +++ b/code/modules/mafia/_defines.dm @@ -46,12 +46,6 @@ GLOBAL_LIST_INIT(mafia_setups,generate_mafia_setups()) var/list/roles // 12 Player -/datum/mafia_setup/twelve_vanilla - name = "12 Player Setup Vanilla" - roles = list( - /datum/mafia_role=9, - /datum/mafia_role/mafia=3 - ) /datum/mafia_setup/twelve_basic name = "12 Player Setup Basic" @@ -68,7 +62,7 @@ GLOBAL_LIST_INIT(mafia_setups,generate_mafia_setups()) roles = list( /datum/mafia_role=6, /datum/mafia_role/md=3, - /datum/mafia_role/mafia=4 + /datum/mafia_role/mafia=3 ) /datum/mafia_setup/twelve_all diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm index aa8f2cb48dc..f8781ca65cb 100644 --- a/code/modules/mafia/controller.dm +++ b/code/modules/mafia/controller.dm @@ -1,35 +1,62 @@ + + +/** + * The mafia controller handles the mafia minigame in progress. + * It is first created when the first ghost signs up to play. + */ /datum/mafia_controller + ///all roles in the game, dead or alive. check their game status if you only want living or dead. var/list/all_roles = list() - var/list/player_role_lookup = list() //This only exists to speed up role retrieval + ///exists to speed up role retrieval, it's a dict. player_role_lookup[player ckey] will give you the role they play + var/list/player_role_lookup = list() + ///what part of the game you're playing in. day phases, night phases, judgement phases, etc. var/phase = MAFIA_PHASE_SETUP + ///how long the game has gone on for, changes with every sunrise. day one, night one, day two, etc. var/turn = 0 - var/first_day_phase_period = 20 SECONDS //say hi to everyone, no voting so no discussion - var/day_phase_period = 1 MINUTES //talk with others about the night - var/voting_phase_period = 30 SECONDS //vote someone to get put on trial - var/judgement_phase_period = 30 SECONDS //defend yourself! don't get lynched! sometimes skipped - var/judgement_lynch_period = 5 SECONDS //just watch a guy die (or live but lol) - var/night_phase_period = 45 SECONDS //mafia talk and pick someone to kill - var/victory_lap_period = 20 SECONDS //just waiting around sayin' woop woop + ///first day has no voting, and thus is shorter + var/first_day_phase_period = 20 SECONDS + ///talk with others about the last night + var/day_phase_period = 1 MINUTES + ///vote someone to get put on trial + var/voting_phase_period = 30 SECONDS + ///defend yourself! don't get lynched! sometimes skipped if nobody votes. + var/judgement_phase_period = 30 SECONDS + ///guilty or innocent, we want a bit of time for players to process the outcome of the vote + var/judgement_lynch_period = 5 SECONDS + ///mafia talk at night and pick someone to kill, some town roles use their actions, etc etc. + var/night_phase_period = 45 SECONDS + ///like the lynch period, players need to see what the other players in the game's roles were + var/victory_lap_period = 20 SECONDS + ///template picked when the game starts. used for the name and desc reading var/datum/map_template/mafia/current_map + ///map generation tool that deletes the current map after the game finishes var/datum/map_generator/massdelete/map_deleter - var/list/current_setup_text //Redable list of roles in current game + ///Readable list of roles in current game, sent to the tgui panel for roles list > list("Psychologist x1", "Clown x2") + var/list/current_setup_text - var/player_outfit = /datum/outfit/mafia //todo some fluffy outfit + ///starting outfit for all mafia players. it's just a grey jumpsuit. + var/player_outfit = /datum/outfit/mafia - var/list/landmarks = list() //spawn points for players, each one has a house - var/town_center_landmark = null //town center for when people get put on trial + ///spawn points for players, each one has a house + var/list/landmarks = list() + ///town center for when people get put on trial + var/town_center_landmark - var/list/votes = list() //group voting on one person, like putting people to trial or choosing who to kill as mafia - //and these are the judgement phase votes, aka people sorting themselves into guilty and innocent lists. whichever has more wins! + ///group voting on one person, like putting people to trial or choosing who to kill as mafia + var/list/votes = list() + ///and these (judgement_innocent_votes and judgement_guilty_votes) are the judgement phase votes, aka people sorting themselves into guilty and innocent lists. whichever has more wins! var/list/judgement_innocent_votes = list() var/list/judgement_guilty_votes = list() - var/datum/mafia_role/on_trial = null + ///current role on trial for the judgement phase, will die if guilty is greater than innocent + var/datum/mafia_role/on_trial + ///current timer for phase var/next_phase_timer + ///used for debugging in testing (doesn't put people out of the game, some other shit i forgot, who knows just don't set this in live) honestly kinda deprecated var/debug = FALSE /datum/mafia_controller/New() @@ -43,6 +70,20 @@ end_game() qdel(map_deleter) +/** + * Triggers at beginning of the game when there is a confirmed list of valid, ready players. + * Creates a 100% ready game that has NOT started (no players in bodies) + * Followed by start game + * + * Does the following: + * * Picks map, and loads it + * * Grabs landmarks if it is the first time it's loading + * * Sets up the role list + * * Puts players in each role randomly + * Arguments: + * * setup_list: list of all the datum setups (fancy list of roles) that would work for the game + * * ready_players: list of filtered, sane players (so not playing or disconnected) for the game to put into roles + */ /datum/mafia_controller/proc/prepare_game(setup_list,ready_players) var/list/possible_maps = subtypesof(/datum/map_template/mafia) @@ -87,15 +128,28 @@ var/team_suffix = team ? "([uppertext(team)] CHAT)" : "" for(var/M in GLOB.dead_mob_list) var/mob/spectator = M - if(!(spectator in GLOB.mafia_signup) || player_role_lookup[spectator.ckey] == null) - continue - var/link = FOLLOW_LINK(M, town_center_landmark) - to_chat(M, "[link] MAFIA: [msg] [team_suffix]") + if(spectator.ckey in GLOB.mafia_signup || player_role_lookup[spectator.mind.current] != null) //was in current game, or is signed up + var/link = FOLLOW_LINK(M, town_center_landmark) + to_chat(M, "[link] MAFIA: [msg] [team_suffix]") +/** + * The game by this point is now all set up, and so we can put people in their bodies and start the first phase. + * + * Does the following: + * * Creates bodies for all of the roles with the first proc + * * Starts the first day manually (so no timer) with the second proc + */ /datum/mafia_controller/proc/start_game() create_bodies() start_day() +/** + * How every day starts. + * + * What players do in this phase: + * * If day one, just a small starting period to see who is in the game and check role, leading to the night phase. + * * Otherwise, it's a longer period used to discuss events that happened during the night, leading to the voting phase. + */ /datum/mafia_controller/proc/start_day() turn += 1 phase = MAFIA_PHASE_DAY @@ -110,13 +164,29 @@ SStgui.update_uis(src) - +/** + * Players have finished the discussion period, and now must put up someone to the chopping block. + * + * What players do in this phase: + * * Vote on which player to put up for lynching, leading to the judgement phase. + * * If no votes are case, the judgement phase is skipped, leading to the night phase. + */ /datum/mafia_controller/proc/start_voting_phase() phase = MAFIA_PHASE_VOTING next_phase_timer = addtimer(CALLBACK(src, .proc/check_trial, TRUE),voting_phase_period,TIMER_STOPPABLE) //be verbose! send_message("Voting started! Vote for who you want to see on trial today.") SStgui.update_uis(src) +/** + * Players have voted someone up, and now the person must defend themselves while the town votes innocent or guilty. + * + * What players do in this phase: + * * Vote innocent or guilty, if they are not on trial. + * * Defend themselves and wait for judgement, if they are. + * * Leads to the lynch phase. + * Arguments: + * * verbose: boolean, announces whether there were votes or not. after judgement it goes back here with no voting period to end the day. + */ /datum/mafia_controller/proc/check_trial(verbose = TRUE) var/datum/mafia_role/loser = get_vote_winner("Day")//, majority_of_town = TRUE) if(loser) @@ -133,6 +203,13 @@ lockdown() SStgui.update_uis(src) +/** + * Players have voted innocent or guilty on the person on trial, and that person is now killed or returned home. + * + * What players do in this phase: + * * r/watchpeopledie + * * If the accused is killed, their true role is revealed to the rest of the players. + */ /datum/mafia_controller/proc/lynch() for(var/i in judgement_innocent_votes) var/datum/mafia_role/role = i @@ -154,15 +231,32 @@ //day votes are already cleared, so this will skip the trial and check victory/lockdown/whatever else next_phase_timer = addtimer(CALLBACK(src, .proc/check_trial, FALSE),judgement_lynch_period,TIMER_STOPPABLE)// small pause to see the guy dead, no verbosity since we already did this +/** + * Teenie helper proc to move players back to their home. + * Used in the above, but also used in the debug button "send all players home" + * Arguments: + * * role: mafia role that is getting sent back to the game. + */ /datum/mafia_controller/proc/send_home(datum/mafia_role/role) role.body.forceMove(get_turf(role.assigned_landmark)) +/** + * Checks to see if a faction (or solo antagonist) has won. + * + * Calculates in this order: + * * counts up town, mafia, and solo + * * solos can count as town members for the purposes of mafia winning + * * sends the amount of living people to the solo antagonists, and see if they won OR block the victory of the teams + * * checks if solos won from above, then if town, then if mafia + * * starts the end of the game if a faction won + * * returns TRUE if someone won the game, halting other procs from continuing in the case of a victory + */ /datum/mafia_controller/proc/check_victory() var/alive_town = 0 var/alive_mafia = 0 var/list/solos_to_ask = list() //need to ask after because first round is counting team sizes - var/list/total_victors = null //if this has someone, they won alone. list because side antags can with with people - var/blocked_victory = FALSE + var/list/total_victors = list() //if this list gets filled with anyone, they win. list because side antags can with with people + var/blocked_victory = FALSE //if a solo antagonist is stopping the town or mafia from finishing the game. ///PHASE ONE: TALLY UP ALL NUMBERS OF PEOPLE STILL ALIVE @@ -189,11 +283,12 @@ //solo victories! var/solo_end = FALSE for(var/datum/mafia_role/winner in total_victors) - send_message("!! [uppertext(winner.name)] VICTORY !!") + send_message("!! [uppertext(winner.name)] VICTORY !!") solo_end = TRUE if(solo_end) start_the_end() - if(blocked_victory)//a solo antag is stopping game from ending + return TRUE + if(blocked_victory) return FALSE if(alive_mafia == 0) start_the_end("!! TOWN VICTORY !!") @@ -202,6 +297,16 @@ start_the_end("!! MAFIA VICTORY !!") return TRUE +/** + * The end of the game is in two procs, because we want a bit of time for players to see eachothers roles. + * Because of how check_victory works, the game is halted in other places by this point. + * + * What players do in this phase: + * * See everyone's role postgame + * * See who won the game + * Arguments: + * * message: string, if non-null it sends it to all players. used to announce team victories while solos are handled in check victory + */ /datum/mafia_controller/proc/start_the_end(message) SEND_SIGNAL(src,COMSIG_MAFIA_GAME_END) if(message) @@ -211,6 +316,9 @@ phase = MAFIA_PHASE_VICTORY_LAP next_phase_timer = addtimer(CALLBACK(src,.proc/end_game),victory_lap_period,TIMER_STOPPABLE) +/** + * Cleans up the game, resetting variables back to the beginning and removing the map with the generator. + */ /datum/mafia_controller/proc/end_game() map_deleter.generate() //remove the map, it will be loaded at the start of the next one @@ -220,10 +328,18 @@ votes = list() phase = MAFIA_PHASE_SETUP +/** + * After the voting and judgement phases, the game goes to night shutting the windows and beginning night with a proc. + */ /datum/mafia_controller/proc/lockdown() toggle_night_curtains(close=TRUE) start_night() +/** + * Shuts poddoors attached to mafia. + * Arguments: + * * close: boolean, the state you want the curtains in. + */ /datum/mafia_controller/proc/toggle_night_curtains(close) for(var/obj/machinery/door/poddoor/D in GLOB.machines) //I really dislike pathing of these if(D.id != "mafia") //so as to not trigger shutters on station, lol @@ -233,6 +349,13 @@ else INVOKE_ASYNC(D, /obj/machinery/door/poddoor.proc/open) +/** + * The actual start of night for players. Mostly info is given at the start of the night as the end of the night is when votes and actions are submitted and tried. + * + * What players do in this phase: + * * Mafia are told to begin voting on who to kill + * * Powers that are picked during the day announce themselves right now + */ /datum/mafia_controller/proc/start_night() phase = MAFIA_PHASE_NIGHT send_message("Night [turn] started! Lockdown will end in 45 seconds.") @@ -240,6 +363,17 @@ next_phase_timer = addtimer(CALLBACK(src, .proc/resolve_night),night_phase_period,TIMER_STOPPABLE) SStgui.update_uis(src) +/** + * The end of the night, and a series of signals for the order of events on a night. + * + * Order of events, and what they mean: + * * Start of resolve (NIGHT_START) is for activating night abilities that MUST go first + * * Action phase (NIGHT_ACTION_PHASE) is for non-lethal day abilities + * * Mafia then tallies votes and kills the highest voted person (note: one random voter visits that person for the purposes of roleblocking) + * * Killing phase (NIGHT_KILL_PHASE) is for lethal night abilities + * * End of resolve (NIGHT_END) is for cleaning up abilities that went off and i guess doing some that must go last + * * Finally opens the curtains and calls the start of day phase, completing the cycle until check victory returns TRUE + */ /datum/mafia_controller/proc/resolve_night() SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_START) SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_ACTION_PHASE) @@ -259,6 +393,16 @@ start_day() SStgui.update_uis(src) +/** + * Proc that goes off when players vote for something with their mafia panel. + * + * If teams, it hides the tally overlay and only sends the vote messages to the team that is voting + * Arguments: + * * voter: the mafia role that is trying to vote for... + * * target: the mafia role that is getting voted for + * * vt: type of vote submitted (is this the day vote? is this the mafia night vote?) + * * teams: see mafia team defines for what to put in, makes the messages only send to a specific team (so mafia night votes only sending messages to mafia at night) + */ /datum/mafia_controller/proc/vote_for(datum/mafia_role/voter,datum/mafia_role/target,vt, teams) if(!votes[vt]) votes[vt] = list() @@ -277,6 +421,9 @@ if(old) old.body.update_icon() +/** + * Clears out the votes of a certain type (day votes, mafia kill votes) while leaving others untouched + */ /datum/mafia_controller/proc/reset_votes(vt) var/list/bodies_to_update = list() for(var/vote in votes[vt]) @@ -286,12 +433,24 @@ for(var/mob/M in bodies_to_update) M.update_icon() +/** + * Returns how many people voted for the role, in whatever vote (day vote, night kill vote) + * Arguments: + * * role: the mafia role the proc tries to get the amount of votes for + * * vt: the vote type (getting how many day votes were for the role, or mafia night votes for the role) + */ /datum/mafia_controller/proc/get_vote_count(role,vt) . = 0 for(var/votee in votes[vt]) if(votes[vt][votee] == role) . += 1 +/** + * Returns whichever role got the most votes, in whatever vote (day vote, night kill vote) + * returns null if no votes + * Arguments: + * * vt: the vote type (getting the role that got the most day votes, or the role that got the most mafia votes) + */ /datum/mafia_controller/proc/get_vote_winner(vt) var/list/tally = list() for(var/votee in votes[vt]) @@ -302,10 +461,21 @@ sortTim(tally,/proc/cmp_numeric_dsc,associative=TRUE) return length(tally) ? tally[1] : null +/** + * Returns a random person who voted for whatever vote (day vote, night kill vote) + * Arguments: + * * vt: vote type (getting a random day voter, or mafia night voter) + */ /datum/mafia_controller/proc/get_random_voter(vt) if(length(votes[vt])) return pick(votes[vt]) +/** + * Adds mutable appearances to people who get publicly voted on (so not night votes) showing how many people are picking them + * Arguments: + * * source: the body of the role getting the overlays + * * overlay_list: signal var passing the overlay list of the mob + */ /datum/mafia_controller/proc/display_votes(atom/source, list/overlay_list) if(phase != MAFIA_PHASE_VOTING) return @@ -313,6 +483,15 @@ var/mutable_appearance/MA = mutable_appearance('icons/obj/mafia.dmi',"vote_[v]") overlay_list += MA +/** + * Called when the game is setting up, AFTER map is loaded but BEFORE the phase timers start. Creates and places each role's body and gives the correct player key + * + * Notably: + * * Toggles godmode so the mafia players cannot kill themselves + * * Adds signals for voting overlays, see display_votes proc + * * gives mafia panel + * * sends the greeting text (goals, role name, etc) + */ /datum/mafia_controller/proc/create_bodies() for(var/datum/mafia_role/role in all_roles) var/mob/living/carbon/human/H = new(get_turf(role.assigned_landmark)) @@ -484,6 +663,11 @@ for(var/key in L) . += L[key] +/** + * Returns all setups that the amount of players signed up could support (so fill each role) + * Arguments: + * * ready_count: the amount of players signed up (not sane, so some players may have disconnected or rejoined ss13). + */ /datum/mafia_controller/proc/find_best_setup(ready_count) var/list/all_setups = GLOB.mafia_setups var/valid_setups = list() @@ -493,6 +677,12 @@ valid_setups += list(S) return length(valid_setups) > 0 ? pick(valid_setups) : null +/** + * Called when enough players have signed up to fill a setup. DOESN'T NECESSARILY MEAN THE GAME WILL START. + * + * Checks if everyone signed up is an observer, and is still connected. If people aren't, they're removed from the list. + * If there aren't enough players post sanity, it aborts. otherwise, it selects enough people for the game and starts preparing the game for real. + */ /datum/mafia_controller/proc/basic_setup() var/ready_count = length(GLOB.mafia_signup) var/list/setup = find_best_setup(ready_count) @@ -531,6 +721,11 @@ prepare_game(setup,filtered_keys) start_game() +/** + * Called when someone signs up, and sees if there are enough people in the signup list to begin. + * + * Only checks if everyone is actually valid to start (still connected and an observer) if there are enough players (basic_setup) + */ /datum/mafia_controller/proc/try_autostart() if(phase != MAFIA_PHASE_SETUP) return @@ -554,6 +749,9 @@ /datum/action/innate/mafia_panel/Activate() parent.ui_interact(owner) +/** + * Creates the global datum for playing mafia games, destroys the last if that's required and returns the new. + */ /proc/create_mafia_game() if(GLOB.mafia_game) QDEL_NULL(GLOB.mafia_game) diff --git a/code/modules/mafia/map_pieces.dm b/code/modules/mafia/map_pieces.dm index a63136a1dbf..f9f08af3f2a 100644 --- a/code/modules/mafia/map_pieces.dm +++ b/code/modules/mafia/map_pieces.dm @@ -30,6 +30,7 @@ requires_power = FALSE has_gravity = STANDARD_GRAVITY flags_1 = NONE + block_suicide = TRUE /datum/map_template/mafia var/description = "" @@ -54,11 +55,6 @@ description = "The haunted ghost UFO tour has gone south and now it's up to our fine townies and scare seekers to kill the actual real alien changelings..." mappath = "_maps/map_files/Mafia/mafia_ayylmao.dmm" -/datum/map_template/mafia/necropolis - name = "Necropolis Showdown" - description = "The townies have shown up to try and suss out who truly ruined the art direction of SS13. No hurt feelings intended!" - mappath = "_maps/map_files/Mafia/mafia_necropolis.dmm" - /datum/map_template/mafia/spider_clan name = "Spider Clan Kidnapping" description = "New and improved spider clan kidnappings are a lot less boring and have a lot more lynching. Damn westaboos!" diff --git a/code/modules/mafia/roles.dm b/code/modules/mafia/roles.dm index 6c961df5d59..7eccfcd866a 100644 --- a/code/modules/mafia/roles.dm +++ b/code/modules/mafia/roles.dm @@ -41,8 +41,9 @@ . = ..() /datum/mafia_role/proc/greet() + SEND_SOUND(body, 'sound/ambience/ambifailure.ogg') to_chat(body,"You are the [name].") - to_chat(body,"[desc].") + to_chat(body,"[desc]") switch(team) if(MAFIA_TEAM_MAFIA) to_chat(body,"You and your co-conspirators win if you outnumber crewmembers.") @@ -273,7 +274,7 @@ /datum/mafia_role/psychologist name = "Psychologist" - desc = "You can visit a single member of the town to reveal their true role in the morning!" + desc = "You can visit someone ONCE PER GAME to reveal their true role in the morning!" revealed_outfit = /datum/outfit/mafia/psychologist targeted_actions = list("Reveal") @@ -354,7 +355,7 @@ . = ..() if(!.) return FALSE - if(game.phase != MAFIA_PHASE_NIGHT || target.game_status != MAFIA_ALIVE) + if(game.phase != MAFIA_PHASE_NIGHT || target.game_status != MAFIA_ALIVE || target == src) return FALSE /datum/mafia_role/traitor/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target) @@ -385,7 +386,7 @@ /datum/mafia_role/fugitive/New(datum/mafia_controller/game) . = ..() - RegisterSignal(game,COMSIG_MAFIA_NIGHT_START,.proc/night_start) + RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/night_start) RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/night_end) RegisterSignal(game,COMSIG_MAFIA_GAME_END,.proc/survived) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index a8f40388367..aa0a7b30c0d 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -905,6 +905,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!invisibility) . += "It seems extremely obvious." +/mob/dead/observer/examine_more(mob/user) + if(!IsAdminGhost(user, TRUE)) + return ..() + . = list("You examine [src] closer, and note the following...") + . += list("\t>[ADMIN_FULLMONTY(src)]") + /mob/dead/observer/proc/set_invisibility(value) invisibility = value if(!value) @@ -948,8 +954,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/list/t_ray_images = list() var/static/list/stored_t_ray_images = list() for(var/obj/O in orange(client.view, src) ) - - if(O.invisibility == INVISIBILITY_MAXIMUM) + 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/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index 137de92db86..6f1c9a1a63b 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -16,11 +16,10 @@ return if (action == "orbit") - var/list/pois = getpois(skip_mindless = 1) - var/atom/movable/poi = pois[params["name"]] + var/ref = params["ref"] + var/atom/movable/poi = (locate(ref) in GLOB.mob_list) || (locate(ref) in GLOB.poi_list) if (poi != null) owner.ManualFollow(poi) - ui.close() /datum/orbit_menu/ui_data(mob/user) var/list/data = list() @@ -39,6 +38,8 @@ var/poi = pois[name] + serialized["ref"] = REF(poi) + var/mob/M = poi if (istype(M)) if (isobserver(M)) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 20217535a0b..7c7dd7d4546 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -166,6 +166,10 @@ var/power_throw = 0 if(HAS_TRAIT(src, TRAIT_HULK)) power_throw++ + if(HAS_TRAIT(src, TRAIT_DWARF)) + power_throw-- + if(HAS_TRAIT(thrown_thing, TRAIT_DWARF)) + power_throw++ if(pulling && grab_state >= GRAB_NECK) power_throw++ visible_message("[src] throws [thrown_thing][power_throw ? " really hard!" : "."]", \ @@ -1184,3 +1188,6 @@ S.generate(BP, W) S.fake = TRUE QDEL_NULL(W) + +/mob/living/carbon/is_face_visible() + return !(wear_mask?.flags_inv & HIDEFACE) && !(head?.flags_inv & HIDEFACE) diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 79051d2207a..baaff3e1ea0 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -80,7 +80,7 @@ /mob/living/carbon/update_fire(var/fire_icon = "Generic_mob_burning") remove_overlay(FIRE_LAYER) - if(on_fire || islava(loc)) + if(on_fire || HAS_TRAIT(src, TRAIT_PERMANENTLY_ONFIRE)) var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/OnFire.dmi', fire_icon, -FIRE_LAYER) new_fire_overlay.appearance_flags = RESET_COLOR overlays_standing[FIRE_LAYER] = new_fire_overlay diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index 70e8dff4afe..c28fa0768e0 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -44,6 +44,7 @@ return if(H.dna.features["moth_wings"] != "Burnt Off" && H.bodytemperature >= 800 && H.fire_stacks > 0) //do not go into the extremely hot light. you will not survive to_chat(H, "Your precious wings burn to a crisp!") + H.dna.features["original_moth_wings"] = H.dna.features["moth_wings"] //Fire apparently destroys DNA, so let's preserve that elsewhere H.dna.features["moth_wings"] = "Burnt Off" if(flying_species) //This is all exclusive to if the person has the effects of a potion of flight if(H.movement_type & FLYING) @@ -71,3 +72,12 @@ var/datum/gas_mixture/current = H.loc.return_air() if(current && (current.return_pressure() >= ONE_ATMOSPHERE*0.85)) //as long as there's reasonable pressure and no gravity, flight is possible return TRUE + + +/datum/species/moth/spec_fully_heal(mob/living/carbon/human/H) + . = ..() + if(H.dna.features["original_moth_wings"] != null) + H.dna.features["moth_wings"] = H.dna.features["original_moth_wings"] + if(H.dna.features["original_moth_wings"] == null && H.dna.features["moth_wings"] == "Burnt Off") + H.dna.features["moth_wings"] = "Plain" + handle_mutant_bodyparts(H) diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index bf1d7138751..620da593bdd 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -34,14 +34,9 @@ bodytemp_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 50) // about -50c /datum/species/plasmaman/spec_life(mob/living/carbon/human/H) - var/datum/gas_mixture/environment = H.loc.return_air() - var/atmos_sealed = FALSE - if (H.wear_suit && H.head && istype(H.wear_suit, /obj/item/clothing) && istype(H.head, /obj/item/clothing)) - var/obj/item/clothing/CS = H.wear_suit - var/obj/item/clothing/CH = H.head - if (CS.clothing_flags & CH.clothing_flags & STOPSPRESSUREDAMAGE) - atmos_sealed = TRUE - if((!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman) || !istype(H.gloves, /obj/item/clothing/gloves)) && !atmos_sealed) + var/atmos_sealed = CanIgniteMob(H) && (isclothing(H.wear_suit) && H.wear_suit.clothing_flags & STOPSPRESSUREDAMAGE) && (isclothing(H.head) && H.head.clothing_flags & STOPSPRESSUREDAMAGE) + if(!atmos_sealed && (!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman) || !istype(H.gloves, /obj/item/clothing/gloves))) + var/datum/gas_mixture/environment = H.loc.return_air() if(environment) if(environment.total_moles()) if(environment.gases[/datum/gas/oxygen] && (environment.gases[/datum/gas/oxygen][MOLES]) >= 1) //Same threshhold that extinguishes fire @@ -50,14 +45,13 @@ H.visible_message("[H]'s body reacts with the atmosphere and bursts into flames!","Your body reacts with the atmosphere and bursts into flame!") H.IgniteMob() internal_fire = TRUE - else - if(H.fire_stacks) - var/obj/item/clothing/under/plasmaman/P = H.w_uniform - if(istype(P)) - P.Extinguish(H) - internal_fire = FALSE - else + else if(H.fire_stacks) + var/obj/item/clothing/under/plasmaman/P = H.w_uniform + if(istype(P)) + P.Extinguish(H) internal_fire = FALSE + else + internal_fire = FALSE H.update_fire() /datum/species/plasmaman/handle_fire(mob/living/carbon/human/H, no_protection) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index c16840bfb6c..81ef2e6f504 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -107,8 +107,6 @@ if(EFFECT_IRRADIATE) if(!HAS_TRAIT(src, TRAIT_RADIMMUNE)) radiation += max(effect * hit_percent, 0) - else - radiation = 0 if(EFFECT_SLUR) slurring = max(slurring,(effect * hit_percent)) if(EFFECT_STUTTER) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index ced35a2d27a..3449662684c 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1556,3 +1556,7 @@ switch(stat) //Current stat. if(UNCONSCIOUS) become_blind(UNCONSCIOUS_BLIND) + +/// Only defined for carbons who can wear masks and helmets, we just assume other mobs have visible faces +/mob/living/proc/is_face_visible() + return TRUE diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 124f7effca5..9146b85d6a9 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -172,7 +172,7 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) /datum/cameranet/proc/checkTurfVis(turf/position) - var/datum/camerachunk/chunk = chunkGenerated(position.x, position.y, position.z) + var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z) if(chunk) if(chunk.changed) chunk.hasChanged(1) // Update now, no matter if it's visible or not. diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 5dd9c0406ba..cf5ce1f77b6 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -256,7 +256,7 @@ S.robot_arm = robot_arm S.healthanalyzer = healthanalyzer var/obj/item/storage/firstaid/FA = firstaid - S.damagetype_healer = initial(FA.damagetype_healed) + S.damagetype_healer = initial(FA.damagetype_healed) ? initial(FA.damagetype_healed) : BRUTE qdel(src) diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index bccb26ae80f..65924d2bb2f 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -254,7 +254,7 @@ tipper_name = user.name /mob/living/simple_animal/bot/medbot/proc/set_right(mob/user) - mobility_flags &= MOBILITY_MOVE + mobility_flags |= MOBILITY_MOVE var/list/messagevoice if(user) diff --git a/code/modules/mob/living/simple_animal/eldritch_demons.dm b/code/modules/mob/living/simple_animal/eldritch_demons.dm index 2caee21d8af..bfec32b118c 100644 --- a/code/modules/mob/living/simple_animal/eldritch_demons.dm +++ b/code/modules/mob/living/simple_animal/eldritch_demons.dm @@ -16,7 +16,7 @@ speed = 0 a_intent = INTENT_HARM stop_automated_movement = 1 - AIStatus = AI_ON + AIStatus = AI_OFF attack_sound = 'sound/weapons/punch1.ogg' see_in_dark = 7 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE @@ -37,8 +37,6 @@ /mob/living/simple_animal/hostile/eldritch/Initialize() . = ..() add_spells() - //by default - mind.add_antag_datum(/datum/antagonist/heretic_monster) /** * Add_spells diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 88e221d6224..32039a58efb 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -20,7 +20,6 @@ maxHealth = 50000 health = 50000 healable = 0 - harm_intent_damage = 10 obj_damage = 100 melee_damage_lower = 68 @@ -109,6 +108,9 @@ if(!can_be_seen(get_turf(loc))) ..() +/mob/living/simple_animals/hostile/statue/IsVocal() //we're a statue, of course we can't talk. + return FALSE + /mob/living/simple_animal/hostile/statue/proc/can_be_seen(turf/destination) if(!cannot_be_seen) return null diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 67fc37b90db..402f8b0b97e 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -991,6 +991,6 @@ var/datum/disease/parrot_possession/P = new P.parrot = src forceMove(H) - H.ForceContractDisease(P) + H.ForceContractDisease(P, FALSE) parrot_interest = null H.visible_message("[src] dive bombs into [H]'s chest and vanishes!", "[src] dive bombs into your chest, vanishing! This can't be good!") diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 35c5c004687..fa4db80b54d 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -419,10 +419,12 @@ var/list/result if(client) LAZYINITLIST(client.recent_examines) - if(isnull(client.recent_examines[A]) || client.recent_examines[A] < world.time) // originally this wasn't an assoc list, but sometimes the timer failed and atoms stayed in a client's recent_examines, so we check here manually - client.recent_examines[A] = world.time + EXAMINE_MORE_TIME + if(isnull(client.recent_examines[A]) || client.recent_examines[A] < world.time) result = A.examine(src) + client.recent_examines[A] = world.time + EXAMINE_MORE_TIME // set the value to when the examine cooldown ends + RegisterSignal(A, COMSIG_PARENT_QDELETING, .proc/clear_from_recent_examines, override=TRUE) // to flush the value if deleted early addtimer(CALLBACK(src, .proc/clear_from_recent_examines, A), EXAMINE_MORE_TIME) + handle_eye_contact(A) else result = A.examine_more(src) else @@ -432,10 +434,37 @@ SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A) /mob/proc/clear_from_recent_examines(atom/A) - if(QDELETED(A) || !client) + if(!client) return + UnregisterSignal(A, COMSIG_PARENT_QDELETING) LAZYREMOVE(client.recent_examines, A) +/** + * handle_eye_contact() is called when we examine() something. If we examine an alive mob with a mind who has examined us in the last second within 5 tiles, we make eye contact! + * + * Note that if either party has their face obscured, the other won't get the notice about the eye contact + * Also note that examine_more() doesn't proc this or extend the timer, just because it's simpler this way and doesn't lose much. + * The nice part about relying on examining is that we don't bother checking visibility, because we already know they were both visible to each other within the last second, and the one who triggers it is currently seeing them + */ +/mob/proc/handle_eye_contact(mob/living/examined_mob) + return + +/mob/living/handle_eye_contact(mob/living/examined_mob) + if(!istype(examined_mob) || src == examined_mob || examined_mob.stat >= UNCONSCIOUS || !client || !examined_mob.client?.recent_examines || !(src in examined_mob.client.recent_examines)) + return + + if(get_dist(src, examined_mob) > EYE_CONTACT_RANGE) + return + + // check to see if their face is blocked or, if not, a signal blocks it + if(examined_mob.is_face_visible() && SEND_SIGNAL(src, COMSIG_MOB_EYECONTACT, examined_mob, TRUE) != COMSIG_BLOCK_EYECONTACT) + var/msg = "You make eye contact with [examined_mob]." + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, src, msg), 3) // so the examine signal has time to fire and this will print after + + if(is_face_visible() && SEND_SIGNAL(examined_mob, COMSIG_MOB_EYECONTACT, src, FALSE) != COMSIG_BLOCK_EYECONTACT) + var/msg = "[src] makes eye contact with you." + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, examined_mob, msg), 3) + /** * Point at an atom * diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index de999177cbd..8879f54ae20 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -421,7 +421,7 @@ to_chat(user, "[affecting] is already in good condition!") ///Is the passed in mob an admin ghost -/proc/IsAdminGhost(var/mob/user) +/proc/IsAdminGhost(var/mob/user, ignore_AI_interact) if(!user) //Are they a mob? Auto interface updates call this with a null src return if(!user.client) // Do they have a client? @@ -430,7 +430,7 @@ return if(!check_rights_for(user.client, R_ADMIN)) // Are they allowed? return - if(!user.client.AI_Interact) // Do they have it enabled? + if(!ignore_AI_interact && !user.client.AI_Interact) // Do they have it enabled? return return TRUE diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 51df052f895..d53e9aab03a 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -222,6 +222,7 @@ /obj/item/paper/examine_more(mob/user) ui_interact(user) + return list("You try to read [src]...") /obj/item/paper/can_interact(mob/user) diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index bce6e914faa..26a50fa50a3 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -202,14 +202,11 @@ var/psize_x = (size_x * 2 + 1) * world.icon_size var/psize_y = (size_y * 2 + 1) * world.icon_size - var/get_icon = camera_get_icon(turfs, target_turf, psize_x, psize_y, clone_area, size_x, size_y, (size_x * 2 + 1), (size_y * 2 + 1)) + var/icon/get_icon = camera_get_icon(turfs, target_turf, psize_x, psize_y, clone_area, size_x, size_y, (size_x * 2 + 1), (size_y * 2 + 1)) qdel(clone_area) - var/icon/temp = icon('icons/effects/96x96.dmi',"") - temp.Blend("#000", ICON_OVERLAY) - temp.Scale(psize_x, psize_y) - temp.Blend(get_icon, ICON_OVERLAY) + get_icon.Blend("#000", ICON_UNDERLAY) - var/datum/picture/P = new("picture", desc.Join(" "), mobs_spotted, dead_spotted, temp, null, psize_x, psize_y, blueprints) + var/datum/picture/P = new("picture", desc.Join(" "), mobs_spotted, dead_spotted, get_icon, null, psize_x, psize_y, blueprints) after_picture(user, P, flag) blending = FALSE diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm index fa12cc20a7d..f74a2fc683d 100644 --- a/code/modules/photography/camera/camera_image_capturing.dm +++ b/code/modules/photography/camera/camera_image_capturing.dm @@ -51,7 +51,7 @@ atoms += A CHECK_TICK - var/icon/res = icon('icons/effects/96x96.dmi', "transparent") + var/icon/res = icon('icons/blanks/96x96.dmi', "nothing") res.Scale(psize_x, psize_y) var/list/sorted = list() @@ -60,7 +60,7 @@ var/atom/c = atoms[i] for(j = sorted.len, j > 0, --j) var/atom/c2 = sorted[j] - if(c2.layer <= c.layer) + if((c2.plane <= c.plane) && (c2.layer <= c.layer)) break sorted.Insert(j+1, c) CHECK_TICK @@ -76,7 +76,7 @@ var/atom/movable/AM = A xo += AM.step_x yo += AM.step_y - var/icon/img = getFlatIcon(A) + var/icon/img = getFlatIcon(A, no_anim = TRUE) res.Blend(img, blendMode2iconMode(A.blend_mode), xo, yo) CHECK_TICK else @@ -86,7 +86,7 @@ var/yo = (clone.y - center.y) * world.icon_size + clone.pixel_y + ycomp xo += clone.step_x yo += clone.step_y - var/icon/img = getFlatIcon(clone) + var/icon/img = getFlatIcon(clone, no_anim = TRUE) if(img) if(clone.turn_angle) //the cheapest (so best, considering cams don't need to be laggier) way of doing this, considering getFlatIcon doesn't give a snot about transforms.' img.Turn(clone.turn_angle) diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index bcd9fc00956..846b5866357 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -59,6 +59,10 @@ field_generator power level display fields = list() connected_gens = list() +/obj/machinery/field/generator/anchored/Initialize() + . = ..() + setAnchored(TRUE) + /obj/machinery/field/generator/ComponentInitialize() . = ..() AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) @@ -84,6 +88,12 @@ field_generator power level display else to_chat(user, "[src] needs to be firmly secured to the floor first!") +/obj/machinery/field/generator/setAnchored(anchorvalue) + . = ..() + if(active) + turn_off() + state = anchorvalue ? FG_SECURED : FG_UNSECURED + /obj/machinery/field/generator/can_be_unfasten_wrench(mob/user, silent) if(active) if(!silent) @@ -97,14 +107,6 @@ field_generator power level display return ..() -/obj/machinery/field/generator/default_unfasten_wrench(mob/user, obj/item/I, time = 20) - . = ..() - if(. == SUCCESSFUL_UNFASTEN) - if(anchored) - state = FG_SECURED - else - state = FG_UNSECURED - /obj/machinery/field/generator/wrench_act(mob/living/user, obj/item/I) ..() default_unfasten_wrench(user, I) @@ -145,8 +147,7 @@ field_generator power level display /obj/machinery/field/generator/attack_animal(mob/living/simple_animal/M) if(M.environment_smash & ENVIRONMENT_SMASH_RWALLS && active == FG_OFFLINE && state != FG_UNSECURED) - state = FG_UNSECURED - anchored = FALSE + setAnchored(FALSE) M.visible_message("[M] rips [src] free from its moorings!") else ..() diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index ab6b0c021bb..1a1ce943177 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -712,7 +712,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(zap_count >= 1) playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10) for(var/i in 1 to zap_count) - supermatter_zap(src, range, clamp(power*2, 4000, 20000), list(), flags) + supermatter_zap(src, range, clamp(power*2, 4000, 20000), flags) if(prob(5)) supermatter_anomaly_gen(src, FLUX_ANOMALY, rand(5, 10)) @@ -1038,7 +1038,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(PYRO_ANOMALY) new /obj/effect/anomaly/pyro(L, 200) -/obj/machinery/power/supermatter_crystal/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 4000, list/targets_hit = list(), zap_flags = ZAP_SUPERMATTER_FLAGS) +/obj/machinery/power/supermatter_crystal/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 4000, zap_flags = ZAP_SUPERMATTER_FLAGS, list/targets_hit = list()) if(QDELETED(zapstart)) return . = zapstart.dir @@ -1177,7 +1177,9 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) zap_str -= (zap_str/10) zap_count += 1 for(var/j in 1 to zap_count) - supermatter_zap(target, new_range, zap_str, targets_hit, zap_flags) + if(zap_count > 1) + targets_hit = targets_hit.Copy() //Pass by ref begone + supermatter_zap(target, new_range, zap_str, zap_flags, targets_hit) /obj/overlay/psy icon = 'icons/obj/supermatter.dmi' diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index df9ed8dce5b..9b0305acf9e 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -180,7 +180,7 @@ var/mob/living/carbon/C = A C.dust() -/proc/tesla_zap(atom/source, zap_range = 3, power, zap_flags = ZAP_DEFAULT_FLAGS, list/shocked_targets) +/proc/tesla_zap(atom/source, zap_range = 3, power, zap_flags = ZAP_DEFAULT_FLAGS, list/shocked_targets = list()) if(QDELETED(source)) return . = source.dir @@ -330,8 +330,8 @@ else power = closest_atom.zap_act(power, zap_flags, shocked_targets) if(prob(20))//I know I know - tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets) - tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets) + tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets.Copy())//No pass by ref, it's a bad play + tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets.Copy()) else tesla_zap(closest_atom, next_range, power, zap_flags, shocked_targets) diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 35745899543..635071818f0 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -253,7 +253,7 @@ if (chambered && !chambered.BB) chambered.forceMove(drop_location()) chambered = null - var/num_loaded = magazine.attackby(A, user, params, TRUE) + var/num_loaded = magazine?.attackby(A, user, params, TRUE) if (num_loaded) to_chat(user, "You load [num_loaded] [cartridge_wording]\s into \the [src].") playsound(src, load_sound, load_sound_volume, load_sound_vary) @@ -410,7 +410,8 @@ rounds.Add(chambered) if(drop_all) chambered = null - rounds.Add(magazine.ammo_list(drop_all)) + if(magazine) + rounds.Add(magazine.ammo_list(drop_all)) return rounds #define BRAINS_BLOWN_THROW_RANGE 3 diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 80902b037b8..6defdc6659c 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -17,6 +17,8 @@ var/recent_spin = 0 /obj/item/gun/ballistic/revolver/chamber_round(spin_cylinder = TRUE) + if(!magazine) //if it mag was qdel'd somehow. + CRASH("revolver tried to chamber a round without a magazine!") if(spin_cylinder) chambered = magazine.get_round(TRUE) else @@ -91,14 +93,14 @@ ) /obj/item/gun/ballistic/revolver/detective/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) - if(magazine.caliber != initial(magazine.caliber)) + if(magazine && magazine.caliber != initial(magazine.caliber)) if(prob(70 - (magazine.ammo_count() * 10))) //minimum probability of 10, maximum of 60 playsound(user, fire_sound, fire_sound_volume, vary_fire_sound) to_chat(user, "[src] blows up in your face!") user.take_bodypart_damage(0,20) user.dropItemToGround(src) - return 0 - ..() + return FALSE + return ..() /obj/item/gun/ballistic/revolver/detective/screwdriver_act(mob/living/user, obj/item/I) if(..()) diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index d7e70c7c953..c3012d16251 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -25,7 +25,6 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) /obj/machinery/conveyor/centcom_auto id = "round_end_belt" - /obj/machinery/conveyor/inverted //Directions inverted so you can use different corner peices. icon_state = "conveyor_map_inverted" verted = -1 @@ -37,10 +36,12 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) // Auto conveyour is always on unless unpowered +/obj/machinery/conveyor/auto + processing_flags = START_PROCESSING_ON_INIT + /obj/machinery/conveyor/auto/Initialize(mapload, newdir) - . = ..() operating = TRUE - update_move_direction() + return ..() /obj/machinery/conveyor/auto/update() . = ..() @@ -250,9 +251,11 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) id = newid update_icon() LAZYADD(GLOB.conveyors_by_id[id], src) + wires = new /datum/wires/conveyor(src) /obj/machinery/conveyor_switch/Destroy() LAZYREMOVE(GLOB.conveyors_by_id[id], src) + QDEL_NULL(wires) . = ..() /obj/machinery/conveyor_switch/vv_edit_var(var_name, var_value) @@ -332,6 +335,9 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) transfer_fingerprints_to(C) to_chat(user, "You detach the conveyor switch.") qdel(src) + if(is_wire_tool(I)) + wires.interact(user) + return TRUE /obj/machinery/conveyor_switch/oneway icon_state = "conveyor_switch_oneway" diff --git a/code/modules/recycling/disposal/outlet.dm b/code/modules/recycling/disposal/outlet.dm index aa516b91fab..581c6f60679 100644 --- a/code/modules/recycling/disposal/outlet.dm +++ b/code/modules/recycling/disposal/outlet.dm @@ -13,6 +13,8 @@ var/obj/structure/disposalconstruct/stored var/start_eject = 0 var/eject_range = 2 + /// how fast we're spitting fir- atoms + var/eject_speed = EJECT_SPEED_MED /obj/structure/disposaloutlet/Initialize(mapload, obj/structure/disposalconstruct/make_from) . = ..() @@ -61,7 +63,7 @@ var/atom/movable/AM = A AM.forceMove(T) AM.pipe_eject(dir) - AM.throw_at(target, eject_range, 1) + AM.throw_at(target, eject_range, eject_speed) H.vent_gas(T) qdel(H) @@ -80,3 +82,39 @@ stored = null qdel(src) return TRUE + +/obj/structure/disposaloutlet/examine(mob/user) + . = ..() + switch(eject_speed) + if(EJECT_SPEED_SLOW) + . += "An LED image of a turtle is displayed on the side of the outlet." + if(EJECT_SPEED_MED) + . += "An LED image of a bumblebee is displayed on the side of the outlet." + if(EJECT_SPEED_FAST) + . += "An LED image of a speeding bullet is displayed on the side of the outlet." + if(EJECT_SPEED_YEET) + . += "An LED image of a grawlix is displayed on the side of the outlet." + +/obj/structure/disposaloutlet/multitool_act(mob/living/user, obj/item/I) + . = ..() + to_chat(user, "You adjust the ejection force on \the [src].") + switch(eject_speed) + if(EJECT_SPEED_SLOW) + eject_speed = EJECT_SPEED_MED + if(EJECT_SPEED_MED) + eject_speed = EJECT_SPEED_FAST + if(EJECT_SPEED_FAST) + if(obj_flags & EMAGGED) + eject_speed = EJECT_SPEED_YEET + else + eject_speed = EJECT_SPEED_SLOW + if(EJECT_SPEED_YEET) + eject_speed = EJECT_SPEED_SLOW + return TRUE + +/obj/structure/disposaloutlet/emag_act(mob/user, obj/item/card/emag/E) + . = ..() + if(obj_flags & EMAGGED) + return + to_chat(user, "You silently disable the sanity checking on \the [src]'s ejection force.") + obj_flags |= EMAGGED diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 1d231ab532c..e882ccba3bf 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -605,6 +605,32 @@ materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/silver = 500) build_path = /obj/item/organ/lungs/cybernetic/tier3 +/datum/design/cybernetic_stomach + name = "Basic Cybernetic Stomach" + desc = "A basic cybernetic stomach." + id = "cybernetic_stomach" + build_type = PROTOLATHE | MECHFAB + construction_time = 40 + materials = list(/datum/material/iron = 500, /datum/material/glass = 500) + build_path = /obj/item/organ/stomach/cybernetic + category = list("Misc", "Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + +/datum/design/cybernetic_stomach/tier2 + name = "Cybernetic Stomach" + desc = "A cybernetic stomach." + id = "cybernetic_stomach_tier2" + materials = list(/datum/material/iron = 500, /datum/material/glass = 500) + build_path = /obj/item/organ/stomach/cybernetic/tier2 + +/datum/design/cybernetic_stomach/tier3 + name = "Upgraded Cybernetic Stomach" + desc = "An upgraded cybernetic stomach." + id = "cybernetic_stomach_tier3" + construction_time = 50 + materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/silver = 500) + build_path = /obj/item/organ/stomach/cybernetic/tier3 + /datum/design/cybernetic_ears name = "Cybernetic Ears" desc = "A pair of cybernetic ears." @@ -774,3 +800,10 @@ id = "surgery_zombie" surgery = /datum/surgery/advanced/necrotic_revival research_icon_state = "surgery_head" + +/datum/design/surgery/wing_reconstruction + name = "Wing Reconstruction" + desc = "An experimental surgical procedure that reconstructs the damaged wings of moth people. Requires Instabitaluri." + id = "surgery_wing_reconstruction" + surgery = /datum/surgery/advanced/wing_reconstruction + research_icon_state = "surgery_chest" diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index c17e8a31fb8..533b657cde5 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -60,13 +60,22 @@ Note: Must be placed within 3 tiles of the R&D Console /obj/machinery/rnd/destructive_analyzer/proc/reclaim_materials_from(obj/item/thing) . = 0 var/datum/component/material_container/storage = linked_console?.linked_lathe?.materials.mat_container - if(storage) //Also sends salvaged materials to a linked protolathe, if any. - for(var/material in thing.custom_materials) - var/can_insert = min((storage.max_amount - storage.total_amount), (min(thing.custom_materials[material]*(decon_mod/10), thing.custom_materials[material]))) - storage.insert_amount_mat(can_insert, material) - . += can_insert - if (.) - linked_console.linked_lathe.materials.silo_log(src, "reclaimed", 1, "[thing.name]", thing.custom_materials) + if(!storage) // If we have no storage drop out + return + // sends salvaged materials to a linked protolathe, if any. + for(var/material in thing.custom_materials) + var/can_insert = 0 // the amount of material to insert + if(istype(thing, /obj/item/stack/sheet)) + var/obj/item/stack/sheet/stack = thing + if(stack.mats_per_unit) + can_insert += stack.mats_per_unit[material] + can_insert = min((storage.max_amount - storage.total_amount), (min(can_insert*(decon_mod/10), can_insert))) + else + can_insert = min((storage.max_amount - storage.total_amount), (min(thing.custom_materials[material]*(decon_mod/10), thing.custom_materials[material]))) + storage.insert_amount_mat(can_insert, material) + . += can_insert + if (.) + linked_console.linked_lathe.materials.silo_log(src, "reclaimed", 1, "[thing.name]", thing.custom_materials) /obj/machinery/rnd/destructive_analyzer/proc/destroy_item(obj/item/thing, innermode = FALSE) if(QDELETED(thing) || QDELETED(src) || QDELETED(linked_console)) @@ -87,12 +96,14 @@ Note: Must be placed within 3 tiles of the R&D Console if(istype(thing, /obj/item/stack/sheet)) var/obj/item/stack/sheet/S = thing if(S.amount > 1 && !innermode) - S.amount-- + S.use(1, check=FALSE) loaded_item = S else - qdel(S) + qdel(thing) + loaded_item = null else qdel(thing) + loaded_item = null if (!innermode) update_icon() return TRUE @@ -143,6 +154,7 @@ Note: Must be placed within 3 tiles of the R&D Console if(destroy_item(loaded_item)) linked_console.stored_research.add_point_list(point_value) linked_console.stored_research.deconstructed_items[loaded_type] = point_value + return TRUE /obj/machinery/rnd/destructive_analyzer/proc/unload_item() diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 39727e86de0..78a55e9d34a 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -56,7 +56,7 @@ starting_node = TRUE display_name = "Basic Medical Equipment" description = "Basic medical tools and equipment." - design_ids = list("cybernetic_liver", "cybernetic_heart", "cybernetic_lungs", "scalpel", "circular_saw", "bonesetter", "surgicaldrill", "retractor", "cautery", "hemostat", + design_ids = list("cybernetic_liver", "cybernetic_heart", "cybernetic_lungs","cybernetic_stomach", "scalpel", "circular_saw", "bonesetter", "surgicaldrill", "retractor", "cautery", "hemostat", "surgical_drapes", "syringe", "plumbing_rcd", "beaker", "large_beaker", "xlarge_beaker", "dropper", "defibmountdefault", "surgical_tape", "portable_chem_mixer") /////////////////////////Biotech///////////////////////// @@ -103,7 +103,7 @@ display_name = "Advanced Surgery" description = "When simple medicine doesn't cut it." prereq_ids = list("imp_wt_surgery") - design_ids = list("surgery_lobotomy", "surgery_heal_brute_upgrade_femto", "surgery_heal_burn_upgrade_femto","surgery_heal_combo") + design_ids = list("surgery_lobotomy", "surgery_heal_brute_upgrade_femto", "surgery_heal_burn_upgrade_femto","surgery_heal_combo","surgery_wing_reconstruction") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) export_price = 4000 @@ -481,7 +481,7 @@ display_name = "Cybernetic Organs" description = "We have the technology to rebuild him." prereq_ids = list("biotech") - design_ids = list("cybernetic_ears", "cybernetic_heart_tier2", "cybernetic_liver_tier2", "cybernetic_lungs_tier2") + design_ids = list("cybernetic_ears", "cybernetic_heart_tier2", "cybernetic_liver_tier2", "cybernetic_lungs_tier2", "cybernetic_stomach_tier2") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) export_price = 5000 @@ -490,7 +490,7 @@ display_name = "Upgraded Cybernetic Organs" description = "We have the technology to upgrade him." prereq_ids = list("adv_biotech", "cyber_organs") - design_ids = list("cybernetic_ears_u", "cybernetic_heart_tier3", "cybernetic_liver_tier3", "cybernetic_lungs_tier3") + design_ids = list("cybernetic_ears_u", "cybernetic_heart_tier3", "cybernetic_liver_tier3", "cybernetic_lungs_tier3", "cybernetic_stomach_tier3") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) export_price = 5000 diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 9ff6da7d7f1..144f38ec681 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -181,14 +181,15 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th to_chat(user, "[name] cannot be cast unless you are completely manifested in the material plane!") return FALSE + var/mob/living/L = user + if(istype(L) && (invocation_type == INVOCATION_WHISPER || invocation_type == INVOCATION_SHOUT) && !L.can_speak_vocal()) + to_chat(user, "You can't get the words out!") + return FALSE + if(ishuman(user)) var/mob/living/carbon/human/H = user - if((invocation_type == "whisper" || invocation_type == "shout") && !H.can_speak_vocal()) - to_chat(user, "You can't get the words out!") - return FALSE - var/list/casting_clothes = typecacheof(list(/obj/item/clothing/suit/wizrobe, /obj/item/clothing/suit/space/hardsuit/wizard, /obj/item/clothing/head/wizard, @@ -247,17 +248,17 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th /obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount switch(invocation_type) - if("shout") + if(INVOCATION_SHOUT) if(prob(50))//Auto-mute? Fuck that noise user.say(invocation, forced = "spell") else user.say(replacetext(invocation," ","`"), forced = "spell") - if("whisper") + if(INVOCATION_WHISPER) if(prob(50)) user.whisper(invocation) else user.whisper(replacetext(invocation," ","`")) - if("emote") + if(INVOCATION_EMOTE) user.visible_message(invocation, invocation_emote_self) //same style as in mob/living/emote.dm /obj/effect/proc_holder/spell/proc/playMagSound() @@ -557,7 +558,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th charge_max = 100 cooldown_min = 50 invocation = "Victus sano!" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER school = "restoration" sound = 'sound/magic/staff_healing.ogg' diff --git a/code/modules/spells/spell_types/aimed.dm b/code/modules/spells/spell_types/aimed.dm index f96e598aaa6..1c011d361e8 100644 --- a/code/modules/spells/spell_types/aimed.dm +++ b/code/modules/spells/spell_types/aimed.dm @@ -95,7 +95,7 @@ charge_max = 100 clothes_req = FALSE invocation = "P'WAH, UNLIM'TED P'WAH" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT cooldown_min = 20 base_icon_state = "lightning" action_icon_state = "lightning0" @@ -113,7 +113,7 @@ charge_max = 60 clothes_req = FALSE invocation = "ONI SOMA" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 20 cooldown_min = 20 //10 deciseconds reduction per rank projectile_type = /obj/projectile/magic/aoe/fireball @@ -136,7 +136,7 @@ charge_max = 50 clothes_req = FALSE invocation = "Sigi'lu M'Fan 'Tasia" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 40 cooldown_min = 10 projectile_amount = 5 diff --git a/code/modules/spells/spell_types/area_teleport.dm b/code/modules/spells/spell_types/area_teleport.dm index abbfd1856cf..1e02cd52b13 100644 --- a/code/modules/spells/spell_types/area_teleport.dm +++ b/code/modules/spells/spell_types/area_teleport.dm @@ -82,8 +82,8 @@ words = "[invocation]" switch(invocation_type) - if("shout") + if(INVOCATION_SHOUT) user.say(words, forced = "spell") playsound(user.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, TRUE) - if("whisper") + if(INVOCATION_WHISPER) user.whisper(words, forced = "spell") diff --git a/code/modules/spells/spell_types/charge.dm b/code/modules/spells/spell_types/charge.dm index 62e8543393d..694b34153db 100644 --- a/code/modules/spells/spell_types/charge.dm +++ b/code/modules/spells/spell_types/charge.dm @@ -6,7 +6,7 @@ charge_max = 600 clothes_req = FALSE invocation = "DIRI CEL" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER range = -1 cooldown_min = 400 //50 deciseconds reduction per rank include_user = TRUE diff --git a/code/modules/spells/spell_types/devil.dm b/code/modules/spells/spell_types/devil.dm index 6f554135870..eaa8eae9731 100644 --- a/code/modules/spells/spell_types/devil.dm +++ b/code/modules/spells/spell_types/devil.dm @@ -23,7 +23,7 @@ /obj/effect/proc_holder/spell/targeted/conjure_item/violin item_type = /obj/item/instrument/violin/golden desc = "A devil's instrument of choice. Use this to summon/unsummon your golden violin." - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER invocation = "I ain't had this much fun since Georgia." action_icon_state = "golden_violin" name = "Summon golden violin" @@ -33,7 +33,7 @@ /obj/effect/proc_holder/spell/targeted/summon_contract name = "Summon infernal contract" desc = "Skip making a contract by hand, just do it by magic." - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER invocation = "Just sign on the dotted line." include_user = FALSE range = 5 @@ -81,7 +81,7 @@ charge_max = 80 clothes_req = FALSE invocation = "Your very soul will catch fire!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 2 projectile_type = /obj/projectile/magic/aoe/fireball/infernal @@ -181,7 +181,7 @@ random_target_priority = TARGET_RANDOM max_targets = 3 invocation = "TASTE SIN AND INDULGE!!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT /obj/effect/proc_holder/spell/targeted/sintouch/ascended name = "Greater sin touch" diff --git a/code/modules/spells/spell_types/forcewall.dm b/code/modules/spells/spell_types/forcewall.dm index 3c3fcc320a2..64eca54e3d7 100644 --- a/code/modules/spells/spell_types/forcewall.dm +++ b/code/modules/spells/spell_types/forcewall.dm @@ -5,7 +5,7 @@ charge_max = 100 clothes_req = FALSE invocation = "TARCOL MINTI ZHERI" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT sound = 'sound/magic/forcewall.ogg' action_icon_state = "shield" range = -1 diff --git a/code/modules/spells/spell_types/knock.dm b/code/modules/spells/spell_types/knock.dm index 3e75989308d..d31a587eaa8 100644 --- a/code/modules/spells/spell_types/knock.dm +++ b/code/modules/spells/spell_types/knock.dm @@ -6,7 +6,7 @@ charge_max = 100 clothes_req = FALSE invocation = "AULIE OXIN FIERA" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER range = 3 cooldown_min = 20 //20 deciseconds reduction per rank diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm index 1845fdfadf4..8aee4d8809c 100644 --- a/code/modules/spells/spell_types/lichdom.dm +++ b/code/modules/spells/spell_types/lichdom.dm @@ -11,7 +11,7 @@ clothes_req = FALSE centcom_cancast = FALSE invocation = "NECREM IMORTIUM!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = -1 level_max = 0 //cannot be improved cooldown_min = 10 diff --git a/code/modules/spells/spell_types/lightning.dm b/code/modules/spells/spell_types/lightning.dm index f5b015b9040..3231d22170e 100644 --- a/code/modules/spells/spell_types/lightning.dm +++ b/code/modules/spells/spell_types/lightning.dm @@ -5,7 +5,7 @@ charge_max = 300 clothes_req = TRUE invocation = "UN'LTD P'WAH!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 7 cooldown_min = 30 selection_type = "view" diff --git a/code/modules/spells/spell_types/mime.dm b/code/modules/spells/spell_types/mime.dm index e64867f2556..d4595016a72 100644 --- a/code/modules/spells/spell_types/mime.dm +++ b/code/modules/spells/spell_types/mime.dm @@ -4,7 +4,7 @@ school = "mime" panel = "Mime" summon_type = list(/obj/effect/forcefield/mime) - invocation_type = "emote" + invocation_type = INVOCATION_EMOTE invocation_emote_self = "You form a wall in front of yourself." summon_lifespan = 300 charge_max = 300 @@ -34,7 +34,7 @@ school = "mime" panel = "Mime" summon_type = list(/obj/structure/chair/mime) - invocation_type = "emote" + invocation_type = INVOCATION_EMOTE invocation_emote_self = "You conjure an invisible chair and sit down." summon_lifespan = 250 charge_max = 300 @@ -72,7 +72,7 @@ school = "mime" panel = "Mime" summon_type = list(/obj/item/storage/box/mime) - invocation_type = "emote" + invocation_type = INVOCATION_EMOTE invocation_emote_self = "You conjure up an invisible box, large enough to store a few things." summon_lifespan = 500 charge_max = 300 @@ -151,7 +151,7 @@ school = "mime" panel = "Mime" wall_type = /obj/effect/forcefield/mime/advanced - invocation_type = "emote" + invocation_type = INVOCATION_EMOTE invocation_emote_self = "You form a blockade in front of yourself." charge_max = 600 sound = null @@ -182,7 +182,7 @@ charge_max = 300 clothes_req = FALSE antimagic_allowed = TRUE - invocation_type = "emote" + invocation_type = INVOCATION_EMOTE invocation_emote_self = "You fire your finger gun!" range = 20 projectile_type = /obj/projectile/bullet/mime diff --git a/code/modules/spells/spell_types/pointed/barnyard.dm b/code/modules/spells/spell_types/pointed/barnyard.dm index 61e3cf71278..4753f7b4182 100644 --- a/code/modules/spells/spell_types/pointed/barnyard.dm +++ b/code/modules/spells/spell_types/pointed/barnyard.dm @@ -8,7 +8,7 @@ clothes_req = FALSE stat_allowed = FALSE invocation = "KN'A FTAGHU, PUCK 'BTHNK!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 7 cooldown_min = 30 ranged_mousepointer = 'icons/effects/mouse_pointers/barn_target.dmi' diff --git a/code/modules/spells/spell_types/pointed/blind.dm b/code/modules/spells/spell_types/pointed/blind.dm index a773c5ad8d8..5051a6516b0 100644 --- a/code/modules/spells/spell_types/pointed/blind.dm +++ b/code/modules/spells/spell_types/pointed/blind.dm @@ -5,7 +5,7 @@ charge_max = 300 clothes_req = FALSE invocation = "STI KALY" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER message = "Your eyes cry out in pain!" cooldown_min = 50 //12 deciseconds reduction per rank starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind", "/obj/effect/proc_holder/spell/targeted/genetic/blind") diff --git a/code/modules/spells/spell_types/pointed/mind_transfer.dm b/code/modules/spells/spell_types/pointed/mind_transfer.dm index b3819dd7dbc..d08c1ab2a17 100644 --- a/code/modules/spells/spell_types/pointed/mind_transfer.dm +++ b/code/modules/spells/spell_types/pointed/mind_transfer.dm @@ -5,7 +5,7 @@ charge_max = 600 clothes_req = FALSE invocation = "GIN'YU CAPAN" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER range = 1 cooldown_min = 200 //100 deciseconds reduction per rank ranged_mousepointer = 'icons/effects/mouse_pointers/mindswap_target.dmi' diff --git a/code/modules/spells/spell_types/rod_form.dm b/code/modules/spells/spell_types/rod_form.dm index 5debe7341c6..a3d5dbc6cc7 100644 --- a/code/modules/spells/spell_types/rod_form.dm +++ b/code/modules/spells/spell_types/rod_form.dm @@ -8,7 +8,7 @@ range = -1 include_user = TRUE invocation = "CLANG!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT action_icon_state = "immrod" /obj/effect/proc_holder/spell/targeted/rod_form/cast(list/targets,mob/user = usr) diff --git a/code/modules/spells/spell_types/santa.dm b/code/modules/spells/spell_types/santa.dm index e807f863ba9..350206eaf73 100644 --- a/code/modules/spells/spell_types/santa.dm +++ b/code/modules/spells/spell_types/santa.dm @@ -7,7 +7,7 @@ clothes_req = FALSE antimagic_allowed = TRUE invocation = "HO HO HO" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 3 cooldown_min = 50 diff --git a/code/modules/spells/spell_types/shapeshift.dm b/code/modules/spells/spell_types/shapeshift.dm index 658e78353e8..bae56ff2a1f 100644 --- a/code/modules/spells/spell_types/shapeshift.dm +++ b/code/modules/spells/spell_types/shapeshift.dm @@ -8,7 +8,7 @@ range = -1 include_user = TRUE invocation = "RAC'WA NO!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT action_icon_state = "shapeshift" var/revert_on_death = TRUE diff --git a/code/modules/spells/spell_types/soultap.dm b/code/modules/spells/spell_types/soultap.dm index c152c89f8c0..9dafa04193a 100644 --- a/code/modules/spells/spell_types/soultap.dm +++ b/code/modules/spells/spell_types/soultap.dm @@ -10,7 +10,7 @@ school = "necromancy" //i could see why this wouldn't be necromancy but messing with souls or whatever. ectomancy? charge_max = 10 invocation = "AT ANY COST!" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT level_max = 0 cooldown_min = 10 diff --git a/code/modules/spells/spell_types/summonitem.dm b/code/modules/spells/spell_types/summonitem.dm index 9132436b283..8636211941c 100644 --- a/code/modules/spells/spell_types/summonitem.dm +++ b/code/modules/spells/spell_types/summonitem.dm @@ -5,7 +5,7 @@ charge_max = 100 clothes_req = FALSE invocation = "GAR YOK" - invocation_type = "whisper" + invocation_type = INVOCATION_WHISPER range = -1 level_max = 0 //cannot be improved cooldown_min = 100 diff --git a/code/modules/spells/spell_types/the_traps.dm b/code/modules/spells/spell_types/the_traps.dm index cc270764fa5..6fb86100ab0 100644 --- a/code/modules/spells/spell_types/the_traps.dm +++ b/code/modules/spells/spell_types/the_traps.dm @@ -7,7 +7,7 @@ clothes_req = TRUE invocation = "CAVERE INSIDIAS" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 3 summon_type = list( diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index 5453678d299..e923ef0c778 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -6,7 +6,7 @@ charge_max = 200 clothes_req = TRUE invocation = "FORTI GY AMA" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 7 cooldown_min = 60 //35 deciseconds reduction per rank max_targets = 0 @@ -45,7 +45,7 @@ charge_max = 400 clothes_req = TRUE invocation = "BIRUZ BENNAR" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = -1 include_user = TRUE @@ -99,7 +99,7 @@ charge_max = 400 clothes_req = TRUE invocation = "NEC CANTIO" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = -1 include_user = TRUE cooldown_min = 200 //50 deciseconds reduction per rank @@ -146,7 +146,7 @@ charge_max = 600 clothes_req = TRUE invocation = "SCYAR NILA" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = -1 include_user = TRUE cooldown_min = 200 //100 deciseconds reduction per rank @@ -170,7 +170,7 @@ charge_max = 500 clothes_req = TRUE invocation = "TOKI YO TOMARE" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 0 cooldown_min = 100 action_icon_state = "time" @@ -188,7 +188,7 @@ charge_max = 1200 clothes_req = TRUE invocation = "NOUK FHUNMM SACP RISSKA" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 1 summon_type = list(/mob/living/simple_animal/hostile/carp) @@ -216,7 +216,7 @@ charge_max = 1200 clothes_req = FALSE invocation = "IA IA" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT summon_amt = 10 range = 3 @@ -235,7 +235,7 @@ charge_max = 400 clothes_req = TRUE invocation = "GITTAH WEIGH" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT range = 5 cooldown_min = 150 selection_type = "view" @@ -311,7 +311,7 @@ charge_max = 60 clothes_req = FALSE invocation = "FI'RAN DADISKO" - invocation_type = "shout" + invocation_type = INVOCATION_SHOUT max_targets = 0 range = 6 include_user = TRUE diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index 7f2f73aea00..eed291b61be 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/station_goals/dna_vault.dm @@ -63,10 +63,10 @@ name = "DNA Sampler" desc = "Can be used to take chemical and genetic samples of pretty much anything." icon = 'icons/obj/syringe.dmi' - inhand_icon_state = "hypo" + inhand_icon_state = "sampler" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' - icon_state = "hypo" + icon_state = "sampler" item_flags = NOBLUDGEON var/list/animals = list() var/list/plants = list() diff --git a/code/modules/surgery/advanced/wingreconstruction.dm b/code/modules/surgery/advanced/wingreconstruction.dm new file mode 100644 index 00000000000..fa16e902adc --- /dev/null +++ b/code/modules/surgery/advanced/wingreconstruction.dm @@ -0,0 +1,37 @@ +/datum/surgery/advanced/wing_reconstruction + name = "Wing Reconstruction" + desc = "An experimental surgical procedure that reconstructs the damaged wings of moth people. Requires Instabitaluri." + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/wing_reconstruction) + possible_locs = list(BODY_ZONE_CHEST) + target_mobtypes = list(/mob/living/carbon/human) + +/datum/surgery/advanced/wing_reconstruction/can_start(mob/user, mob/living/carbon/target) + return ..() && target.dna.features["moth_wings"] == "Burnt Off" && ismoth(target) + +/datum/surgery_step/wing_reconstruction + name = "start wing reconstruction" + implements = list(TOOL_HEMOSTAT = 85, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15) + time = 200 + chems_needed = list(/datum/reagent/medicine/c2/instabitaluri) + require_all_chems = FALSE + +/datum/surgery_step/wing_reconstruction/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to fix [target]'s charred wing membranes...", + "[user] begins to fix [target]'s charred wing membranes.", + "[user] begins to perform surgery on [target]'s charred wing membranes.") + +/datum/surgery_step/wing_reconstruction/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + display_results(user, target, "You succeed in reconstructing [target]'s wings.", + "[user] successfully reconstructs [target]'s wings!", + "[user] completes the surgery on [target]'s wings.") + if(H.dna.features["original_moth_wings"] != null) + H.dna.features["moth_wings"] = H.dna.features["original_moth_wings"] + else + H.dna.features["moth_wings"] = "Plain" + H.update_mutant_bodyparts() + return ..() diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index c2a96fbce0b..d4f69095d13 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -112,6 +112,7 @@ return list() /mob/living/carbon/get_missing_limbs() + RETURN_TYPE(/list) var/list/full = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) for(var/zone in full) if(get_bodypart(zone)) diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 5b62fedaa0d..4acd84857ad 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -463,8 +463,7 @@ desc = "A basic cybernetic version of the lungs found in traditional humanoid entities." icon_state = "lungs-c" organ_flags = ORGAN_SYNTHETIC - safe_oxygen_min = 16 - maxHealth = STANDARD_ORGAN_THRESHOLD*0.5 + maxHealth = STANDARD_ORGAN_THRESHOLD * 0.5 var/emp_vulnerability = 80 //Chance of permanent effects if emp-ed. @@ -472,7 +471,6 @@ name = "cybernetic lungs" desc = "A cybernetic version of the lungs found in traditional humanoid entities. Allows for greater intakes of oxygen than organic lungs, requiring slightly less pressure." icon_state = "lungs-c-u" - organ_flags = ORGAN_SYNTHETIC maxHealth = 1.5 * STANDARD_ORGAN_THRESHOLD safe_oxygen_min = 13 emp_vulnerability = 40 @@ -484,6 +482,7 @@ safe_toxins_max = 20 safe_co2_max = 20 maxHealth = 2 * STANDARD_ORGAN_THRESHOLD + safe_oxygen_min = 13 emp_vulnerability = 20 cold_level_1_threshold = 200 diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm index 4d817a6f732..e307fe32d08 100755 --- a/code/modules/surgery/organs/stomach.dm +++ b/code/modules/surgery/organs/stomach.dm @@ -128,3 +128,37 @@ /obj/item/organ/stomach/ethereal/proc/adjust_charge(amount) crystal_charge = clamp(crystal_charge + amount, ETHEREAL_CHARGE_NONE, ETHEREAL_CHARGE_DANGEROUS) + +/obj/item/organ/stomach/cybernetic + name = "basic cybernetic stomach" + icon_state = "stomach-c" + desc = "A basic device designed to mimic the functions of a human stomach" + organ_flags = ORGAN_SYNTHETIC + maxHealth = STANDARD_ORGAN_THRESHOLD * 0.5 + var/emp_vulnerability = 80 //Chance of permanent effects if emp-ed. + +/obj/item/organ/stomach/cybernetic/tier2 + name = "cybernetic stomach" + icon_state = "stomach-c-u" + desc = "An electronic device designed to mimic the functions of a human stomach. Handles disgusting food a bit better." + maxHealth = 1.5 * STANDARD_ORGAN_THRESHOLD + disgust_metabolism = 2 + emp_vulnerability = 40 + +/obj/item/organ/stomach/cybernetic/tier3 + name = "upgraded cybernetic stomach" + icon_state = "stomach-c-u2" + desc = "An upgraded version of the cybernetic stomach, designed to improve further upon organic stomachs. Handles disgusting food very well." + maxHealth = 2 * STANDARD_ORGAN_THRESHOLD + disgust_metabolism = 3 + emp_vulnerability = 20 + +/obj/item/organ/stomach/cybernetic/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + if(!COOLDOWN_FINISHED(src, severe_cooldown)) //So we cant just spam emp to kill people. + owner.vomit(stun = FALSE) + COOLDOWN_START(src, severe_cooldown, 10 SECONDS) + if(prob(emp_vulnerability/severity)) //Chance of permanent effects + organ_flags |= ORGAN_SYNTHETIC_EMP //Starts organ faliure - gonna need replacing soon. diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index eb353b8dda8..dff8642f839 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -171,10 +171,8 @@ chems += chemname return english_list(chems, and_text = require_all_chems ? " and " : " or ") -//Replaces visible_message during operations so only people looking over the surgeon can tell what they're doing, allowing for shenanigans. +//Replaces visible_message during operations so only people looking over the surgeon can see them. /datum/surgery_step/proc/display_results(mob/user, mob/living/carbon/target, self_message, detailed_message, vague_message, target_detailed = FALSE) - var/list/detailed_mobs = get_hearers_in_view(1, user) //Only the surgeon and people looking over his shoulder can see the operation clearly - if(!target_detailed) - detailed_mobs -= target //The patient can't see well what's going on, unless it's something like getting cut user.visible_message(detailed_message, self_message, vision_distance = 1, ignored_mobs = target_detailed ? null : target) - user.visible_message(vague_message, "", ignored_mobs = detailed_mobs) + if(!target_detailed) + to_chat(target, vague_message) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 9b7bc5df5fb..e0cb06733ca 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -2,6 +2,14 @@ //Keep this sorted alphabetically #ifdef UNIT_TESTS +/// Asserts that a condition is true +/// If the condition is not true, fails the test +#define TEST_ASSERT(assertion, reason) if (!(assertion)) { return Fail("Assertion failed: [reason || "No reason"]") } + +/// Asserts that the two parameters passed are equal, fails otherwise +/// Optionally allows an additional message in the case of a failure +#define TEST_ASSERT_EQUAL(a, b, message) if ((a) != (b)) { return Fail("Expected [a] to be equal to [b].[message ? " [message]" : ""]") } + #include "anchored_mobs.dm" #include "bespoke_id.dm" #include "card_mismatch.dm" @@ -13,6 +21,10 @@ #include "spawn_humans.dm" #include "species_whitelists.dm" #include "subsystem_init.dm" +#include "surgeries.dm" #include "timer_sanity.dm" #include "unit_test.dm" + +#undef TEST_ASSERT +#undef TEST_ASSERT_EQUAL #endif diff --git a/code/modules/unit_tests/surgeries.dm b/code/modules/unit_tests/surgeries.dm new file mode 100644 index 00000000000..761168d3d70 --- /dev/null +++ b/code/modules/unit_tests/surgeries.dm @@ -0,0 +1,79 @@ +/datum/unit_test/amputation/Run() + var/mob/living/carbon/human/patient = allocate(/mob/living/carbon/human) + var/mob/living/carbon/human/user = allocate(/mob/living/carbon/human) + + TEST_ASSERT_EQUAL(patient.get_missing_limbs().len, 0, "Patient is somehow missing limbs before surgery") + + var/datum/surgery/amputation/surgery = new(patient, BODY_ZONE_R_ARM, patient.get_bodypart(BODY_ZONE_R_ARM)) + + var/datum/surgery_step/sever_limb/sever_limb = new + sever_limb.success(user, patient, BODY_ZONE_R_ARM, null, surgery) + + TEST_ASSERT_EQUAL(patient.get_missing_limbs().len, 1, "Patient did not lose any limbs") + TEST_ASSERT_EQUAL(patient.get_missing_limbs()[1], BODY_ZONE_R_ARM, "Patient is missing a limb that isn't the one we operated on") + +/datum/unit_test/brain_surgery/Run() + var/mob/living/carbon/human/patient = allocate(/mob/living/carbon/human) + patient.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_SURGERY) + patient.setOrganLoss(ORGAN_SLOT_BRAIN, 20) + + TEST_ASSERT(patient.has_trauma_type(), "Patient does not have any traumas, despite being given one") + + var/mob/living/carbon/human/user = allocate(/mob/living/carbon/human) + + var/datum/surgery_step/fix_brain/fix_brain = new + fix_brain.success(user, patient) + + TEST_ASSERT(!patient.has_trauma_type(), "Patient kept their brain trauma after brain surgery") + TEST_ASSERT(patient.getOrganLoss(ORGAN_SLOT_BRAIN) < 20, "Patient did not heal their brain damage after brain surgery") + +/datum/unit_test/multiple_surgeries/Run() + var/mob/living/carbon/human/user = allocate(/mob/living/carbon/human) + var/mob/living/carbon/human/patient_zero = allocate(/mob/living/carbon/human) + var/mob/living/carbon/human/patient_one = allocate(/mob/living/carbon/human) + + var/obj/item/scalpel/scalpel = allocate(/obj/item/scalpel) + + var/datum/surgery_step/incise/surgery_step = new + var/datum/surgery/organ_manipulation/surgery_for_zero = new + + INVOKE_ASYNC(surgery_step, /datum/surgery_step/proc/initiate, user, patient_zero, BODY_ZONE_CHEST, scalpel, surgery_for_zero) + TEST_ASSERT(surgery_for_zero.step_in_progress, "Surgery on patient zero was not initiated") + + var/datum/surgery/organ_manipulation/surgery_for_one = new + + // Without waiting for the incision to complete, try to start a new surgery + TEST_ASSERT(!surgery_step.initiate(user, patient_one, BODY_ZONE_CHEST, scalpel, surgery_for_one), "Was allowed to start a second surgery without the rod of asclepius") + TEST_ASSERT(!surgery_for_one.step_in_progress, "Surgery for patient one is somehow in progress, despite not initiating") + + user.apply_status_effect(STATUS_EFFECT_HIPPOCRATIC_OATH) + INVOKE_ASYNC(surgery_step, /datum/surgery_step/proc/initiate, user, patient_one, BODY_ZONE_CHEST, scalpel, surgery_for_one) + TEST_ASSERT(surgery_for_one.step_in_progress, "Surgery on patient one was not initiated, despite having rod of asclepius") + +/datum/unit_test/tend_wounds/Run() + var/mob/living/carbon/human/patient = allocate(/mob/living/carbon/human) + patient.take_overall_damage(100, 100) + + var/mob/living/carbon/human/user = allocate(/mob/living/carbon/human) + + // Test that tending wounds actually lowers damage + var/datum/surgery_step/heal/brute/basic/basic_brute_heal = new + basic_brute_heal.success(user, patient, BODY_ZONE_CHEST) + TEST_ASSERT(patient.getBruteLoss() < 100, "Tending brute wounds didn't lower brute damage ([patient.getBruteLoss()])") + + var/datum/surgery_step/heal/burn/basic/basic_burn_heal = new + basic_burn_heal.success(user, patient, BODY_ZONE_CHEST) + TEST_ASSERT(patient.getFireLoss() < 100, "Tending burn wounds didn't lower burn damage ([patient.getFireLoss()])") + + // Test that wearing clothing lowers heal amount + var/mob/living/carbon/human/naked_patient = allocate(/mob/living/carbon/human) + naked_patient.take_overall_damage(100) + + var/mob/living/carbon/human/clothed_patient = allocate(/mob/living/carbon/human) + clothed_patient.equipOutfit(/datum/outfit/job/doctor, TRUE) + clothed_patient.take_overall_damage(100) + + basic_brute_heal.success(user, naked_patient, BODY_ZONE_CHEST) + basic_brute_heal.success(user, clothed_patient, BODY_ZONE_CHEST) + + TEST_ASSERT(naked_patient.getBruteLoss() < clothed_patient.getBruteLoss(), "Naked patient did not heal more from wounds tending than a clothed patient") diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index 492bfecf4d9..57f4efab293 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -25,9 +25,11 @@ GLOBAL_VAR(test_log) //internal shit var/succeeded = TRUE + var/list/allocated var/list/fail_reasons /datum/unit_test/New() + allocated = new run_loc_bottom_left = locate(1, 1, 1) run_loc_top_right = locate(5, 5, 1) @@ -35,6 +37,7 @@ GLOBAL_VAR(test_log) //clear the test area for(var/atom/movable/AM in block(run_loc_bottom_left, run_loc_top_right)) qdel(AM) + QDEL_LIST(allocated) return ..() /datum/unit_test/proc/Run() @@ -48,6 +51,18 @@ GLOBAL_VAR(test_log) LAZYADD(fail_reasons, reason) +/// Allocates an instance of the provided type, and places it somewhere in an available loc +/// Instances allocated through this proc will be destroyed when the test is over +/datum/unit_test/proc/allocate(type, ...) + var/list/arguments = args.Copy(2) + if (!arguments.len) + arguments = list(run_loc_bottom_left) + else if (arguments[1] == null) + arguments[1] = run_loc_bottom_left + var/instance = new type(arglist(arguments)) + allocated += instance + return instance + /proc/RunUnitTests() CHECK_TICK diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index f48e3decb07..6e5e6a07068 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -962,6 +962,14 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/machinery/vending/onTransitZ() return +/obj/machinery/vending/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) + . = ..() + var/mob/living/L = AM + if(tilted || !istype(L) || !prob(20 * (throwingdatum.speed - L.throw_speed))) // hulk throw = +20%, neckgrab throw = +20% + return + + tilt(L) + /obj/machinery/vending/custom name = "Custom Vendor" icon_state = "robotics" diff --git a/config/game_options.txt b/config/game_options.txt index 544ae19ce44..e4c458a5a7e 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -45,7 +45,7 @@ WALK_DELAY 4 ##MULTIPLICATIVE_MOVESPEED /mob/living/carbon/monkey 0 ##MULTIPLICATIVE_MOVESPEED /mob/living/carbon/alien 0 ##MULTIPLICATIVE_MOVESPEED /mob/living/simple_animal/slime 0 -MULTIPLICATIVE_MOVESPEED /mob/living/simple_animal 1 +MULTIPLICATIVE_MOVESPEED /mob/living/simple_animal 0 ## NAMES ### diff --git a/html/changelog.html b/html/changelog.html index 3f2ce5b2be6..0ead303da11 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -1,1859 +1,1859 @@ - - - - /tg/ Station 13 Changelog - - - - - - - -
- - - - -
-
Traditional Games Space Station 13
- -

- Join our Discord channel -
- - - - - -
- Current Project Maintainers
- Recent GitHub contributors
- Thanks to: Baystation 12, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original Space Station 13 developers, Invisty for the title image and the countless others who have contributed to the game, issue tracker or wiki over the years. -
Have a bug to report?
Visit our Issue Tracker.
- Please search first to ensure that the bug has not already been reported. -
- - -
-

08 July 2020

-

ArcaneMusic updated:

-
    -
  • The bounty board has been added to all standard NT stations, for making and paying out bounties for credits made by crew members across the station. Available as a standalone machine, as well as a modular app.
  • -
-

Fikou updated:

-
    -
  • fixes labor camp beacon sprite
  • -
  • manly dorf now doesnt turn on dorf mode with alcohol tolerance
  • -
-

Jared-Fogle updated:

-
    -
  • Fixed cryo cells locking up those with prosthetic limbs.
  • -
  • Fixes tend wounds not healing and brain surgery not curing traumas.
  • -
-

ShizCalev updated:

-
    -
  • Added more examine text to bots.
  • -
-

oranges updated:

-
    -
  • Where some names might previously have been accepted, they will now be rejected, this should not affect any regular names in use
  • -
- -

07 July 2020

-

ATHATH updated:

-
    -
  • The description of eldritch essence has been modified to make what it actually does more clear.
  • -
  • Eldritch essence and unholy water both now actually use the metabolization_rate variable.
  • -
-

ArcaneMusic updated:

-
    -
  • Added a new mutation of geraniums, called Fraxinella, AKA Burning Bush.
  • -
  • Added a new mutation of watermelon, called Barrel Melon, which has the new trait Auto-Distilling Composition. (Sprite provided by Kryson)
  • -
  • Walking Mushrooms now have a new graftable gene, Occulary Mimicry.
  • -
-

EdgeLordExe updated:

-
    -
  • Nitric acid is slightly better
  • -
  • Meat hook is now a 11tc cook traitor item. It can no longer be aquired from necropolis chests. sorry miners!
  • -
-

Fikou updated:

-
    -
  • servicelathe can now print airlock painters, decal painters and spraycans
  • -
  • explorer suits now have space suit level heat protection
  • -
-

Jared-Fogle updated:

-
    -
  • Donut boxes will now accurately show what donuts are inside.
  • -
  • Fixed a bug where when teleporting naturally (such as going through a z-level in space), if you were pulling someone that was then pulling another person, only you and the person you were pulling would make it through.
  • -
  • Removed the healing skill, and by effect dissection surgery and the legendary healer's cloak.
  • -
-

Jay Smith updated:

-
    -
  • The Portable Chemical Mixer now uses proper vortex anomaly cores instead of raw ones.
  • -
-

Kathy Ryals updated:

-
    -
  • Nanotrasen finally realized they forgot to ship the mandatory anomaly compressor and two anomaly cores to Icebox.
  • -
-

LemonInTheDark updated:

-
    -
  • Removed the research modes from tesla coils and radiation collectors.
  • -
-

Orchian updated:

-
    -
  • Added a new traitor item for HoP and QM, the OCD
  • -
-

ShizCalev updated:

-
    -
  • Fixed gas canisters having a misplaced flashing icon when they are close to empty.
  • -
  • Fixed inducers not working on a couple items with internal powercells.
  • -
  • Fixed a scenario where mobs would accidentally be kicked off a vehicle if they were handcuffed.
  • -
  • Added support to kick a mob off a vehicle if the vehicle is restrained.
  • -
  • You can now unlock bots by alt-clicking them when their maintenance panel is open.
  • -
  • Optimized a good chunk of MULEbot code, fixing things such as it rebuilding it's overlays/icons 5 times every second while moving to a destination. Less free lag!
  • -
  • Fixed MULEbots closing crates when the crate doesn't actually get loaded onto it.
  • -
  • Fixed the maintenance hatch on MULEbots visually closing for a moment when emagged.
  • -
  • Paranormal MULEbots will no longer briefly turn into a normal MULEbot when emagged.
  • -
  • Fixed interface exploits involving paranormal MULEbots carrying ghosts.
  • -
  • Fixed MULEbot blood tracks sometimes facing the wrong direction.
  • -
  • Player controlled MULEbots will now leave bloody tracks if they've run over a mob.
  • -
  • Fixed players riding MULEbots sometimes appearing underneath it instead of ontop of it.
  • -
  • Fixed AI's making a chiming noise when they receive a remote notification from a MULEbot. Now only the AI will hear the notification's sound.
  • -
  • Fixed MULEbots dropping mobs off at their current location instead of at their dropoff point.
  • -
  • Fixed a minor runtime related to MULEbots dropping off deleted items/mobs.
  • -
  • Fixed mobs having the wrong height offset when riding MULEbots.
  • -
  • Fixed mobs sometimes ending up underneath MULEbots while riding them.
  • -
  • Fixed mobs not falling off MULEbots when stunned / incapacitated.
  • -
  • Fixed inducers not recharging MULEbots.
  • -
  • Fixed MULEbots leaving bloody tracks in space.
  • -
  • Fixed MULEbots leaving multiple blood tracks in the same spot if they failed to move.
  • -
  • Fixed hacked MULEbots spamming messages about knocking down a mob when they didn't actually do it.
  • -
  • Fixed MULEbot commands not resetting when they were turned off.
  • -
  • Fixed MULEbots not turning off properly when their maintenance hatch is opened.
  • -
  • Fixed MULEbots not turning off properly when they ran out of power while moving.
  • -
  • Fixed MULEbots flashing their external warning lights while they're turned off when their avoidance wire is cut.
  • -
  • Fixed mobs being able to walk right over MULEbots when they turn off.
  • -
  • MULEbots will now try to put their powercell in your hands when you remove them with a crowbar.
  • -
  • Fixed the interface for MULEbots briefly looking like you turned it on successfully even though it was out of power.
  • -
  • MULEbots will now provide feedback if they fail to turn on due to their maintenance panel being open.
  • -
  • MULEbots will no longer flash and beep when their wires are pulsed if they don't have power.
  • -
  • MULEbots will now actually flash when their external warning lights are pulsed.
  • -
  • MULEbots will now flash when they beep / buzz.
  • -
  • Added a bit more examine text to MULEbots.
  • -
  • Fixed an exploit involving coins and mints that could crash the server.
  • -
  • Fixed buckled mobs sometimes appearing over what they're buckled to.
  • -
  • Renamed the "Paranormal MULEbot" to simply, "GHOULbot".
  • -
  • L6 Saw's inhands work again.
  • -
  • Fixed a couple exploits involving the L6.
  • -
  • Guns with a magazine + a round in the chamber won't appear empty anymore.
  • -
  • Energy based guns are no longer missing textures when worn.... Again.
  • -
  • Touched up and added a few worn / inhand icons for some energy based guns.
  • -
-

TetraZeta, NecromancerAnne updated:

-
    -
  • A new sprite for the Marisa outfit.
  • -
-

TheVekter updated:

-
    -
  • NT has approved orders for all members of Cargo to spawn with NTOS-capable tablets.
  • -
-

bobbahbrown updated:

-
    -
  • AI laws no longer include HTML on tgui displays
  • -
-

nightred updated:

-
    -
  • Service hall's deliveries windoor access has been fix
  • -
-

zxaber updated:

-
    -
  • The thermal vision modules found on certain Syndicate cyborgs is functional once more.
  • -
- -

06 July 2020

-

ATHATH updated:

-
    -
  • The default chem capacity of most grown plants is now 100u.
  • -
-

Anturk + Arm + other summer ball contributors code, trollbreeder + fikou + jerryderpington mapping updated:

-
    -
  • Mafia minigame added for ghosts
  • -
-

ArcaneMusic updated:

-
    -
  • Vend-A-Trays are now operated through a UI.
  • -
-

Arkatos updated:

-
    -
  • Jukebox now uses tgui.
  • -
  • You can now set a volume of a jukebox songs.
  • -
-

Disco updated:

-
    -
  • [Icebox] SM exterior cooling pipes have had unnecessary thermal shielding removed
  • -
-

EdgeLordExe updated:

-
    -
  • Added Extreme Medcine Allergy, a new quirk that gives you 2 points!
  • -
  • CHEMS METABOLIZE AGAIN
  • -
-

Inept, KathyRyals updated:

-
    -
  • A few minor map fixes, hot from the oven.
  • -
-

Jay Smith & Michael Trauf updated:

-
    -
  • Portable Chemical Mixer (Requires a vortex anomaly core to activate)
  • -
  • Unique sprites for the Portable Chemical Mixer
  • -
  • Added Portable Chemical Mixer to the Medical Techfab
  • -
-

LemonInTheDark updated:

-
    -
  • Contaminated objects will now glow bright green until cleaned, remember to quarantine rouge free golems.
  • -
  • Buffed rad goggles in general, the text lasts longer, is brighter, and will show more then twice as far away
  • -
  • Fixed the text from radiation goggles not showing above mobs
  • -
  • The APC control console is now tgui rather then html. It should be a lot more usable. I've made other changes, you won't notice.
  • -
-

Melbert updated:

-
    -
  • Brain Tumor damage is now paused when in stasis.
  • -
  • Brain Tumor damage is now paused when having Mannitol metabolizing in you.
  • -
  • Brain Tumor quirk users will now spawn with a pill bottle containing 4 x 5u Mannitol pills.
  • -
-

MrDoomBringer / Ryll-Ryll updated:

-
    -
  • Admins can now add shrapnel clouds of any projectile they desire to supplypods launched with the Config/Launch Supplypod menu!
  • -
-

Ryll/Shaps updated:

-
    -
  • Bubblegum and Legion can no longer cause wounds, as intended
  • -
-

ShizCalev updated:

-
    -
  • Fixed a few awkward messages related to igniting items.
  • -
  • Info messages are now slightly brighter than notification messages when using dark mode.
  • -
-

Skoglol updated:

-
    -
  • BoxStation has been removed in favor of IceBox.
  • -
-

Timberpoes & Kathy Ryals updated:

-
    -
  • The Bluespace Locator now uses TGUI.
  • -
-

Wayland-Smithy updated:

-
    -
  • New alien larva spawn tips!
  • -
  • Alien Queens are now easier to distinguish over hivemind communication similar to a Blob Overmind.
  • -
- -

05 July 2020

-

Caldony updated:

-
    -
  • the damp rag can now clean microwaves!
  • -
-

Disco updated:

-
    -
  • Miners can now open doors and cabinets in luxury bar capsules they purchase
  • -
-

Firecage updated:

-
    -
  • The reading rooms on Metastation has been renovated into a small art gallery.
  • -
-

Fox McCloud updated:

-
    -
  • Fixes station alert consoles not properly displaying alerts
  • -
-

Iatots updated:

-
    -
  • Traitorous research directors can now order the laser arm implant from their uplink, like roboticists.
  • -
-

LemonInTheDark updated:

-
    -
  • The sm will no longer gain eer when hugboxed, such as on shuttles.
  • -
  • Added some more hugbox flags, use as desired.
  • -
-

XRandomXManX updated:

-
    -
  • When further examining a battle arcade machine it will display all the combos that can be used.
  • -
-

anconfuzedrock updated:

-
    -
  • cargo cases don't let you buy 3 guns for literally cheaper than buying a bulk crate with the guns in them any more.
  • -
-

nightred updated:

-
    -
  • Meta Bar counters are tweaked in placement
  • -
  • Cold rooms are now cold, no longer arctic conditions.
  • -
- -

04 July 2020

-

ArcaneMusic updated:

-
    -
  • Plants with over 100% reagent genes now split up their reagents between all available chemicals.
  • -
  • Plants now correctly apply percentages of reagents to a plant's overall reagent capacity.
  • -
  • Densified Chemicals now causes plants to produce half the yield, while still produces double capacity plants.
  • -
  • The richest crew account on station is now showcased on the round-end window! Flex on your coworkers!
  • -
  • Economy Logging now totals how much money the crew had at round-end.
  • -
-

Tlaltecuhtli updated:

-
    -
  • the chamaleon stamp can now stamp cardboard into syndiboxes
  • -
-

ivanmixo updated:

-
    -
  • You can now check yourself for injuries while handcuffed
  • -
- -

03 July 2020

-

Jared-Fogle updated:

-
    -
  • Changed the configuration to enable moths by default, rather than being commented out.
  • -
  • Updated defibrilator mount description to remove line about being immovable.
  • -
  • You can now place people you are fireman carrying onto morgue trays.
  • -
  • You can now place people you are fireman carrying onto objects that buckle players.
  • -
-

ShizCalev updated:

-
    -
  • Jaunting mobs can now travel over bar tables.
  • -
  • Fixed an invisible cable stack on derelict.
  • -
-

WarlockD updated:

-
    -
  • Your suit now washes under the shower
  • -
  • Sink now cleans properly
  • -
-

bobbahbrown updated:

-
    -
  • Jannies rejoice, the sanitation department has developed a new experimental broom module for our robotic cleaning friends. Ask your roboticist for a broom upgrade today!
  • -
-

zxaber updated:

-
    -
  • Hulks now take damage to their arms for smashing walls and machines. You won't get through very many walls before you have to visit medical, though the damage for punching an airlock is quite a bit less.
  • -
- -

01 July 2020

-

ATH1909 updated:

-
    -
  • Freon's warning message no longer depends on the presence of nitryl in your lungs.
  • -
-

ATHATH updated:

-
    -
  • The medbot on the library ship is now special.
  • -
  • The damage taken from being thrown into a wall should now use the same wound_bonus value as the damage you'd take from being thrown into a human would use.
  • -
-

Melbert updated:

-
    -
  • Blind people can now feel when they're being hugged and shaken. Go hug your local blind person today.
  • -
-

TaF updated:

-
    -
  • Adds an invisible/hidden icon that can be used for items that may not be in need of a sprite.
  • -
  • Weapons sawn off show a worn icon after being sawn.
  • -
  • Energy weapons properly show ammo depletion when worn. Icons for this are still a work in progress.
  • -
  • Fixes neckerchief icon overlay issue.
  • -
  • Fixes nanite scanner in_hand icon.
  • -
  • Fixes 23 items with common worn icons.
  • -
  • Removes duplicate null icon in back slot icon file
  • -
-

Wayland-Smithy updated:

-
    -
  • Revenants, being spirits, can now hear ghost gang banter.
  • -
  • Revenant speech color is now readable when using Darkmode.
  • -
-

carshalash updated:

-
    -
  • Causes the reactive spine blob type to retaliate to bun as well as brute damage
  • -
-

ivanmixo updated:

-
    -
  • You can no longer take your ID out while unconscious or in soft crit
  • -
-

nightred updated:

-
    -
  • Meta bar tables are not that metal
  • -
- -

30 June 2020

-

ATH1909 updated:

-
    -
  • The messages from attempting to feed someone the contents of a glass container (including, say, disease bottles or vaccine bottles) will now mention the name of the aforementioned container.
  • -
-

Arkatos updated:

-
    -
  • All Abductor machines now use tgui.
  • -
-

Iatots updated:

-
    -
  • runtime station has a small genetics section now
  • -
  • runtime station doesn't run out of power anymore
  • -
-

Ryll/Shaps updated:

-
    -
  • Fixed an issue with Nuke Ops tablets being invisible
  • -
-

ShizCalev updated:

-
    -
  • Fixed newspapers not being flammable.
  • -
  • Standardized how paper products are burned. You're now able to ignite newspapers, folders, and photographs with lights/welders/hot stuff!
  • -
  • Igniting a piece of paper will no longer cause it to teleport to your feet.
  • -
  • Fixed some paper interactions not leaving fingerprints on the object.
  • -
-

WarlockD updated:

-
    -
  • Medical Kiosk shows rad contamination
  • -
  • Medical Kiosk gives better directions on rad sickness
  • -
-

sprites, Edge code updated:

-
    -
  • Codex cicatrix now looks a lot better
  • -
- -

29 June 2020

-

FloranOtten updated:

-
    -
  • Nanotrasen Scouting forces have recently reported being shot at by an old man in a shack. Watch out for any strange log cabins!
  • -
-

ShizCalev updated:

-
    -
  • Fixed pamphlets having the wrong icon.
  • -
  • Fixed pamphlets and a couple of guides never showing that they're on fire.
  • -
  • Paper will no longer infinitely add new fire overlays while they're on fire.
  • -
  • Paper planes will now use the proper icon while on fire.
  • -
  • Added support for custom fire overlays for objects. Set the custom_fire_overlay var to change it!
  • -
-

anconfuzedrock updated:

-
    -
  • ninja dashes recharge 5x as slow, but they all recharge at the same time.
  • -
  • ninjas are slightly less the definition of speed. They're also faster when their suit is depowered I guess.
  • -
-

and KathyRyals updated:

-
    -
  • Nanotrasen found out about the amount of expensive chemicals served in survival medipens and cut them down to safe costs...
  • -
  • ...And they turned the old medipen into a luxury
  • -
  • Lavaland Extract was found to break laws of physics and was removed from existance
  • -
- -

28 June 2020

-

ATHATH updated:

-
    -
  • Fixed n2o knocking out players for longer than expected.
  • -
-

ArcaneMusic updated:

-
    -
  • Adds the Cargo Bounty UI as a modular app, with cargo access.
  • -
  • The Cargo Bounty UI has been revamped.
  • -
  • Cargo tablets now come preinstalled with the price tagger and cargo bounty apps.
  • -
-

Cyberboss updated:

-
    -
  • TGS4 channel tags will now use ',' as a delimiter to indicate multiple tags.
  • -
-

EdgeLordExe updated:

-
    -
  • Mansus grasp now wont proc on things it shouldnt proc on, tl;dr you wont loose your charges by missclicking on a tile.
  • -
  • Replaced touch of madness with a new fun late game spell
  • -
  • Switches positions of blood siphon and cleave
  • -
-

Fikou updated:

-
    -
  • you can now transmute a pen, a pair of eyes, a bible and human skin into a spare codex cicatrix if you researched some new lore
  • -
  • mjolnir now knockdowns instead of stunning
  • -
-

Hopek updated:

-
    -
  • Tape recorder has been reworked.
  • -
-

KathyRyals updated:

-
    -
  • The Xray mutation can no longer be obtained via combining radioactive and thermal eyes.
  • -
-

ShizCalev updated:

-
    -
  • Fixed some bad areacoord messages when teleporting around.
  • -
  • Fixed an exploit that would allow you to destroy round-critical / indestructible items with folders.
  • -
-

XRandomXManX updated:

-
    -
  • Removed Decal Painter from BEPIS Minor Rewards
  • -
  • Added Decal Painter to the Basic Tools Research Node
  • -
  • Added Decal Painter to Maintenance Loot alongside the Airlock Painter
  • -
-

necromanceranne updated:

-
    -
  • Added new heretic blade sprites! One for the Ashen Blade, Rusted Blade and Flesh Blade
  • -
  • The blades have some descriptions now.
  • -
  • Fixed some infiltrator toolbox sprites (hopefully).
  • -
  • Some eldritch items have had their descriptions and text altered to be a bit more legible and flavourful.
  • -
-

nightred updated:

-
    -
  • Service department area update on Meta
  • -
  • Stackers deposit to the silo when picking up stacks from the input side.
  • -
-

silicons updated:

-
    -
  • An explosion compressor has been added to science. It makes raw anomaly cores into proper anomaly cores using prepared TTVs of a specific required blast radius.
  • -
- -

27 June 2020

-

Ryll/Shaps updated:

-
    -
  • Too much bone hurting juice REALLY hurts your bones, oof.
  • -
-

Tlaltecuhtli updated:

-
    -
  • the nanotransen research science division found that epinephrine has healing effects to people who drank lexorin
  • -
  • eye stabbing returns a normal attack if it fails instead of doing nothing
  • -
- -

26 June 2020

-

Arkatos updated:

-
    -
  • Portable Turret now uses tgui.
  • -
-

Ryll/Shaps updated:

-
    -
  • Nanotrasen now uses smaller fonts on ID's to show age and account information, requiring a closer look to read
  • -
-

ShizCalev updated:

-
    -
  • Fixed revenant's light overload ability not blowing lights in a square if there was another broken/burnt out/empty light in it.
  • -
  • Fixed showing a piece of paper to a camera not working if there was an AI that had died or has remote access disabled.
  • -
  • Bank cards will now still give you notifications if you're standing next to another player who has them disabled.
  • -
  • Fixed bronze golems' gong ability not working if there was a dead mob on screen.
  • -
  • Fixed bone golems' bonechill ability not working if there was any mobs that were undead, resistant to cold, or also golems on screen.
  • -
  • Fixed a scenario where you would be unable to offer someone an item if you already had a pending item offer with someone else standing near you.
  • -
-

WarlockD updated:

-
    -
  • Suit cell charge on stat panel
  • -
  • Suit cell gauge works now
  • -
-

coiax updated:

-
    -
  • The Nanite Host Scan program can now scan the host for wounds.
  • -
-

sergeirocks100 updated:

-
    -
  • Malt Liquor can now be obtained from your local Booze-O-Mat
  • -
- -

25 June 2020

-

ATHATH updated:

-
    -
  • The tox purging threshold for livers has been changed from 3u to 3u * [liver's health]/[liver's maximum health].
  • -
-

EdgeLordExe updated:

-
    -
  • Otherwordly presence has taken more control over the holes in reality.
  • -
  • Influences now actually spawn randomly on the station.
  • -
-

Jared-Fogle updated:

-
    -
  • The search bar will now automatically focus when you open up the orbit menu, the uplink, the biogenerator, and the camera console.
  • -
-

Melbert updated:

-
    -
  • Allows the HONK Oingo-Boingo Punch-Face to toggle between lethal and non-lethal modes.
  • -
  • The HONK Oingo-Boingo Punch-Face's throw distance now scales on how much damage it deals. By default, it's the same distance as before.
  • -
  • Pacifists can no longer use the HONK Oingo-Boingo Punch-Face to damage people.
  • -
  • Admins can now edit the damage of the HONK Oingo-Boingo Punch-Face. Honk.
  • -
-

WarlockD updated:

-
    -
  • You can open paper ui with double shift click
  • -
-

dearmochi updated:

-
    -
  • Fix thrown bolas (and other items) bypassing weapon/shield blocking
  • -
- -

24 June 2020

-

ArcaneMusic updated:

-
    -
  • Sentient regal and regular rats can now eat cheese wedges to recover a small amount of health.
  • -
-

Arkatos updated:

-
    -
  • Turret Control Panel now uses tgui.
  • -
-

Caldony updated:

-
    -
  • fixed a bug with the battle arcade game where the combos would sometimes not register correctly.
  • -
-

EdgeLordExe updated:

-
    -
  • Wizard can no longer mindswap into a statue to become neigh invicible, fire throwing bastard.
  • -
  • Wizard can no longer mindswap into laughter or slaughter demons to gain a free jaunt and an unlimited heals for killing people. You know one thing that wizard is good at...
  • -
-

LemonInTheDark updated:

-
    -
  • Removes a redundant check in fire code
  • -
-

Maurukas updated:

-
    -
  • Boxstation and Icebox medbays have been completely reworked
  • -
-

ShizCalev updated:

-
    -
  • Fixed the backpack setting showing up twice in the preferences window.
  • -
  • Chameleon ties can no longer disguise as skill capes.
  • -
  • The SM will no longer pull mobs not affected by gravity.
  • -
-

TemporalOroboros updated:

-
    -
  • Synthflesh works again.
  • -
-

Timberpoes updated:

-
    -
  • DNA Console will no longer bluescreen in certain scenarios when disks are ejected.
  • -
-

WarlockD updated:

-
    -
  • allows the air alarm to let vents suck are as well as pressurize.
  • -
-

tmtmtl30 updated:

-
    -
  • stopped midround dynamic families ruleset from picking mindshielded starting family members
  • -
- -

23 June 2020

-

Kathy Ryals updated:

-
    -
  • Fixed Box wires and pipes near R&D, as well as the door that got deleted.
  • -
-

LemonInTheDark updated:

-
    -
  • Fixed stealth implants not properly boxing the user, and doors not shocking
  • -
  • Renamed COOLDOWN_CHECK to COOLDOWN_FINISHED
  • -
  • Removed some old unused clockcult status effects
  • -
-

LemonInTheDark, Heather Shadelight updated:

-
    -
  • Changed some portal sprites, hope ya like em :)
  • -
-

Paxilmaniac updated:

-
    -
  • PP-95 smg and it's magazine
  • -
  • replaced mosin with pp-95 in the nuke op uplink
  • -
-

ShizCalev updated:

-
    -
  • Fixed logging / admin message coordinate handling for items being held by mobs / in containers / in containers inside other containers giving nullspace / 0,0,0 location references.
  • -
-

Timberpoes updated:

-
    -
  • Belts in Delta EVA and the Ashwalker Ruins no longer show up as ERRORs.
  • -
  • Science are now able to print DNA Scanner boards. Boards associated with Genetics are now only printable in Science and have been removed from Medical printers.
  • -
-

bobbahbrown updated:

-
    -
  • Removed exploitable world/topic command server_hop
  • -
-

silicons updated:

-
    -
  • onZImpact no longer does throw_impact. This was broken anyways. Code must now manually handle multiz falling impacts. This fixes runtimes occuring whenever something fell.
  • -
-

zxaber updated:

-
    -
  • Nuke Ops (and Lone Ops) now start with a Syndicate-themed tablet, rather than the pinpointer. The Syndicate tablet comes pre-installed with an app that replaces the function of disk pinpointers.
  • -
  • Lifeline and Fission360, the apps that track suit sensors and nuke disks respectively, now show the tracking status on the screen of the tablet/laptop object itself, without needing to keep the window open.
  • -
- -

22 June 2020

-

EdgeLordExe updated:

-
    -
  • You can no longer raise the living as ghouls.
  • -
  • Mansus grasp and blood siphon no longer have infinite range.
  • -
  • Armsy can now actually attack with any of his bodyparts. fix:Armsy can now acutally walk in space.
  • -
  • replaced a few type paths with more descriptive ones.
  • -
-

Gamer025 updated:

-
    -
  • Blood drunk miner megafauna can no longer move structures like bolted down doors / windows
  • -
-

Kathy Ryals updated:

-
    -
  • Due to some very convincing paramedics, the medidrobe has been updated to include the paramedic jumpsuit and jumpskirt.
  • -
-

Melbert updated:

-
    -
  • Obsession picture objective no longer needs the obsessed themselves to be in the picture.
  • -
  • Obsession picture objective now works properly.
  • -
-

TemporalOroboros updated:

-
    -
  • Reagent exposure proc names now accurately describe their function.
  • -
  • Reagent exposure code is less `istype` dependent.
  • -
-

WarlockD updated:

-
    -
  • Preview works now
  • -
  • Clicking on "save" now previews correctly
  • -
  • Form fields now sized correctly
  • -
  • Form fields now save the data
  • -
- -

21 June 2020

-

Jared-Fogle updated:

-
    -
  • Pointing will now animate starting from you to the object you pointed at.
  • -
- -

20 June 2020

-

Caldony updated:

-
    -
  • NT finally decided to update the arcade battle video game after its terrible space game reviews from syndicate gaming.
  • -
-

LemonInTheDark updated:

-
    -
  • Fixed a "Feature" from 2 years ago. The sm will now pull objects closer to it based on the eer. This includes you, so be careful.
  • -
  • I've documented all of the sms variables.
  • -
  • Refactored sm code to be more modular. Badmins do not rejoice!
  • -
- -

19 June 2020

-

Kathy Ryals updated:

-
    -
  • The plant analyzer has been updated to be able to analyze a Podman health or chemical contents.
  • -
-

LemonInTheDark updated:

-
    -
  • The singularity will no longer turn snow or ice on icebox into lattices when at stage 5
  • -
-

Ryll/Shaps updated:

-
    -
  • Empaths are able to detect deafness derived from hearing damage
  • -
  • Inacusiate and Sensory Restoration no longer instantly heal all hearing damage when applied, instead rapidly removing both ear damage and deafness.
  • -
  • MedHUDs and observers now display quirks as intended on examine
  • -
  • Nanotrasen's Central Shipping department has put limits on the free shipping it offers on goody crates, to discourage abuse of its bluespace packaging
  • -
-

SteelSlayer updated:

-
    -
  • Removed a handful of unnecessary variables from intercoms.
  • -
  • Refactored intercom's code so that it doesn't need to process() and constantly check whether it's powered or EMP'd every few seconds.
  • -
-

WarlockD updated:

-
    -
  • Cyborgs can now use multi layer cable interface
  • -
-

genessee596 updated:

-
    -
  • TCG brand trading cards now show their rarity on the card, with tiers of rarity attached to a background color on the 'N' box on the bottom right corner.
  • -
- -

18 June 2020

-

ATHATH updated:

-
    -
  • pAIs no longer start with a medHUD, secHUD, and diagHUD turned on as soon as they're downloaded, even if they haven't bought any HUDs yet.
  • -
  • You can now take obligate carnivory grafts from jupiter cups.
  • -
  • You can now take fire resistance grafts from lavaland plants.
  • -
-

Iamgoofball updated:

-
    -
  • Gangsters are, in fact, antags, and can totally kill, destroy, and murder all they want.
  • -
  • Fixes GARBAGE DAY
  • -
  • Dynamic Families now goes from 30 to 15 minutes, instead of 60 to 30 minutes.
  • -
  • Space Cop Objectives have been changed in Families.
  • -
-

ShizCalev updated:

-
    -
  • Fixed a scenario that allowed infinite resource generation via ore machines.
  • -
  • Swarmers can no longer cut power lines by deconstructing catwalks underneath them.
  • -
  • Corrected a minor grammar error when attacking mobs with sharp stuff.
  • -
  • Clothing repair now works.
  • -
  • Fixed redundant "shredded x fell apart, completely shredded!" message when damaging clothing in your hands.
  • -
  • Added better pronoun handling for clothing that consist of a pair of items (ie shoes, gloves, ect)
  • -
  • Shredding clothing while holding it will no longer make you drop it.
  • -
  • Shredding clothing while holding it will no longer tell you that it fell off you.
  • -
  • Moths can no longer infinitely eat shredded clothing.
  • -
  • Tears in the very fabric of reality created by Eldritch gods can no longer be mended with acid, fire, and TK.
  • -
-

TheSpaghetti updated:

-
    -
  • orang
  • -
-

Timberpoes updated:

-
    -
  • Added scroll bar to ghost Orbit target selection menu.
  • -
-

Tlaltecuhtli updated:

-
    -
  • organ transport box, if filled with cryostylene or ice it ll keep organs and bodyparts like heads inside frozen ( they dont decay)
  • -
-

WarlockD updated:

-
    -
  • Added markdown for paper
  • -
-

tralezab updated:

-
    -
  • heretics raising the living into ghouls
  • -
- -

17 June 2020

-

EdgeLordExe updated:

-
    -
  • Having Codex Cicatrix in a pocket while sacrificing someone will give you charges now.
  • -
-

Firecage updated:

-
    -
  • Clown cars are now unable to be driven over ice chasms.
  • -
-

LoserWasTaken updated:

-
    -
  • ooc no longer checks if message is ic if round hasn't started
  • -
-

Melbert updated:

-
    -
  • Fixed staff of animation being able to spawn animated objects inside containers (ie bags)
  • -
-

Mickyan updated:

-
    -
  • fixed missing icon appearing while wearing wigs, again!
  • -
  • wigs will once again change inventory icon based on hairstyle
  • -
-

Ryll/Shaps updated:

-
    -
  • You can no longer embed items into walls
  • -
-

ShizCalev updated:

-
    -
  • Engineering scanner goggles are now the correct color when their modes are switched.
  • -
  • Fixed cable coils always showing as a full stack.
  • -
-

TheChosenEvilOne updated:

-
    -
  • emergency shuttle console no longer lists authorizations twice.
  • -
- -

15 June 2020

-

Cobby kills medbots!!! updated:

-
    -
  • Medbots that are suppose to heal other damage types than brute now actually do so
  • -
-

IradT updated:

-
    -
  • Added a doorjack to the Metaops bundle
  • -
  • added wound armor to the wizard hat
  • -
-

Jared-Fogle updated:

-
    -
  • The health analyzer is now the first item in the first aid kits.
  • -
  • You will now see an alert when you are drunk.
  • -
-

Shadark updated:

-
    -
  • Deltastation Morgue is now accessible from the main hallway.
  • -
-

ShizCalev updated:

-
    -
  • Fixed a bunch of errors appearing on arcade machines and various monitors / computers when powered off.
  • -
- -

14 June 2020

-

Arkatos updated:

-
    -
  • Airlocks will now immediately show their unrestricted access sides when created via RCD.
  • -
-

Fikou updated:

-
    -
  • you can no longer have fun in ctf with metal
  • -
-

Iamgoofball updated:

-
    -
  • Members of the crew with mindshields have remembered that anti-gang PSA they watched back in space high school.
  • -
-

Jared-Fogle updated:

-
    -
  • Added a new organized orbit menu.
  • -
  • Fixed ghosting making your body look undefibbable to a medical HUD.
  • -
-

a few Sprites from Kryson updated:

-
    -
  • Heretics have been spotted near your area, don't let them succed.
  • -
  • Added a sane version of GetAllContents called get_all_gear().
  • -
-

bobbahbrown updated:

-
    -
  • Fixed malformed SQL queries for logging admin permission changes.
  • -
-

dragomagol updated:

-
    -
  • Nanotrasen has begun producing Peacekeeper plushes to improve public reception of silicons
  • -
-

~~yorii~~ Space updated:

-
    -
  • lava boat oars work now
  • -
- -

13 June 2020

-

ATHATH updated:

-
    -
  • The message that you receive when you try to use a gang induction package as a mindshielded person no longer implies that your mindshield has given you fake memories of attending an anti-gang seminar.
  • -
-

Arkatos updated:

-
    -
  • Unrestricted directional access settings will now show correct directions in the related UIs.
  • -
  • Theoretical radiuses will now show properly in the Tachyon-Doppler Array UI.
  • -
-

Ryll/Shaps updated:

-
    -
  • Medbot interaction menus are fixed
  • -
  • You can no longer queue multiple medbot flips at once
  • -
  • Medbots now have lots more to say, especially if you knock them over!
  • -
-

Shadark updated:

-
    -
  • Detective gets roundstart normal sunglasses instead of SecHUDs at PubbyStation.
  • -
  • Balanced access to arrest option through SecHUDs, now requiring Security access instead of Brig access.
  • -
  • Balanced access to portable turrets, now requiring Security access instead of Brig access.
  • -
-

ShizCalev updated:

-
    -
  • Fixed a scenario where changelings would have missing textures when disguised.
  • -
  • Fixed a scenario where camouflage items would have missing textures.
  • -
  • Items in your suit storage should have less missing textures now.
  • -
  • Restore the ion rifle's unique belt texture.
  • -
  • Fixed a few more belt items having missing textures.
  • -
  • Fixed washing machines sometimes fucking up an item's worn texture.
  • -
-

tmtmtl30 updated:

-
    -
  • dynamic families rulesets can now be forced and will execute instead of runtiming
  • -
- -

12 June 2020

-

ATHATH updated:

-
    -
  • Borgs and AIs now start with their borgHUDs/siliconHUDs on by default.
  • -
-

Jared-Fogle updated:

-
    -
  • Ghosts will now be revealed when the round is over.
  • -
-

Ryll/Shaps updated:

-
    -
  • Introduces medical wounds, new injuries that can happen to fleshy carbons when they sustain lots of damage on a bodypart. There's quite a lot of change here, but you can read the guide at: https://tgstation13.org/wiki/Guide_to_wounds and an extended changelog is available here: https://hackmd.io/l_FI9b3tSqa_woDadewJXA
  • -
  • Introduces scars and temporal scarring! Healing a wound leaves a scar behind that can be seen by examining someone twice rapidly, and if Temporal Scarring is enabled in character prefs, surviving a round with scars will save them to be granted at roundstart another round! Let your body tell stories!
  • -
  • Bleeding is now fully bodypart-focused, and 95% of bleeding comes from cut wounds from sharp weapons. Gauze is applied on a limb-by-limb basis, and helps staunch bloodflow rather than totally stop it. Notably, you no longer bleed just from having 40+ brute damage on a limb.
  • -
  • Organic bodyparts are no longer disabled at maximum damage, but are easier to cause wounds to
  • -
  • O2 medkits in emergency lockers have been replaced with new emergency medkits with basic tools for diagnosing and treating wounds and basic damage
  • -
  • Herapin now rapidly increases bleeding on all open cuts, rather than causing bleeding by itself. The more cuts on the target, the more it will affect them.
  • -
  • Neckgrab table slams now hit the targeted limb rather than just the head, with a large chance to dislocate or break a bone
  • -
  • Sharp weapons and burning weapons can now shred zones on jumpsuits, disabling protection on that limb. Damaged clothes can be repaired with cloth.
  • -
  • Slaughter demons now deal less raw damage, but gain the ability to cause cut wounds, which becomes more powerful with each attack on a humanoid but resets when bloodcrawling.
  • -
-

Timberpoes updated:

-
    -
  • Delta's Genetics Lab has been redesigned.
  • -
  • Pubby's Genetics Lab has been redesigned.
  • -
  • Science ID Card access levels have been redesigned. R&D now has its own dedicated access level with Toxins and Toxins Storage having their own dedicated access levels.
  • -
  • Science doors across all maps have had their access levels tweaked, especially around maintenance access and R&D access.
  • -
  • Geneticists now have R&D Access across all maps.
  • -
  • Xenobiology's Winter Coats now have a new set of pockets that can hold all the same equipment as a lab coat.
  • -
  • All Xenobiology secure containment areas there were missing them, now have Connector/Injector pairs for injecting gasses directly into secure containment.
  • -
  • Pubby's Xenobiology lab now has three slime spawns.
  • -
  • Pubby's Xenobiology lab has been expanded with addtional containment pens.
  • -
  • Meta's Xenobiology freezer no longer shares a pipe with Xenobio's air distribution pipes. Scientists should no longer freeze to death and space suits with internals are no longer necessary.
  • -
  • Delta's Xenobiology lab now requires Xenobiology access to enter.
  • -
  • Delta's Xenobiology lab has been expanded with additional containment pens.
  • -
  • Pubby's Toxins Mass Driver room now has an intercom.
  • -
  • Delta's Toxins Mass Driver room's intercom has been moved closer to the Tachyon-Doppler Research Array.
  • -
  • Prototype Hardsuits have been moved to the RD's Office on from Toxins on Meta and Pubby.
  • -
  • All Genetics Labs across all station now come fully equipped with Body Bags, Space Cleaner and Mutadone.
  • -
  • Box's Genetics Lab now has an air alarm.
  • -
  • Meta's Genetics Lab's camera has been moved so the AI can see the entire lab, including the Air Alarm.
  • -
  • Geneticists will no longer spawn in the monkey pen on Meta.
  • -
  • The Medical Laptop in Delta's Genetics lab can now be accessed by Geneticists.
  • -
  • Pubby's Robotics Lab now has a Cautery!
  • -
  • Probably more minor quality of life changes I forgot to document as I made them.
  • -
- -

11 June 2020

-

Arkatos updated:

-
    -
  • Tachyon-Doppler Array now uses tgui.
  • -
-

Inept updated:

-
    -
  • Card collectors, rejoice! The NTED has released a new binder for storing your TCG cards. Pick one up at the Fun vendor today!
  • -
-

ShizCalev updated:

-
    -
  • I comes before E, except after C.
  • -
  • Wearing a gun on your armor / belt will no longer result in your waist turning purple and black.
  • -
-

tmtmtl30 updated:

-
    -
  • The Families gamemode and antagonist have been refactored and should perform more sanely in some cases.
  • -
  • Families can now appear in dynamic rounds.
  • -
- -

10 June 2020

-

ATHATH updated:

-
    -
  • The in-game podcloning guide (The Human Harvest: From Seed to Market) has been updated.
  • -
  • Venus human traps now have x-ray and thermal vision.
  • -
-

ArcaneMusic updated:

-
    -
  • The Seed Vault ruin now comes equip with the complete modern arsenal of new botany tools and equipment.
  • -
-

Arkatos updated:

-
    -
  • Holopad now uses tgui.
  • -
-

Cobby updated:

-
    -
  • craftable medbots now only heal brute unless they are built with specialized medkits.
  • -
  • medbots built with the brute medkit heal 10% more
  • -
  • medbots built with the advance medkit heal all damage types
  • -
-

Fox McCloud updated:

-
    -
  • Fixes attack animations being stuttery and twitchy; they should, once again, be buttery smooth
  • -
-

GoldenAlpharex updated:

-
    -
  • New Modular Console Preset added: /obj/machinery/modular_computer/console/preset/id
  • -
-

Inept updated:

-
    -
  • The Nanotrasen Entertainment Division has released a new product: Tarot cards! They're available from the Fun vendor for all your divination needs.
  • -
-

Jared-Fogle updated:

-
    -
  • Fixed the medical HUD sometimes reporting undefibbable bodies as defibbable and vice versa.
  • -
  • Fixed plasmamen needing hearts in order to be defibbed.
  • -
  • Fixed crew with HARS needing a brain to be defibbed.
  • -
  • Fixed defibrillators being borked. Sorry!
  • -
-

Kelenius updated:

-
    -
  • Hygienebot construction has been fixed.
  • -
  • Hygienebots now require a proximity sensor between welding and tubing.
  • -
  • Hygienebots no longer slip their path while chasing someone.
  • -
  • Hygienebots are less spammy.
  • -
-

Ryll/Shaps updated:

-
    -
  • You can now tip over medbots!
  • -
-

ShizCalev updated:

-
    -
  • Defibbing now works properly on ALL species that don't require hearts to survive, as opposed to just plasmamen.
  • -
  • Defibbing now works properly on mobs with the Muscled Veins trait if their heart was removed.
  • -
-

TheChosenEvilOne updated:

-
    -
  • Fixed dynamic giving antagonist roles to jobs that shouldn't get them (again).
  • -
-

TiviPlus updated:

-
    -
  • Succesful restart votes will now complete instantly
  • -
-

bababooey updated:

-
    -
  • bababooey
  • -
-

bobbahbrown updated:

-
    -
  • Improved performance of lighting code
  • -
-

tmtmtl30 updated:

-
    -
  • removed deprecated check_win() proc
  • -
- -

08 June 2020

-

IndieanaJones updated:

-
    -
  • Lavaland elite loot drops for Broodmother and Legionnaire now have in-hand use functions
  • -
  • Lavaland elites now have more health in their arena fights, along with several other balance changes
  • -
  • Fixed lavaland elites not being able to damage mechs
  • -
-

SpaceManiac updated:

-
    -
  • BSQL has been replaced with rust-g, improving SQL reliability and safety.
  • -
- -

07 June 2020

-

LemonInTheDark updated:

-
    -
  • Breaking a canister while it's wrenched down will no longer cause it to look "goofy"
  • -
-

TheChosenEvilOne updated:

-
    -
  • Removed high population override from dynamic.
  • -
  • fixed dynamic runtiming with invalid configurations.
  • -
-

tmtmtl30 updated:

-
    -
  • Dynamic roundstart ruleset scaling on second-rolled roundstart rulesets has been slightly tweaked.
  • -
- -

06 June 2020

-

IradT updated:

-
    -
  • fixed changeling reset function not giving the right values after absorbing another changeling
  • -
-

Ryll/Shaps updated:

-
    -
  • Having a circle hand or slapper in hand no longer protects you from xeno tackles or borg buckling
  • -
- -

05 June 2020

-

LemonInTheDark updated:

-
    -
  • The singularity no longer turns reinforced floor tiles into infinite rods
  • -
  • Added some unit tests for cards, hopefully you'll see fun things with this soon.
  • -
-

MrDoomBringer updated:

-
    -
  • Supplypods can once again have custom falling sounds
  • -
-

nemvar updated:

-
    -
  • Icelag fix boxed
  • -
- -

04 June 2020

-

ATHATH updated:

-
    -
  • The 16 second hardstun that non-pAI mulebots with cut avoidance wires apply to living creatures they bump into has been replaced with a much more tame 8 second knockdown.
  • -
-

ArcaneMusic updated:

-
    -
  • Organic Pest Killer is now available in the biogenerator.
  • -
  • Pest Killer and Weed Killer now applies the correct amount of toxicity and doesn't individually harm the plant's health.
  • -
  • Pest/Week killer bottles now have a transfer rate of 1 ,2, and 5 units per use, and a max capacity of 30 units.
  • -
-

Fikou updated:

-
    -
  • atmos jumpsuit now has the same armor values as engi jumpsuit
  • -
  • replaces plasma in bluespace beaker design with plastic
  • -
-

Ryll/Shaps updated:

-
    -
  • Cigarette packets now have coupons on the back for small cargo items! Smoking DOES pay!
  • -
  • Single/small items in cargo have been rebranded as goodies, come in lockboxes rather than crates, and can only be purchased with private accounts. They also are immune to the 10% private account fee, obviously.
  • -
-

Skoglol updated:

-
    -
  • Removed some dead unused code in languages.
  • -
  • Box gravity generator and AI core APC rewired to smes, will not run out roundstart anymore. P.A.C.M.A.N. added to grav gen for emergencies.
  • -
-

TheChosenEvilOne updated:

-
    -
  • Dynamic will no longer give antagonist roles to jobs who shouldn't have them when restricted roles is set in the config.
  • -
-

Tlaltecuhtli updated:

-
    -
  • lightfloor makes colored lights and are more visible
  • -
  • you can turn them off/on by using your screwdriver
  • -
  • you can emp em
  • -
  • breaking them actually works
  • -
  • using a broken bulb wont fix em sprites: flicker states for each colour
  • -
-

necromanceranne updated:

-
    -
  • Neckgrabs and especially floor neckgrabs are no longer near impossible to escape.
  • -
  • Resisting a grab is more consistent across the board, but you get less chances at resisting a grab and take more stamina damage.
  • -
- -

02 June 2020

-

ArcaneMusic updated:

-
    -
  • The hallway on icebox mining is slightly longer. and the ladder deposits you in the locker room.
  • -
  • The icebox mining ladder works again.
  • -
-

EOBGames, ArcaneMusic, LemonInTheDark updated:

-
    -
  • Nanotrasen is pleased to announce the 2560 Core Set of the NT TCG has been released! Aspiring collectors can purchase booster packs from the Fun Vendor, as well as bulk purchases at cargo. Happy hunting!
  • -
-

Kelenius updated:

-
    -
  • DNA scanner can now store any amount of mutations and chromosomes.
  • -
- -

01 June 2020

-

Fhaxaris updated:

-
    -
  • baton, health analyzer, classic baton, PDA and pinpointer.
  • -
-

Fikou updated:

-
    -
  • Our Nanotrasen Elite Anti-Animal Team hunted down King Goat and stopped his reign forever. As a memorial of this event you can now get a cute goat plushie from the arcades.
  • -
-

PrimordialOoze updated:

-
    -
  • Split the Ignore verb into two verbs (Ignore and Unignore)
  • -
  • Unignore allows you to view your ignore list
  • -
  • Unignore allows you to unignore players who are offline
  • -
  • Ignore and Unignore should not interfere with Stealth Mode
  • -
-

SomeoneYouProbablyKnow updated:

-
    -
  • Psychologists gets a new Hud icon that's not a P
  • -
  • The "incarcerated" sec hud icon gets a new sprite that is not a P
  • -
-

TemporalOroboros updated:

-
    -
  • Firesuits and radiation suits can now fit most internals tanks.
  • -
-

Timberpoes updated:

-
    -
  • Only the Descendents of Asclepius who have taken the Hippocratic Oath may perform the Healing Touch miracle and conduct multiple concurrent surgeries. Everyone else is limited to a single surgery step at a time.
  • -
-

nemvar updated:

-
    -
  • Glow will now always be a random color.
  • -
  • Antiglow will now absorb all light equally.
  • -
  • Improved waddling for big things.
  • -
- -

31 May 2020

-

Fikou updated:

-
    -
  • a bunch of items no longer give illegal tech
  • -
-

Helianthus00 updated:

-
    -
  • Fixed the air supply and scrubber pipes to be more neat, as well as fixing a few displaced vents in medbay
  • -
  • removed the double cable on one of the AI upload doors.
  • -
-

MacBlaze1 updated:

-
    -
  • fixed no one showing up on crew monitor or #51332
  • -
- -

30 May 2020

-

ArcaneMusic updated:

-
    -
  • Plant sprites no longer ERROR when just planted.
  • -
-

Kathy Ryals updated:

-
    -
  • The Nanite Programmer and Nanite Program Hub can now be properly deconstructed.
  • -
-

MrDoomBringer updated:

-
    -
  • You should seriously consider playing for over five thousand hours, okay?
  • -
-

Ryll/Shaps updated:

-
    -
  • Characters of "Other" gender can now choose between male and female sprites in their preferences
  • -
-

Shadark updated:

-
    -
  • Plant analyzer can now be used on planted glowshrooms.
  • -
  • Planted glowshrooms are more influenced by their stats.
  • -
  • Planted glowshrooms expand more rapidly, but decay over time.
  • -
- -

29 May 2020

-

ArcaneMusic updated:

-
    -
  • Standard Engineering tools now show up on the player when worn on the belt.
  • -
-

AsphaltEvidence updated:

-
    -
  • added directional sprites to the arcade machines
  • -
  • added directional sprites to the arcade machine screens
  • -
-

MrDoomBringer updated:

-
    -
  • Nanotrasen is pleased to announce that their employee's inner monologues will now be able to properly spell intricacies
  • -
-

Qustinnus updated:

-
    -
  • fixes a critical bug where you couldn't build toilets out of pizza or meat.
  • -
-

TheVekter updated:

-
    -
  • Nanotrasen is experimenting further regarding the interaction between hydrogen and plasma. A new cargo bounty has been added for a single tank of hydrogen.
  • -
  • Centcom no longer needs Phazon mechs delivered to them.
  • -
-

nemvar updated:

-
    -
  • Nerfed the power chromosome + (anti)-glowy mutation
  • -
-

willox updated:

-
    -
  • remove unnecessary var/id from /datum/material
  • -
- -

27 May 2020

-

ArcaneMusic updated:

-
    -
  • Icebox's mining, EVA Exits, and cargo shuttle areas have been adjusted to distinguish them from boxstation.
  • -
  • Adds Liquid Earthquake, a botany biogenerator chem that increases production speed, but increases plant weed susceptibility.
  • -
  • Adds Enduro Grow, a botany biogenerator chem that improves a plant's endurance stat, but decreases it's yield and potency.
  • -
-

ArcaneMusic/Azlan updated:

-
    -
  • Updated the Ancient Spear sprite.
  • -
-

Kathy Ryals updated:

-
    -
  • You can now altClick to take out a disk from a DNA Console.
  • -
-

Krysonism updated:

-
    -
  • fixes the horticultural waders sprite by adding hand holes.
  • -
-

Kurgis updated:

-
    -
  • New mouse detective poster.
  • -
-

LemonInTheDark updated:

-
    -
  • Fixed smallscreen resizing on restart or when you die.
  • -
  • Pixel size and scaling method will properly save now.
  • -
-

MacBlaze1 updated:

-
    -
  • Prevents doomsday activation while shunting and disabled doomsday if a malf shunts after activation.
  • -
  • fixed #50792, also known as the cool amazing bug that makes taking your clothes on and off duplicate an unknown onto the crew monitor program/console/device
  • -
-

Qustinnus updated:

-
    -
  • You can no longer get hardcore random points by joining last second
  • -
-

Ryll/Shaps updated:

-
    -
  • You can no longer shotgun canned beverages
  • -
  • Removed errant TP from the admin full monty
  • -
-

WarlockD updated:

-
    -
  • Fixed the internal to use mask
  • -
  • flag change to the space heater and electrolyzer
  • -
-

actioninja updated:

-
    -
  • missing textures
  • -
-

nemvar updated:

-
    -
  • Scaling methods in the preference menu now have the correct names.
  • -
-

ohnoitsdixie updated:

-
    -
  • Paramedics now have access to the Engineering Foyer, and no longer have to crawl into Engineering through maintenance like filthy assistants.
  • -
-

willox updated:

-
    -
  • Botany grafts for traits other than 'perennial growth' are no longer non-functional
  • -
  • Cross-pollination can no longer result in plants entering an infinitely-harvestable state
  • -
-

zxaber updated:

-
    -
  • Two new apps for modular computers are available: Lifeline for Medical, and Fission360 for anyone with access to the Syndicate repository. Lifeline is an improved suit sensors tracker, and Fission360 is the same but for nuclear-related things.
  • -
- -

26 May 2020

-

Fikou, spookydonut made the glove code sane updated:

-
    -
  • concussive gauntlets! available at your local tendril chest
  • -
  • tendril loot has changed a bit
  • -
  • hulks can now break rocks
  • -
-

JoshAdamPowell updated:

-
    -
  • Simplified granibitaluri recipe
  • -
-

MrDoomBringer updated:

-
    -
  • Reaching legendary levels of any given skill will grant you an otherwise unobtainable reward.
  • -
  • Nanotrasen has recently acquired new software to track employee skill development, straight from your PDA! Check it out! In unrelated news, the rate of summary executions handed out to Nanotrasen's lowest performing employees has risen sharply.
  • -
  • Modify player's skills with the new Skill Panel menu, available from the Player Panel!
  • -
-

Paxilmaniac updated:

-
    -
  • things to the bounty hunter ship that might be important, such as oxygen tanks, and a toolbox, along with two tiny fans in the airlocks
  • -
-

Pumpkinoe updated:

-
    -
  • Added a new large emergency shuttle for purchase at 8000 Cr, the Dynamic Enviornment Interaction Shuttle. Try it out today and frolic with the monkeys!
  • -
-

Ryll/Shaps updated:

-
    -
  • Sleeping carp no longer grants outright damage resistances to all forms of damage. Its price has been decreased to 12TC
  • -
-

TerraGS updated:

-
    -
  • Material containers are better at managing local storage
  • -
-

Timberpoes updated:

-
    -
  • SMES units now self-charge when containing yellow slime cores.
  • -
-

Tlaltecuhtli updated:

-
    -
  • janibelt/medibelt can be opened from backpack
  • -
  • removed some defunct code (picking a color of cable but its all yellow in belt.dm)
  • -
  • bandoliers now hold their intended 18 shells.
  • -
-

WarlockD updated:

-
    -
  • Swapped a few arguments out of the materials container
  • -
-

kevinz000 updated:

-
    -
  • Hierophant now uses its ranged abilities in melee attacks, meaning the strategy of standing still and tanking the hits is no longer viable in 99% of circumstances.
  • -
- -

25 May 2020

-

Cyberboss updated:

-
    -
  • The `notify` TGS command will no longer work if the related config setting is disabled
  • -
  • Fixed not actually limiting chat sends to tagged channels as the config should allow when running under TGS4.
  • -
  • Fixed the `notify` command not working for IRC users.
  • -
-

Fikou updated:

-
    -
  • fixed science glasses recipe using beer goggles instead of science glasses
  • -
-

Gamer025 updated:

-
    -
  • Nanotrasen checked the last few expenses reports and decided to reduce payday spending. Because of this, the salary of all non human employees has been reduced by 25%. Please consult your local Head of Personal for more information.
  • -
-

Kelenius updated:

-
    -
  • Cyborgs (except Peacekeeper and Standard) now have access to their department's radio.
  • -
-

LemonInTheDark updated:

-
    -
  • Changed the way h2o interacts with the engine. It should acts similar to o2 normally, but in high concentrations it cools the engine down. Have fun :)
  • -
  • Mulebots no longer go insane when shit starts to lag
  • -
  • Refactored client.view into a datum, changed some zoom values to work properly
  • -
  • Spinning while using a binocular will work as expected
  • -
  • Fully adds widescreen support to zooming
  • -
  • I've moved the pixel scaling and zoom methods from the menu bar to the game preferences window. You'll need to reset them.
  • -
  • Pixel size will now automatically update on zoom, so you won't end up with ui buttons you can't see.
  • -
  • FIxed the epic gamer skill of binocular applied to advanced camera console
  • -
-

LemonInTheDark, with thanks to ArcaneDefence for the pointer updated:

-
    -
  • Scrubbers no longer cool pipenets attached to them when scrubbing space
  • -
-

MarioWizard119 updated:

-
    -
  • Synthflesh now also works via vapor.
  • -
-

NewSta updated:

-
    -
  • You might potentially see better a/an usage
  • -
-

Ryll/Shaps updated:

-
    -
  • You can now use ! and ? at the end of 'spawn' chatbar verb commands to search for only the ends of paths, or to automatically select a random type of the paths your search returns! Happy badminning!
  • -
  • Adds a config option for OOC kindness commendations! When enabled, a small percentage of the crew gets asked if anyone made their round better, and those people will get a little heart next to their name in OOC for 24h!
  • -
  • lobby menu work again
  • -
-

Shadark updated:

-
    -
  • Manually printed barcodes are now working correctly.
  • -
-

TetraK1 updated:

-
    -
  • Ghosts can no longer control atmos stuff with alt/ctrl click.
  • -
  • Added logging to ctrl/alt clicks on atmos stuff
  • -
-

TheVekter updated:

-
    -
  • Nanotrasen's export price for Hydrogen no longer violates the basic rules of supply and demand.
  • -
-

actioninja updated:

-
    -
  • smon,k weed
  • -
-

antropod updated:

-
    -
  • Fix PanDEMIC 2200 not showing Blood DNA and Blood Type
  • -
-

kevinz000 updated:

-
    -
  • dir_inverse_multiz() should work now. should.
  • -
-

nemvar updated:

-
    -
  • The camera console looks fancier now.
  • -
-

qustinnus updated:

-
    -
  • you can no longer move up when you are going to fall down anyways, or you know, dead.
  • -
  • simple multi-z audio
  • -
-

spessman-007 updated:

-
    -
  • Quite a few misspellings have been corrected
  • -
-

tralezab updated:

-
    -
  • anomaly crystal theme warping for the jungle now uses wooden walls instead of sandstone ones
  • -
-

wesoda25 updated:

-
    -
  • The progress bar for butchering large mobs is no longer offset.
  • -
-

zxaber updated:

-
    -
  • Explosions that were able to destroy doors before will now rip them from the universe.
  • -
- -

24 May 2020

-

Cobby updated:

-
    -
  • Dissection will now give XP instead of research points.
  • -
-

Fikou updated:

-
    -
  • admins can now do html in ahelps properly
  • -
-

qustinnus updated:

-
    -
  • Fixes you being able to put in more than one license plate in the license plate machine
  • -
- -

22 May 2020

-

ArcaneMusic updated:

-
    -
  • Adds a new assembly component, the freezer, for gradually making the environment colder.
  • -
-

Dorsidwarf updated:

-
    -
  • Swarmer structures are no longer broken.
  • -
-

Fikou updated:

-
    -
  • you can no longer inject html in ahelps
  • -
  • you cant either, jannies
  • -
-

Ghilker updated:

-
    -
  • Cryotubes can no longer reach fusion level heat
  • -
  • Cryotubes breakdown if the heat inside is higher than 2000 K
  • -
  • Cryotubes extinguish the mob if on fire
  • -
-

Mickyan updated:

-
    -
  • Fixed missing icon on wigs
  • -
-

Whoneedspacee updated:

-
    -
  • Icebox Station has been added, explore the depths of the Ice Moon with boxstation right on top of it, don't forget your coat and internals!
  • -
  • You can now mine rock flora into volcanic ash to make glass.
  • -
-

kevinz000 updated:

-
    -
  • Circlegame items now properly delete on drop and can't be made with full hands.
  • -
-

wesoda25 updated:

-
    -
  • fixes a misspelled xenobiology sign
  • -
-

willox updated:

-
    -
  • diseases now retain the ability to infect people after having 'inorganic biology' or 'necrotic metabolism' removed from them
  • -
- -

20 May 2020

-

Skoglol updated:

-
    -
  • Another dynamic rolling restricted roles as antags fix.
  • -
-

Thebleh updated:

-
    -
  • Fixes MetaStation's disposals
  • -
-

dootdoom updated:

-
    -
  • Straight Jacket now has bigger bolder red text to alert you someone is putting it on you.
  • -
- -

17 May 2020

-

Nebulacrity for the sprites, LemonInTheDark for chopshop job updated:

-
    -
  • Adds proper inhands to the singularity hammer, take a look, they're pretty neat.
  • -
- -

15 May 2020

-

PKPenguin321 updated:

-
    -
  • You can no longer cheat at becoming a legendary gamer by committing suicide a lot in Orion Trail.
  • -
-

nemvar updated:

-
    -
  • Clicking links in goonchat will no longer eat your next input.
  • -
- -

13 May 2020

-

ATHATH updated:

-
    -
  • (web) edits some soulstone messages
  • -
-

Fikou updated:

-
    -
  • you can now stroke heads with a bangammer in peace
  • -
-

Inept updated:

-
    -
  • "Devil, just come on back now if you ever want to try again, I told you once, you son of a bitch, I'm the best there's ever been."
  • -
-

ThePainkiller updated:

-
    -
  • Adds Gastrectomy, a surgery for healing damaged stomachs.
  • -
-

rdragan updated:

-
    -
  • Power has been restored to Pubby's Medbay
  • -
- -

12 May 2020

-

Rodey125 updated:

-
    -
  • gumballs and spider lollipops are now a subtype of chewables
  • -
-

TheVekter updated:

-
    -
  • The Clarke's weight has been reduced, causing it not to break floor tiles anymore.
  • -
- -

11 May 2020

-

LemonInTheDark updated:

-
    -
  • Dear out of date coders, you will now be yelled at to update to the correct version of byond, rather then an unsupported one.
  • -
-

Naksu updated:

-
    -
  • Lighting corner updates are ever so slightly faster.
  • -
-

antropod updated:

-
    -
  • Chemical Press can now make patches and bottles
  • -
-

nemvar updated:

-
    -
  • Fixed a lot of broken sprites.
  • -
- -

10 May 2020

-

Couls updated:

-
    -
  • Give item keybind, default to G. Press it while holding an item to offer it to someone nearby, they can click the alert they get to accept it or move for it to go away
  • -
  • There is a right click menu option for giving
  • -
-

Fikou updated:

-
    -
  • the lord singulo syndie kit now has a mining id upgrade and a 10000 credits so you can actually bother with getting a singulo running
  • -
-

Inept updated:

-
    -
  • The Nanotrasen Entertainment Division would like to remind everyone that any resemblance Kotahi bears to any other card game, real or fictional, is a coincidence. Kotahi is legally distinct.
  • -
  • removed some old sprites they're unimportant please don't look
  • -
-

MMMiracles updated:

-
    -
  • Boxstation's AI core was moved back into the original position just below the bridge.
  • -
  • Boxstation's gravity generator was moved to the left of Engineering, accessed through the main Engineering section.
  • -
-

MacBlaze1 updated:

-
    -
  • Security PDA's now come with the Crew Manifest Program
  • -
  • fixed lesser form transformation not transferring stamina damage
  • -
-

Mickyan updated:

-
    -
  • empath quirk can now sense abnormal body temperature on examine
  • -
  • lowered the mood malus from examining people with low sanity as an empath
  • -
  • bubble gum lasts much longer
  • -
  • improved bubble gum sprites
  • -
-

Nebulacrity for the sprites, LemonInTheDark for the mule work updated:

-
    -
  • Improved on the singularity hammer, drop it on the ground and mire the way she shines.
  • -
-

NoxVS updated:

-
    -
  • Nanotrasen has (once again) discovered which direction is left and right, and have fixed the remaining cyborg limbs.
  • -
-

Paxilmaniac updated:

-
    -
  • icon for techpriest hood
  • -
-

Qustinnus updated:

-
    -
  • some ebic new lavaland ambience tracks.
  • -
-

Qustinnus & MrDoomBringer updated:

-
    -
  • Adds hardcore random mode, you get a random character with some random bad quirks. You can earn hardcore random score and get on the leaderboards if you survive and get on the shuttle. If the odds are stacked against you more, you will also earn more points.
  • -
  • Gold wheelchair, only for people with 5k hardcore random mode points
  • -
-

Ryll/Shaps updated:

-
    -
  • Projectiles with shrapnel now embed in the same limb they hit
  • -
-

Shadark updated:

-
    -
  • Contraband items in vending machines now display their correct price.
  • -
  • MULEbots can't be used as steamrollers anymore.
  • -
-

Skoglol updated:

-
    -
  • Dynamic config no longer overwrites ruleset restricted roles.
  • -
-

SteelSlayer updated:

-
    -
  • Fixed the recharger's sprite turning invisible when a screwdriver was used on it
  • -
-

TemporalOroboros updated:

-
    -
  • Plant grafts now work after their parent plant has been deleted.
  • -
  • Hydroponics trays now obey transfer amounts when dealing with water.
  • -
-

TerraGS updated:

-
    -
  • Potato Batteries display properly now
  • -
-

Thebleh updated:

-
    -
  • Metastations 'N2 to Pure' pump is now off by default
  • -
-

Timberpoes updated:

-
    -
  • Nanite Cloud Controllers now display stored rules for programs without requiring specific disks inserted.
  • -
-

TiviPlus updated:

-
    -
  • Kotahi decks will now Shuffle properly
  • -
-

XDTM updated:

-
    -
  • Abductor healing glands now properly check organ damage when detecting which organs to replace.
  • -
  • Abductor healing glands can now replace damaged stomachs and inflamed appendixes.
  • -
  • Abductor healing glands now also reject implants (like mindshield implants) on top of cybernetic organs.
  • -
-

actioninja updated:

-
    -
  • Fallback order of on mob icons was changed to match older versions, correcting some issues with missing sprites
  • -
-

dootdoom updated:

-
    -
  • Cargo supply console is now next to the supply shuttle on box and pubby.
  • -
-

spessman-007 updated:

-
    -
  • Removed unused files
  • -
-

vuonojenmustaturska updated:

-
    -
  • Cleaned up porta-turret code ever so slightly
  • -
- -

09 May 2020

-

RaveRadbury updated:

-
    -
  • light tiles are less picky about how you hold the multitool
  • -
  • Health Analyzers only detect Major Disabilities, rather than all quirks
  • -
  • Advanced Health Analyzers can detect Minor Disabilities as well
  • -
-

Ryll/Shaps updated:

-
    -
  • The INTERACTING_WITH macro now tracks all kinds of do_after
  • -
-

Skoglol updated:

-
    -
  • Trash bags can no longer be equipped on belt.
  • -
-

TheVekter updated:

-
    -
  • Removed the ability to print mini meteor toys from the autolathe and obtain them from cargo crates.
  • -
-

nemvar updated:

-
    -
  • Staff of nothing now shoots nothing.
  • -
  • Wand of nothing shoots nothing again, instead of doing nothing.
  • -
- -

08 May 2020

-

LemonInTheDark updated:

-
    -
  • Added Psychologist features to the SM
  • -
-

Tlaltecuhtli updated:

-
    -
  • fermenter plumbing machine
  • -
  • bottler plumbing machine
  • -
-

WarlockD updated:

-
    -
  • Fixed extractor and tgui
  • -
  • Ran webpack so it would work:P
  • -
-

redguy999 updated:

-
    -
  • Space dragons are now large mobs
  • -
- -

07 May 2020

-

Cartographer-D updated:

-
    -
  • The new isolation cell on Meta now has an observation monitor.
  • -
  • The floor safe in Meta Maintenance now has a nice treat!
  • -
  • Meta's prison and cargo have been touched up even more!
  • -
-

Fikou updated:

-
    -
  • new colossus sprites
  • -
-

Qustinnus (sprites from Lohikar) updated:

-
    -
  • Open-space now has a parent /transparent/ that handles the visuals of open-space besides the backdrop
  • -
  • Glass floors and reinforced glass floors. Look at those peasants down below in style.
  • -
-

Qustinnus, AnturK updated:

-
    -
  • Moved gun overlay updating to update_overlays(), removing lag from objects when you add a flashlight / baynonet to them
  • -
-

uomo91 updated:

-
    -
  • Metastation now has a science wardrobe vendor.
  • -
-

willox updated:

-
    -
  • unique combinations of custom_materials lists are now shared between objects
  • -
-
- -GoonStation 13 Development Team -
- Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
- Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No
-
-
-

Creative Commons License
Except where otherwise noted, Goon Station 13 is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
Rights are currently extended to SomethingAwful Goons only.

-

Some icons by Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 License.

-
- - + + + + /tg/ Station 13 Changelog + + + + + + + +
+ + + + +
+
Traditional Games Space Station 13
+ +

+ Join our Discord channel +
+ + + + + +
+ Current Project Maintainers
+ Recent GitHub contributors
+ Thanks to: Baystation 12, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original Space Station 13 developers, Invisty for the title image and the countless others who have contributed to the game, issue tracker or wiki over the years. +
Have a bug to report?
Visit our Issue Tracker.
+ Please search first to ensure that the bug has not already been reported. +
+ + +
+

13 July 2020

+

Tlaltecuhtli updated:

+
    +
  • monkey caps drop on the floor if no ghosts got polled
  • +
+ +

12 July 2020

+

ATHATH updated:

+
    +
  • To sacrifice someone on a sacrificial altar (such as the ones found in the healing fountain ruin), you must now alt-click the altar, not normal-click it. The default descriptions of sacrificial altars have been updated accordingly.
  • +
+

Alterist updated:

+
    +
  • Upgraded Cybernetic Lungs (Tier3) now have improved oxygen absorption, same as Cybernetic Lungs (Tier2)
  • +
  • Added 3 tier of Cybernetic Stomachs, researchable by R&D and buildable in the Medical Lathe.
  • +
+

Angust updated:

+
    +
  • fixed space vines / kudzu growing slower from better (lower) production speed
  • +
  • random event space vines buffed to have 1-6 production instead of 5-10 to compensate
  • +
+

ArcaneMusic updated:

+
    +
  • Icebox Maintenance, and Icebox Service Hallway have been rearranged to be more spacious.
  • +
  • Bounty boards are properly responsive, and are mapped on icebox dorms as intended.
  • +
+

Dennok updated:

+
    +
  • Separate BLOCK_Z_FALL flag to BLOCK_Z_OUT_DOWN, BLOCK_Z_OUT_UP, BLOCK_Z_IN_DOWN, BLOCK_Z_IN_UP
  • +
  • Now lattice can support spaceman
  • +
  • Catwalk block uplifting from below
  • +
  • now posting in shuttle propertly fails
  • +
+

EdgeLordExe updated:

+
    +
  • Voiceless dead are now longe INVISIBILITY_ABSTRACT, god i hate bugs
  • +
  • Ascension will make you greentext
  • +
+

Fikou updated:

+
    +
  • Bounty hunter hat sprite works again.
  • +
+

Jay Smith & MrDoomBringer updated:

+
    +
  • Replaced faulty sprites for various bags and the Portable Chemical Mixer in the belt slot
  • +
  • Replaced the DNA probe's old sprite (Hypospray) with a unique sprite
  • +
  • New icon and sprites for the DNA probe
  • +
  • Belt sprites for the Portable Chemical Mixer and various bags
  • +
+

Kathy Ryals and ArcaneMusic updated:

+
    +
  • Plant mutation chances at 80+ instability is now a sliding scale.
  • +
+

LemonInTheDark updated:

+
    +
  • The tesla/sm will ground bolts less jankilly now
  • +
  • Wires will no longer burn if they're under a tile that's on fire
  • +
  • Reinserted some old checks for if something is over/under a tile
  • +
+

LoserWasTaken updated:

+
    +
  • blood cleave does only one wound instead of 3 now
  • +
+

Maurukas updated:

+
    +
  • Added reconstructive surgery for moth wings, requiring synthflesh
  • +
  • Magical healing and aheals now restore moth wings
  • +
+

Melbert updated:

+
    +
  • Fixes railings blocking bullets and immovable rods from a certain direction.
  • +
+

MrDoomBringer updated:

+
    +
  • Nanotrasen's Transportation and Logistics Subdivision has spent the better part of their budget developing a brand new model of Supplypod. Internal investigations have revealed the only real differences are almost purely aesthetic.
  • +
+

Ryll/Shaps updated:

+
    +
  • As an admin ghost, examining another ghost twice quickly will pull up clickable links to their info in chat
  • +
  • Examining someone who has examined you within the last second will give you both a small message saying you made eye contact. Having your face obscured by a helmet or mask will prevent the other person from noticing, no matter who looked first.
  • +
  • Those with social anxiety may find eye contact to be stressful, and those who foster unhealthy obsessions over other crewmembers may outright staredown their prey.
  • +
  • Throwing people really hard into vending machines is not advised if you don't want to clean them up afterwards. Things are considered thrown really hard if: You're throwing them as a hulk, the person you're throwing is a dwarf, and/or if you're throwing someone from a neckgrab
  • +
  • You can now adjust the speed disposal outlets eject contents at with a multitool, and emag the disposal outlet to amp the speed up even further!
  • +
  • Player controlled medbots are no longer permanently crippled when tipped over
  • +
  • New admin smite for knotting someone's shoes if possible
  • +
+

ShizCalev updated:

+
    +
  • Fixed radiation immune mobs getting irradiated.
  • +
  • Plasmamen who have acquired the fireproofing trait will no longer get spammed with messages saying they caught on fire.
  • +
  • Stacks will now update properly when you varedit their amount. It's clamped to max_amount, so make sure to change that too if you want to increase the amount beyond it.
  • +
  • Fixed some constant runtime spam when defib rechargers had their defib destroyed.
  • +
  • Fixed a minor runtime when examining paper twice.
  • +
  • Cleaned up arcade machine examine-more messages a little.
  • +
  • Map placed headpikes will now have heads... and pikes!
  • +
  • Fixed headpikes having the wrong mob name.
  • +
  • Fixed a minor runtime when removing a monkey's sentience helmet.
  • +
+

Skoglol updated:

+
    +
  • Parrot possession now works.
  • +
  • Fixed some glowshroom runtimes.
  • +
  • Wendigo no longer spams admin messages.
  • +
+

Tlaltecuhtli updated:

+
    +
  • conveyor switches now have a wire that can be pulsed with signalers/other assemblies to active it
  • +
+

Wayland-Smithy updated:

+
    +
  • Resource and Factory Blobs can only be placed on station where they count towards critical mass.
  • +
+

YPOQ updated:

+
    +
  • Fixed an issue that prevented AIs from tracking players in areas they have not yet viewed.
  • +
+

silicons updated:

+
    +
  • cameras no longer crash the server
  • +
+

tralezab updated:

+
    +
  • Fixed up Mafia maps, at least in all the ways I caught!
  • +
  • mind mag helms losing their icon sometimes
  • +
+

uomo91 updated:

+
    +
  • You can now leave Metastation's medbay after being treated without bugging a doctor to let you out.
  • +
+ +

11 July 2020

+

ShizCalev updated:

+
    +
  • Fixed the field generators in Delta's Singulo area being anchored but not secured.
  • +
  • Fixed field generators continuing to function after being uprooted by a mob.
  • +
+

Timberpoes updated:

+
    +
  • Fix being unable to orbit player characters and antags from the observer orbit menu.
  • +
+

nemvar updated:

+
    +
  • Barrel melon description now makes a bit more sense now.
  • +
+

tralezab updated:

+
    +
  • Cargo can purchase monkey sentience helmets under the science tab!
  • +
+ +

09 July 2020

+

EdgeLordExe updated:

+
    +
  • You can no longer infinitely spawn heretics summons
  • +
+

Jared-Fogle updated:

+
    +
  • Added surgery related unit tests and adds TEST_ASSERT, TEST_ASSERT_EQUAL, and allocate to unit tests.
  • +
+

Melbert updated:

+
    +
  • Fixes an infinite loop / infinite camera shake in the Bubblegum hallucination
  • +
+

Timberpoes updated:

+
    +
  • Ghost orbit menu can now orbit things with weird metadata in their names like medibots and MULEBOTs.
  • +
  • Ghost orbit menu search bar looks prettier.
  • +
  • Ghost orbit menu no longer auto-closes when you select something to orbit. Indirectly buffs voyeurs.
  • +
+

nightred updated:

+
    +
  • fixed destructive analyzer item visual not being removed when destroying items
  • +
+

zxaber updated:

+
    +
  • Borg machine conveyance has been repaired, to the delight of any "alternative"-functioning AIs that wish to onboard new silicon employees.
  • +
+ +

08 July 2020

+

ArcaneMusic updated:

+
    +
  • The bounty board has been added to all standard NT stations, for making and paying out bounties for credits made by crew members across the station. Available as a standalone machine, as well as a modular app.
  • +
+

Fikou updated:

+
    +
  • fixes labor camp beacon sprite
  • +
  • manly dorf now doesnt turn on dorf mode with alcohol tolerance
  • +
+

FloranOtten updated:

+
    +
  • Space Cops now come equipped with appropriate environmental protection.
  • +
+

Jared-Fogle updated:

+
    +
  • Fixed cryo cells locking up those with prosthetic limbs.
  • +
  • Fixes tend wounds not healing and brain surgery not curing traumas.
  • +
+

Melbert updated:

+
    +
  • Mech vs Mech combat system for toy mechs! Hit a toy mech with another toy mech, or attack a player holding a toy mech with a toy mech, and you can initiate battle between toys!
  • +
  • Each toy mech now has its own health stat and special attack move for use in mech vs mech combat. Discover them all!
  • +
  • Suicide act for mech toys. If you wanted to take part in the toy mech battles yourself.
  • +
+

ShizCalev updated:

+
    +
  • Added more examine text to bots.
  • +
  • Fixed player controlled statues being able to speak.
  • +
  • Fixed nonhuman that aren't able to speak being able to cast spoken spells
  • +
  • Fixed a minor runtime caused by removing a laser pointer's diode while it's still turned on.
  • +
+

Tlaltecuhtli updated:

+
    +
  • votes now play a beep noise when they get started
  • +
+

Wayland-Smithy updated:

+
    +
  • Blob mobs from an overmind now see critical mass progress as a status.
  • +
+

oranges updated:

+
    +
  • Where some names might previously have been accepted, they will now be rejected, this should not affect any regular names in use
  • +
+

tralezab updated:

+
    +
  • Removes the 9 assistants 3 changeling setup, yech.
  • +
  • Lotta bugfixes for mafia!
  • +
  • Mafia now alerts you when starting a game!
  • +
  • grammar + better text for some roles at better times of the game
  • +
  • LET THERE BE MAFIA DOCUMENTATION!
  • +
+ +

07 July 2020

+

ATHATH updated:

+
    +
  • The description of eldritch essence has been modified to make what it actually does more clear.
  • +
  • Eldritch essence and unholy water both now actually use the metabolization_rate variable.
  • +
+

ArcaneMusic updated:

+
    +
  • Added a new mutation of geraniums, called Fraxinella, AKA Burning Bush.
  • +
  • Added a new mutation of watermelon, called Barrel Melon, which has the new trait Auto-Distilling Composition. (Sprite provided by Kryson)
  • +
  • Walking Mushrooms now have a new graftable gene, Occulary Mimicry.
  • +
+

EdgeLordExe updated:

+
    +
  • Nitric acid is slightly better
  • +
  • Meat hook is now a 11tc cook traitor item. It can no longer be aquired from necropolis chests. sorry miners!
  • +
+

Fikou updated:

+
    +
  • servicelathe can now print airlock painters, decal painters and spraycans
  • +
  • explorer suits now have space suit level heat protection
  • +
+

Jared-Fogle updated:

+
    +
  • Donut boxes will now accurately show what donuts are inside.
  • +
  • Fixed a bug where when teleporting naturally (such as going through a z-level in space), if you were pulling someone that was then pulling another person, only you and the person you were pulling would make it through.
  • +
  • Removed the healing skill, and by effect dissection surgery and the legendary healer's cloak.
  • +
+

Jay Smith updated:

+
    +
  • The Portable Chemical Mixer now uses proper vortex anomaly cores instead of raw ones.
  • +
+

Kathy Ryals updated:

+
    +
  • Nanotrasen finally realized they forgot to ship the mandatory anomaly compressor and two anomaly cores to Icebox.
  • +
+

LemonInTheDark updated:

+
    +
  • Removed the research modes from tesla coils and radiation collectors.
  • +
+

Orchian updated:

+
    +
  • Added a new traitor item for HoP and QM, the OCD
  • +
+

ShizCalev updated:

+
    +
  • Fixed gas canisters having a misplaced flashing icon when they are close to empty.
  • +
  • Fixed inducers not working on a couple items with internal powercells.
  • +
  • Fixed a scenario where mobs would accidentally be kicked off a vehicle if they were handcuffed.
  • +
  • Added support to kick a mob off a vehicle if the vehicle is restrained.
  • +
  • You can now unlock bots by alt-clicking them when their maintenance panel is open.
  • +
  • Optimized a good chunk of MULEbot code, fixing things such as it rebuilding it's overlays/icons 5 times every second while moving to a destination. Less free lag!
  • +
  • Fixed MULEbots closing crates when the crate doesn't actually get loaded onto it.
  • +
  • Fixed the maintenance hatch on MULEbots visually closing for a moment when emagged.
  • +
  • Paranormal MULEbots will no longer briefly turn into a normal MULEbot when emagged.
  • +
  • Fixed interface exploits involving paranormal MULEbots carrying ghosts.
  • +
  • Fixed MULEbot blood tracks sometimes facing the wrong direction.
  • +
  • Player controlled MULEbots will now leave bloody tracks if they've run over a mob.
  • +
  • Fixed players riding MULEbots sometimes appearing underneath it instead of ontop of it.
  • +
  • Fixed AI's making a chiming noise when they receive a remote notification from a MULEbot. Now only the AI will hear the notification's sound.
  • +
  • Fixed MULEbots dropping mobs off at their current location instead of at their dropoff point.
  • +
  • Fixed a minor runtime related to MULEbots dropping off deleted items/mobs.
  • +
  • Fixed mobs having the wrong height offset when riding MULEbots.
  • +
  • Fixed mobs sometimes ending up underneath MULEbots while riding them.
  • +
  • Fixed mobs not falling off MULEbots when stunned / incapacitated.
  • +
  • Fixed inducers not recharging MULEbots.
  • +
  • Fixed MULEbots leaving bloody tracks in space.
  • +
  • Fixed MULEbots leaving multiple blood tracks in the same spot if they failed to move.
  • +
  • Fixed hacked MULEbots spamming messages about knocking down a mob when they didn't actually do it.
  • +
  • Fixed MULEbot commands not resetting when they were turned off.
  • +
  • Fixed MULEbots not turning off properly when their maintenance hatch is opened.
  • +
  • Fixed MULEbots not turning off properly when they ran out of power while moving.
  • +
  • Fixed MULEbots flashing their external warning lights while they're turned off when their avoidance wire is cut.
  • +
  • Fixed mobs being able to walk right over MULEbots when they turn off.
  • +
  • MULEbots will now try to put their powercell in your hands when you remove them with a crowbar.
  • +
  • Fixed the interface for MULEbots briefly looking like you turned it on successfully even though it was out of power.
  • +
  • MULEbots will now provide feedback if they fail to turn on due to their maintenance panel being open.
  • +
  • MULEbots will no longer flash and beep when their wires are pulsed if they don't have power.
  • +
  • MULEbots will now actually flash when their external warning lights are pulsed.
  • +
  • MULEbots will now flash when they beep / buzz.
  • +
  • Added a bit more examine text to MULEbots.
  • +
  • Fixed an exploit involving coins and mints that could crash the server.
  • +
  • Fixed buckled mobs sometimes appearing over what they're buckled to.
  • +
  • Renamed the "Paranormal MULEbot" to simply, "GHOULbot".
  • +
  • L6 Saw's inhands work again.
  • +
  • Fixed a couple exploits involving the L6.
  • +
  • Guns with a magazine + a round in the chamber won't appear empty anymore.
  • +
  • Energy based guns are no longer missing textures when worn.... Again.
  • +
  • Touched up and added a few worn / inhand icons for some energy based guns.
  • +
+

TetraZeta, NecromancerAnne updated:

+
    +
  • A new sprite for the Marisa outfit.
  • +
+

TheVekter updated:

+
    +
  • NT has approved orders for all members of Cargo to spawn with NTOS-capable tablets.
  • +
+

bobbahbrown updated:

+
    +
  • AI laws no longer include HTML on tgui displays
  • +
+

nightred updated:

+
    +
  • Service hall's deliveries windoor access has been fix
  • +
+

zxaber updated:

+
    +
  • The thermal vision modules found on certain Syndicate cyborgs is functional once more.
  • +
+ +

06 July 2020

+

ATHATH updated:

+
    +
  • The default chem capacity of most grown plants is now 100u.
  • +
+

Anturk + Arm + other summer ball contributors code, trollbreeder + fikou + jerryderpington mapping updated:

+
    +
  • Mafia minigame added for ghosts
  • +
+

ArcaneMusic updated:

+
    +
  • Vend-A-Trays are now operated through a UI.
  • +
+

Arkatos updated:

+
    +
  • Jukebox now uses tgui.
  • +
  • You can now set a volume of a jukebox songs.
  • +
+

Disco updated:

+
    +
  • [Icebox] SM exterior cooling pipes have had unnecessary thermal shielding removed
  • +
+

EdgeLordExe updated:

+
    +
  • Added Extreme Medcine Allergy, a new quirk that gives you 2 points!
  • +
  • CHEMS METABOLIZE AGAIN
  • +
+

Inept, KathyRyals updated:

+
    +
  • A few minor map fixes, hot from the oven.
  • +
+

Jay Smith & Michael Trauf updated:

+
    +
  • Portable Chemical Mixer (Requires a vortex anomaly core to activate)
  • +
  • Unique sprites for the Portable Chemical Mixer
  • +
  • Added Portable Chemical Mixer to the Medical Techfab
  • +
+

LemonInTheDark updated:

+
    +
  • Contaminated objects will now glow bright green until cleaned, remember to quarantine rouge free golems.
  • +
  • Buffed rad goggles in general, the text lasts longer, is brighter, and will show more then twice as far away
  • +
  • Fixed the text from radiation goggles not showing above mobs
  • +
  • The APC control console is now tgui rather then html. It should be a lot more usable. I've made other changes, you won't notice.
  • +
+

Melbert updated:

+
    +
  • Brain Tumor damage is now paused when in stasis.
  • +
  • Brain Tumor damage is now paused when having Mannitol metabolizing in you.
  • +
  • Brain Tumor quirk users will now spawn with a pill bottle containing 4 x 5u Mannitol pills.
  • +
+

MrDoomBringer / Ryll-Ryll updated:

+
    +
  • Admins can now add shrapnel clouds of any projectile they desire to supplypods launched with the Config/Launch Supplypod menu!
  • +
+

Ryll/Shaps updated:

+
    +
  • Bubblegum and Legion can no longer cause wounds, as intended
  • +
+

ShizCalev updated:

+
    +
  • Fixed a few awkward messages related to igniting items.
  • +
  • Info messages are now slightly brighter than notification messages when using dark mode.
  • +
+

Skoglol updated:

+
    +
  • BoxStation has been removed in favor of IceBox.
  • +
+

Timberpoes & Kathy Ryals updated:

+
    +
  • The Bluespace Locator now uses TGUI.
  • +
+

Wayland-Smithy updated:

+
    +
  • New alien larva spawn tips!
  • +
  • Alien Queens are now easier to distinguish over hivemind communication similar to a Blob Overmind.
  • +
+ +

05 July 2020

+

Caldony updated:

+
    +
  • the damp rag can now clean microwaves!
  • +
+

Disco updated:

+
    +
  • Miners can now open doors and cabinets in luxury bar capsules they purchase
  • +
+

Firecage updated:

+
    +
  • The reading rooms on Metastation has been renovated into a small art gallery.
  • +
+

Fox McCloud updated:

+
    +
  • Fixes station alert consoles not properly displaying alerts
  • +
+

Iatots updated:

+
    +
  • Traitorous research directors can now order the laser arm implant from their uplink, like roboticists.
  • +
+

LemonInTheDark updated:

+
    +
  • The sm will no longer gain eer when hugboxed, such as on shuttles.
  • +
  • Added some more hugbox flags, use as desired.
  • +
+

XRandomXManX updated:

+
    +
  • When further examining a battle arcade machine it will display all the combos that can be used.
  • +
+

anconfuzedrock updated:

+
    +
  • cargo cases don't let you buy 3 guns for literally cheaper than buying a bulk crate with the guns in them any more.
  • +
+

nightred updated:

+
    +
  • Meta Bar counters are tweaked in placement
  • +
  • Cold rooms are now cold, no longer arctic conditions.
  • +
+ +

04 July 2020

+

ArcaneMusic updated:

+
    +
  • Plants with over 100% reagent genes now split up their reagents between all available chemicals.
  • +
  • Plants now correctly apply percentages of reagents to a plant's overall reagent capacity.
  • +
  • Densified Chemicals now causes plants to produce half the yield, while still produces double capacity plants.
  • +
  • The richest crew account on station is now showcased on the round-end window! Flex on your coworkers!
  • +
  • Economy Logging now totals how much money the crew had at round-end.
  • +
+

Tlaltecuhtli updated:

+
    +
  • the chamaleon stamp can now stamp cardboard into syndiboxes
  • +
+

ivanmixo updated:

+
    +
  • You can now check yourself for injuries while handcuffed
  • +
+ +

03 July 2020

+

Jared-Fogle updated:

+
    +
  • Changed the configuration to enable moths by default, rather than being commented out.
  • +
  • Updated defibrilator mount description to remove line about being immovable.
  • +
  • You can now place people you are fireman carrying onto morgue trays.
  • +
  • You can now place people you are fireman carrying onto objects that buckle players.
  • +
+

ShizCalev updated:

+
    +
  • Jaunting mobs can now travel over bar tables.
  • +
  • Fixed an invisible cable stack on derelict.
  • +
+

WarlockD updated:

+
    +
  • Your suit now washes under the shower
  • +
  • Sink now cleans properly
  • +
+

bobbahbrown updated:

+
    +
  • Jannies rejoice, the sanitation department has developed a new experimental broom module for our robotic cleaning friends. Ask your roboticist for a broom upgrade today!
  • +
+

zxaber updated:

+
    +
  • Hulks now take damage to their arms for smashing walls and machines. You won't get through very many walls before you have to visit medical, though the damage for punching an airlock is quite a bit less.
  • +
+ +

01 July 2020

+

ATH1909 updated:

+
    +
  • Freon's warning message no longer depends on the presence of nitryl in your lungs.
  • +
+

ATHATH updated:

+
    +
  • The medbot on the library ship is now special.
  • +
  • The damage taken from being thrown into a wall should now use the same wound_bonus value as the damage you'd take from being thrown into a human would use.
  • +
+

Melbert updated:

+
    +
  • Blind people can now feel when they're being hugged and shaken. Go hug your local blind person today.
  • +
+

TaF updated:

+
    +
  • Adds an invisible/hidden icon that can be used for items that may not be in need of a sprite.
  • +
  • Weapons sawn off show a worn icon after being sawn.
  • +
  • Energy weapons properly show ammo depletion when worn. Icons for this are still a work in progress.
  • +
  • Fixes neckerchief icon overlay issue.
  • +
  • Fixes nanite scanner in_hand icon.
  • +
  • Fixes 23 items with common worn icons.
  • +
  • Removes duplicate null icon in back slot icon file
  • +
+

Wayland-Smithy updated:

+
    +
  • Revenants, being spirits, can now hear ghost gang banter.
  • +
  • Revenant speech color is now readable when using Darkmode.
  • +
+

carshalash updated:

+
    +
  • Causes the reactive spine blob type to retaliate to bun as well as brute damage
  • +
+

ivanmixo updated:

+
    +
  • You can no longer take your ID out while unconscious or in soft crit
  • +
+

nightred updated:

+
    +
  • Meta bar tables are not that metal
  • +
+ +

30 June 2020

+

ATH1909 updated:

+
    +
  • The messages from attempting to feed someone the contents of a glass container (including, say, disease bottles or vaccine bottles) will now mention the name of the aforementioned container.
  • +
+

Arkatos updated:

+
    +
  • All Abductor machines now use tgui.
  • +
+

Iatots updated:

+
    +
  • runtime station has a small genetics section now
  • +
  • runtime station doesn't run out of power anymore
  • +
+

Ryll/Shaps updated:

+
    +
  • Fixed an issue with Nuke Ops tablets being invisible
  • +
+

ShizCalev updated:

+
    +
  • Fixed newspapers not being flammable.
  • +
  • Standardized how paper products are burned. You're now able to ignite newspapers, folders, and photographs with lights/welders/hot stuff!
  • +
  • Igniting a piece of paper will no longer cause it to teleport to your feet.
  • +
  • Fixed some paper interactions not leaving fingerprints on the object.
  • +
+

WarlockD updated:

+
    +
  • Medical Kiosk shows rad contamination
  • +
  • Medical Kiosk gives better directions on rad sickness
  • +
+

sprites, Edge code updated:

+
    +
  • Codex cicatrix now looks a lot better
  • +
+ +

29 June 2020

+

FloranOtten updated:

+
    +
  • Nanotrasen Scouting forces have recently reported being shot at by an old man in a shack. Watch out for any strange log cabins!
  • +
+

ShizCalev updated:

+
    +
  • Fixed pamphlets having the wrong icon.
  • +
  • Fixed pamphlets and a couple of guides never showing that they're on fire.
  • +
  • Paper will no longer infinitely add new fire overlays while they're on fire.
  • +
  • Paper planes will now use the proper icon while on fire.
  • +
  • Added support for custom fire overlays for objects. Set the custom_fire_overlay var to change it!
  • +
+

anconfuzedrock updated:

+
    +
  • ninja dashes recharge 5x as slow, but they all recharge at the same time.
  • +
  • ninjas are slightly less the definition of speed. They're also faster when their suit is depowered I guess.
  • +
+

and KathyRyals updated:

+
    +
  • Nanotrasen found out about the amount of expensive chemicals served in survival medipens and cut them down to safe costs...
  • +
  • ...And they turned the old medipen into a luxury
  • +
  • Lavaland Extract was found to break laws of physics and was removed from existance
  • +
+ +

28 June 2020

+

ATHATH updated:

+
    +
  • Fixed n2o knocking out players for longer than expected.
  • +
+

ArcaneMusic updated:

+
    +
  • Adds the Cargo Bounty UI as a modular app, with cargo access.
  • +
  • The Cargo Bounty UI has been revamped.
  • +
  • Cargo tablets now come preinstalled with the price tagger and cargo bounty apps.
  • +
+

Cyberboss updated:

+
    +
  • TGS4 channel tags will now use ',' as a delimiter to indicate multiple tags.
  • +
+

EdgeLordExe updated:

+
    +
  • Mansus grasp now wont proc on things it shouldnt proc on, tl;dr you wont loose your charges by missclicking on a tile.
  • +
  • Replaced touch of madness with a new fun late game spell
  • +
  • Switches positions of blood siphon and cleave
  • +
+

Fikou updated:

+
    +
  • you can now transmute a pen, a pair of eyes, a bible and human skin into a spare codex cicatrix if you researched some new lore
  • +
  • mjolnir now knockdowns instead of stunning
  • +
+

Hopek updated:

+
    +
  • Tape recorder has been reworked.
  • +
+

KathyRyals updated:

+
    +
  • The Xray mutation can no longer be obtained via combining radioactive and thermal eyes.
  • +
+

ShizCalev updated:

+
    +
  • Fixed some bad areacoord messages when teleporting around.
  • +
  • Fixed an exploit that would allow you to destroy round-critical / indestructible items with folders.
  • +
+

XRandomXManX updated:

+
    +
  • Removed Decal Painter from BEPIS Minor Rewards
  • +
  • Added Decal Painter to the Basic Tools Research Node
  • +
  • Added Decal Painter to Maintenance Loot alongside the Airlock Painter
  • +
+

necromanceranne updated:

+
    +
  • Added new heretic blade sprites! One for the Ashen Blade, Rusted Blade and Flesh Blade
  • +
  • The blades have some descriptions now.
  • +
  • Fixed some infiltrator toolbox sprites (hopefully).
  • +
  • Some eldritch items have had their descriptions and text altered to be a bit more legible and flavourful.
  • +
+

nightred updated:

+
    +
  • Service department area update on Meta
  • +
  • Stackers deposit to the silo when picking up stacks from the input side.
  • +
+

silicons updated:

+
    +
  • An explosion compressor has been added to science. It makes raw anomaly cores into proper anomaly cores using prepared TTVs of a specific required blast radius.
  • +
+ +

27 June 2020

+

Ryll/Shaps updated:

+
    +
  • Too much bone hurting juice REALLY hurts your bones, oof.
  • +
+

Tlaltecuhtli updated:

+
    +
  • the nanotransen research science division found that epinephrine has healing effects to people who drank lexorin
  • +
  • eye stabbing returns a normal attack if it fails instead of doing nothing
  • +
+ +

26 June 2020

+

Arkatos updated:

+
    +
  • Portable Turret now uses tgui.
  • +
+

Ryll/Shaps updated:

+
    +
  • Nanotrasen now uses smaller fonts on ID's to show age and account information, requiring a closer look to read
  • +
+

ShizCalev updated:

+
    +
  • Fixed revenant's light overload ability not blowing lights in a square if there was another broken/burnt out/empty light in it.
  • +
  • Fixed showing a piece of paper to a camera not working if there was an AI that had died or has remote access disabled.
  • +
  • Bank cards will now still give you notifications if you're standing next to another player who has them disabled.
  • +
  • Fixed bronze golems' gong ability not working if there was a dead mob on screen.
  • +
  • Fixed bone golems' bonechill ability not working if there was any mobs that were undead, resistant to cold, or also golems on screen.
  • +
  • Fixed a scenario where you would be unable to offer someone an item if you already had a pending item offer with someone else standing near you.
  • +
+

WarlockD updated:

+
    +
  • Suit cell charge on stat panel
  • +
  • Suit cell gauge works now
  • +
+

coiax updated:

+
    +
  • The Nanite Host Scan program can now scan the host for wounds.
  • +
+

sergeirocks100 updated:

+
    +
  • Malt Liquor can now be obtained from your local Booze-O-Mat
  • +
+ +

25 June 2020

+

ATHATH updated:

+
    +
  • The tox purging threshold for livers has been changed from 3u to 3u * [liver's health]/[liver's maximum health].
  • +
+

EdgeLordExe updated:

+
    +
  • Otherwordly presence has taken more control over the holes in reality.
  • +
  • Influences now actually spawn randomly on the station.
  • +
+

Jared-Fogle updated:

+
    +
  • The search bar will now automatically focus when you open up the orbit menu, the uplink, the biogenerator, and the camera console.
  • +
+

Melbert updated:

+
    +
  • Allows the HONK Oingo-Boingo Punch-Face to toggle between lethal and non-lethal modes.
  • +
  • The HONK Oingo-Boingo Punch-Face's throw distance now scales on how much damage it deals. By default, it's the same distance as before.
  • +
  • Pacifists can no longer use the HONK Oingo-Boingo Punch-Face to damage people.
  • +
  • Admins can now edit the damage of the HONK Oingo-Boingo Punch-Face. Honk.
  • +
+

WarlockD updated:

+
    +
  • You can open paper ui with double shift click
  • +
+

dearmochi updated:

+
    +
  • Fix thrown bolas (and other items) bypassing weapon/shield blocking
  • +
+ +

24 June 2020

+

ArcaneMusic updated:

+
    +
  • Sentient regal and regular rats can now eat cheese wedges to recover a small amount of health.
  • +
+

Arkatos updated:

+
    +
  • Turret Control Panel now uses tgui.
  • +
+

Caldony updated:

+
    +
  • fixed a bug with the battle arcade game where the combos would sometimes not register correctly.
  • +
+

EdgeLordExe updated:

+
    +
  • Wizard can no longer mindswap into a statue to become neigh invicible, fire throwing bastard.
  • +
  • Wizard can no longer mindswap into laughter or slaughter demons to gain a free jaunt and an unlimited heals for killing people. You know one thing that wizard is good at...
  • +
+

LemonInTheDark updated:

+
    +
  • Removes a redundant check in fire code
  • +
+

Maurukas updated:

+
    +
  • Boxstation and Icebox medbays have been completely reworked
  • +
+

ShizCalev updated:

+
    +
  • Fixed the backpack setting showing up twice in the preferences window.
  • +
  • Chameleon ties can no longer disguise as skill capes.
  • +
  • The SM will no longer pull mobs not affected by gravity.
  • +
+

TemporalOroboros updated:

+
    +
  • Synthflesh works again.
  • +
+

Timberpoes updated:

+
    +
  • DNA Console will no longer bluescreen in certain scenarios when disks are ejected.
  • +
+

WarlockD updated:

+
    +
  • allows the air alarm to let vents suck are as well as pressurize.
  • +
+

tmtmtl30 updated:

+
    +
  • stopped midround dynamic families ruleset from picking mindshielded starting family members
  • +
+ +

23 June 2020

+

Kathy Ryals updated:

+
    +
  • Fixed Box wires and pipes near R&D, as well as the door that got deleted.
  • +
+

LemonInTheDark updated:

+
    +
  • Fixed stealth implants not properly boxing the user, and doors not shocking
  • +
  • Renamed COOLDOWN_CHECK to COOLDOWN_FINISHED
  • +
  • Removed some old unused clockcult status effects
  • +
+

LemonInTheDark, Heather Shadelight updated:

+
    +
  • Changed some portal sprites, hope ya like em :)
  • +
+

Paxilmaniac updated:

+
    +
  • PP-95 smg and it's magazine
  • +
  • replaced mosin with pp-95 in the nuke op uplink
  • +
+

ShizCalev updated:

+
    +
  • Fixed logging / admin message coordinate handling for items being held by mobs / in containers / in containers inside other containers giving nullspace / 0,0,0 location references.
  • +
+

Timberpoes updated:

+
    +
  • Belts in Delta EVA and the Ashwalker Ruins no longer show up as ERRORs.
  • +
  • Science are now able to print DNA Scanner boards. Boards associated with Genetics are now only printable in Science and have been removed from Medical printers.
  • +
+

bobbahbrown updated:

+
    +
  • Removed exploitable world/topic command server_hop
  • +
+

silicons updated:

+
    +
  • onZImpact no longer does throw_impact. This was broken anyways. Code must now manually handle multiz falling impacts. This fixes runtimes occuring whenever something fell.
  • +
+

zxaber updated:

+
    +
  • Nuke Ops (and Lone Ops) now start with a Syndicate-themed tablet, rather than the pinpointer. The Syndicate tablet comes pre-installed with an app that replaces the function of disk pinpointers.
  • +
  • Lifeline and Fission360, the apps that track suit sensors and nuke disks respectively, now show the tracking status on the screen of the tablet/laptop object itself, without needing to keep the window open.
  • +
+ +

22 June 2020

+

EdgeLordExe updated:

+
    +
  • You can no longer raise the living as ghouls.
  • +
  • Mansus grasp and blood siphon no longer have infinite range.
  • +
  • Armsy can now actually attack with any of his bodyparts. fix:Armsy can now acutally walk in space.
  • +
  • replaced a few type paths with more descriptive ones.
  • +
+

Gamer025 updated:

+
    +
  • Blood drunk miner megafauna can no longer move structures like bolted down doors / windows
  • +
+

Kathy Ryals updated:

+
    +
  • Due to some very convincing paramedics, the medidrobe has been updated to include the paramedic jumpsuit and jumpskirt.
  • +
+

Melbert updated:

+
    +
  • Obsession picture objective no longer needs the obsessed themselves to be in the picture.
  • +
  • Obsession picture objective now works properly.
  • +
+

TemporalOroboros updated:

+
    +
  • Reagent exposure proc names now accurately describe their function.
  • +
  • Reagent exposure code is less `istype` dependent.
  • +
+

WarlockD updated:

+
    +
  • Preview works now
  • +
  • Clicking on "save" now previews correctly
  • +
  • Form fields now sized correctly
  • +
  • Form fields now save the data
  • +
+ +

21 June 2020

+

Jared-Fogle updated:

+
    +
  • Pointing will now animate starting from you to the object you pointed at.
  • +
+ +

20 June 2020

+

Caldony updated:

+
    +
  • NT finally decided to update the arcade battle video game after its terrible space game reviews from syndicate gaming.
  • +
+

LemonInTheDark updated:

+
    +
  • Fixed a "Feature" from 2 years ago. The sm will now pull objects closer to it based on the eer. This includes you, so be careful.
  • +
  • I've documented all of the sms variables.
  • +
  • Refactored sm code to be more modular. Badmins do not rejoice!
  • +
+ +

19 June 2020

+

Kathy Ryals updated:

+
    +
  • The plant analyzer has been updated to be able to analyze a Podman health or chemical contents.
  • +
+

LemonInTheDark updated:

+
    +
  • The singularity will no longer turn snow or ice on icebox into lattices when at stage 5
  • +
+

Ryll/Shaps updated:

+
    +
  • Empaths are able to detect deafness derived from hearing damage
  • +
  • Inacusiate and Sensory Restoration no longer instantly heal all hearing damage when applied, instead rapidly removing both ear damage and deafness.
  • +
  • MedHUDs and observers now display quirks as intended on examine
  • +
  • Nanotrasen's Central Shipping department has put limits on the free shipping it offers on goody crates, to discourage abuse of its bluespace packaging
  • +
+

SteelSlayer updated:

+
    +
  • Removed a handful of unnecessary variables from intercoms.
  • +
  • Refactored intercom's code so that it doesn't need to process() and constantly check whether it's powered or EMP'd every few seconds.
  • +
+

WarlockD updated:

+
    +
  • Cyborgs can now use multi layer cable interface
  • +
+

genessee596 updated:

+
    +
  • TCG brand trading cards now show their rarity on the card, with tiers of rarity attached to a background color on the 'N' box on the bottom right corner.
  • +
+ +

18 June 2020

+

ATHATH updated:

+
    +
  • pAIs no longer start with a medHUD, secHUD, and diagHUD turned on as soon as they're downloaded, even if they haven't bought any HUDs yet.
  • +
  • You can now take obligate carnivory grafts from jupiter cups.
  • +
  • You can now take fire resistance grafts from lavaland plants.
  • +
+

Iamgoofball updated:

+
    +
  • Gangsters are, in fact, antags, and can totally kill, destroy, and murder all they want.
  • +
  • Fixes GARBAGE DAY
  • +
  • Dynamic Families now goes from 30 to 15 minutes, instead of 60 to 30 minutes.
  • +
  • Space Cop Objectives have been changed in Families.
  • +
+

ShizCalev updated:

+
    +
  • Fixed a scenario that allowed infinite resource generation via ore machines.
  • +
  • Swarmers can no longer cut power lines by deconstructing catwalks underneath them.
  • +
  • Corrected a minor grammar error when attacking mobs with sharp stuff.
  • +
  • Clothing repair now works.
  • +
  • Fixed redundant "shredded x fell apart, completely shredded!" message when damaging clothing in your hands.
  • +
  • Added better pronoun handling for clothing that consist of a pair of items (ie shoes, gloves, ect)
  • +
  • Shredding clothing while holding it will no longer make you drop it.
  • +
  • Shredding clothing while holding it will no longer tell you that it fell off you.
  • +
  • Moths can no longer infinitely eat shredded clothing.
  • +
  • Tears in the very fabric of reality created by Eldritch gods can no longer be mended with acid, fire, and TK.
  • +
+

TheSpaghetti updated:

+
    +
  • orang
  • +
+

Timberpoes updated:

+
    +
  • Added scroll bar to ghost Orbit target selection menu.
  • +
+

Tlaltecuhtli updated:

+
    +
  • organ transport box, if filled with cryostylene or ice it ll keep organs and bodyparts like heads inside frozen ( they dont decay)
  • +
+

WarlockD updated:

+
    +
  • Added markdown for paper
  • +
+

tralezab updated:

+
    +
  • heretics raising the living into ghouls
  • +
+ +

17 June 2020

+

EdgeLordExe updated:

+
    +
  • Having Codex Cicatrix in a pocket while sacrificing someone will give you charges now.
  • +
+

Firecage updated:

+
    +
  • Clown cars are now unable to be driven over ice chasms.
  • +
+

LoserWasTaken updated:

+
    +
  • ooc no longer checks if message is ic if round hasn't started
  • +
+

Melbert updated:

+
    +
  • Fixed staff of animation being able to spawn animated objects inside containers (ie bags)
  • +
+

Mickyan updated:

+
    +
  • fixed missing icon appearing while wearing wigs, again!
  • +
  • wigs will once again change inventory icon based on hairstyle
  • +
+

Ryll/Shaps updated:

+
    +
  • You can no longer embed items into walls
  • +
+

ShizCalev updated:

+
    +
  • Engineering scanner goggles are now the correct color when their modes are switched.
  • +
  • Fixed cable coils always showing as a full stack.
  • +
+

TheChosenEvilOne updated:

+
    +
  • emergency shuttle console no longer lists authorizations twice.
  • +
+ +

15 June 2020

+

Cobby kills medbots!!! updated:

+
    +
  • Medbots that are suppose to heal other damage types than brute now actually do so
  • +
+

IradT updated:

+
    +
  • Added a doorjack to the Metaops bundle
  • +
  • added wound armor to the wizard hat
  • +
+

Jared-Fogle updated:

+
    +
  • The health analyzer is now the first item in the first aid kits.
  • +
  • You will now see an alert when you are drunk.
  • +
+

Shadark updated:

+
    +
  • Deltastation Morgue is now accessible from the main hallway.
  • +
+

ShizCalev updated:

+
    +
  • Fixed a bunch of errors appearing on arcade machines and various monitors / computers when powered off.
  • +
+ +

14 June 2020

+

Arkatos updated:

+
    +
  • Airlocks will now immediately show their unrestricted access sides when created via RCD.
  • +
+

Fikou updated:

+
    +
  • you can no longer have fun in ctf with metal
  • +
+

Iamgoofball updated:

+
    +
  • Members of the crew with mindshields have remembered that anti-gang PSA they watched back in space high school.
  • +
+

Jared-Fogle updated:

+
    +
  • Added a new organized orbit menu.
  • +
  • Fixed ghosting making your body look undefibbable to a medical HUD.
  • +
+

a few Sprites from Kryson updated:

+
    +
  • Heretics have been spotted near your area, don't let them succed.
  • +
  • Added a sane version of GetAllContents called get_all_gear().
  • +
+

bobbahbrown updated:

+
    +
  • Fixed malformed SQL queries for logging admin permission changes.
  • +
+

dragomagol updated:

+
    +
  • Nanotrasen has begun producing Peacekeeper plushes to improve public reception of silicons
  • +
+

~~yorii~~ Space updated:

+
    +
  • lava boat oars work now
  • +
+ +

13 June 2020

+

ATHATH updated:

+
    +
  • The message that you receive when you try to use a gang induction package as a mindshielded person no longer implies that your mindshield has given you fake memories of attending an anti-gang seminar.
  • +
+

Arkatos updated:

+
    +
  • Unrestricted directional access settings will now show correct directions in the related UIs.
  • +
  • Theoretical radiuses will now show properly in the Tachyon-Doppler Array UI.
  • +
+

Ryll/Shaps updated:

+
    +
  • Medbot interaction menus are fixed
  • +
  • You can no longer queue multiple medbot flips at once
  • +
  • Medbots now have lots more to say, especially if you knock them over!
  • +
+

Shadark updated:

+
    +
  • Detective gets roundstart normal sunglasses instead of SecHUDs at PubbyStation.
  • +
  • Balanced access to arrest option through SecHUDs, now requiring Security access instead of Brig access.
  • +
  • Balanced access to portable turrets, now requiring Security access instead of Brig access.
  • +
+

ShizCalev updated:

+
    +
  • Fixed a scenario where changelings would have missing textures when disguised.
  • +
  • Fixed a scenario where camouflage items would have missing textures.
  • +
  • Items in your suit storage should have less missing textures now.
  • +
  • Restore the ion rifle's unique belt texture.
  • +
  • Fixed a few more belt items having missing textures.
  • +
  • Fixed washing machines sometimes fucking up an item's worn texture.
  • +
+

tmtmtl30 updated:

+
    +
  • dynamic families rulesets can now be forced and will execute instead of runtiming
  • +
+ +

12 June 2020

+

ATHATH updated:

+
    +
  • Borgs and AIs now start with their borgHUDs/siliconHUDs on by default.
  • +
+

Jared-Fogle updated:

+
    +
  • Ghosts will now be revealed when the round is over.
  • +
+

Ryll/Shaps updated:

+
    +
  • Introduces medical wounds, new injuries that can happen to fleshy carbons when they sustain lots of damage on a bodypart. There's quite a lot of change here, but you can read the guide at: https://tgstation13.org/wiki/Guide_to_wounds and an extended changelog is available here: https://hackmd.io/l_FI9b3tSqa_woDadewJXA
  • +
  • Introduces scars and temporal scarring! Healing a wound leaves a scar behind that can be seen by examining someone twice rapidly, and if Temporal Scarring is enabled in character prefs, surviving a round with scars will save them to be granted at roundstart another round! Let your body tell stories!
  • +
  • Bleeding is now fully bodypart-focused, and 95% of bleeding comes from cut wounds from sharp weapons. Gauze is applied on a limb-by-limb basis, and helps staunch bloodflow rather than totally stop it. Notably, you no longer bleed just from having 40+ brute damage on a limb.
  • +
  • Organic bodyparts are no longer disabled at maximum damage, but are easier to cause wounds to
  • +
  • O2 medkits in emergency lockers have been replaced with new emergency medkits with basic tools for diagnosing and treating wounds and basic damage
  • +
  • Herapin now rapidly increases bleeding on all open cuts, rather than causing bleeding by itself. The more cuts on the target, the more it will affect them.
  • +
  • Neckgrab table slams now hit the targeted limb rather than just the head, with a large chance to dislocate or break a bone
  • +
  • Sharp weapons and burning weapons can now shred zones on jumpsuits, disabling protection on that limb. Damaged clothes can be repaired with cloth.
  • +
  • Slaughter demons now deal less raw damage, but gain the ability to cause cut wounds, which becomes more powerful with each attack on a humanoid but resets when bloodcrawling.
  • +
+

Timberpoes updated:

+
    +
  • Delta's Genetics Lab has been redesigned.
  • +
  • Pubby's Genetics Lab has been redesigned.
  • +
  • Science ID Card access levels have been redesigned. R&D now has its own dedicated access level with Toxins and Toxins Storage having their own dedicated access levels.
  • +
  • Science doors across all maps have had their access levels tweaked, especially around maintenance access and R&D access.
  • +
  • Geneticists now have R&D Access across all maps.
  • +
  • Xenobiology's Winter Coats now have a new set of pockets that can hold all the same equipment as a lab coat.
  • +
  • All Xenobiology secure containment areas there were missing them, now have Connector/Injector pairs for injecting gasses directly into secure containment.
  • +
  • Pubby's Xenobiology lab now has three slime spawns.
  • +
  • Pubby's Xenobiology lab has been expanded with addtional containment pens.
  • +
  • Meta's Xenobiology freezer no longer shares a pipe with Xenobio's air distribution pipes. Scientists should no longer freeze to death and space suits with internals are no longer necessary.
  • +
  • Delta's Xenobiology lab now requires Xenobiology access to enter.
  • +
  • Delta's Xenobiology lab has been expanded with additional containment pens.
  • +
  • Pubby's Toxins Mass Driver room now has an intercom.
  • +
  • Delta's Toxins Mass Driver room's intercom has been moved closer to the Tachyon-Doppler Research Array.
  • +
  • Prototype Hardsuits have been moved to the RD's Office on from Toxins on Meta and Pubby.
  • +
  • All Genetics Labs across all station now come fully equipped with Body Bags, Space Cleaner and Mutadone.
  • +
  • Box's Genetics Lab now has an air alarm.
  • +
  • Meta's Genetics Lab's camera has been moved so the AI can see the entire lab, including the Air Alarm.
  • +
  • Geneticists will no longer spawn in the monkey pen on Meta.
  • +
  • The Medical Laptop in Delta's Genetics lab can now be accessed by Geneticists.
  • +
  • Pubby's Robotics Lab now has a Cautery!
  • +
  • Probably more minor quality of life changes I forgot to document as I made them.
  • +
+ +

11 June 2020

+

Arkatos updated:

+
    +
  • Tachyon-Doppler Array now uses tgui.
  • +
+

Inept updated:

+
    +
  • Card collectors, rejoice! The NTED has released a new binder for storing your TCG cards. Pick one up at the Fun vendor today!
  • +
+

ShizCalev updated:

+
    +
  • I comes before E, except after C.
  • +
  • Wearing a gun on your armor / belt will no longer result in your waist turning purple and black.
  • +
+

tmtmtl30 updated:

+
    +
  • The Families gamemode and antagonist have been refactored and should perform more sanely in some cases.
  • +
  • Families can now appear in dynamic rounds.
  • +
+ +

10 June 2020

+

ATHATH updated:

+
    +
  • The in-game podcloning guide (The Human Harvest: From Seed to Market) has been updated.
  • +
  • Venus human traps now have x-ray and thermal vision.
  • +
+

ArcaneMusic updated:

+
    +
  • The Seed Vault ruin now comes equip with the complete modern arsenal of new botany tools and equipment.
  • +
+

Arkatos updated:

+
    +
  • Holopad now uses tgui.
  • +
+

Cobby updated:

+
    +
  • craftable medbots now only heal brute unless they are built with specialized medkits.
  • +
  • medbots built with the brute medkit heal 10% more
  • +
  • medbots built with the advance medkit heal all damage types
  • +
+

Fox McCloud updated:

+
    +
  • Fixes attack animations being stuttery and twitchy; they should, once again, be buttery smooth
  • +
+

GoldenAlpharex updated:

+
    +
  • New Modular Console Preset added: /obj/machinery/modular_computer/console/preset/id
  • +
+

Inept updated:

+
    +
  • The Nanotrasen Entertainment Division has released a new product: Tarot cards! They're available from the Fun vendor for all your divination needs.
  • +
+

Jared-Fogle updated:

+
    +
  • Fixed the medical HUD sometimes reporting undefibbable bodies as defibbable and vice versa.
  • +
  • Fixed plasmamen needing hearts in order to be defibbed.
  • +
  • Fixed crew with HARS needing a brain to be defibbed.
  • +
  • Fixed defibrillators being borked. Sorry!
  • +
+

Kelenius updated:

+
    +
  • Hygienebot construction has been fixed.
  • +
  • Hygienebots now require a proximity sensor between welding and tubing.
  • +
  • Hygienebots no longer slip their path while chasing someone.
  • +
  • Hygienebots are less spammy.
  • +
+

Ryll/Shaps updated:

+
    +
  • You can now tip over medbots!
  • +
+

ShizCalev updated:

+
    +
  • Defibbing now works properly on ALL species that don't require hearts to survive, as opposed to just plasmamen.
  • +
  • Defibbing now works properly on mobs with the Muscled Veins trait if their heart was removed.
  • +
+

TheChosenEvilOne updated:

+
    +
  • Fixed dynamic giving antagonist roles to jobs that shouldn't get them (again).
  • +
+

TiviPlus updated:

+
    +
  • Succesful restart votes will now complete instantly
  • +
+

bababooey updated:

+
    +
  • bababooey
  • +
+

bobbahbrown updated:

+
    +
  • Improved performance of lighting code
  • +
+

tmtmtl30 updated:

+
    +
  • removed deprecated check_win() proc
  • +
+ +

08 June 2020

+

IndieanaJones updated:

+
    +
  • Lavaland elite loot drops for Broodmother and Legionnaire now have in-hand use functions
  • +
  • Lavaland elites now have more health in their arena fights, along with several other balance changes
  • +
  • Fixed lavaland elites not being able to damage mechs
  • +
+

SpaceManiac updated:

+
    +
  • BSQL has been replaced with rust-g, improving SQL reliability and safety.
  • +
+ +

07 June 2020

+

LemonInTheDark updated:

+
    +
  • Breaking a canister while it's wrenched down will no longer cause it to look "goofy"
  • +
+

TheChosenEvilOne updated:

+
    +
  • Removed high population override from dynamic.
  • +
  • fixed dynamic runtiming with invalid configurations.
  • +
+

tmtmtl30 updated:

+
    +
  • Dynamic roundstart ruleset scaling on second-rolled roundstart rulesets has been slightly tweaked.
  • +
+ +

06 June 2020

+

IradT updated:

+
    +
  • fixed changeling reset function not giving the right values after absorbing another changeling
  • +
+

Ryll/Shaps updated:

+
    +
  • Having a circle hand or slapper in hand no longer protects you from xeno tackles or borg buckling
  • +
+ +

05 June 2020

+

LemonInTheDark updated:

+
    +
  • The singularity no longer turns reinforced floor tiles into infinite rods
  • +
  • Added some unit tests for cards, hopefully you'll see fun things with this soon.
  • +
+

MrDoomBringer updated:

+
    +
  • Supplypods can once again have custom falling sounds
  • +
+

nemvar updated:

+
    +
  • Icelag fix boxed
  • +
+ +

04 June 2020

+

ATHATH updated:

+
    +
  • The 16 second hardstun that non-pAI mulebots with cut avoidance wires apply to living creatures they bump into has been replaced with a much more tame 8 second knockdown.
  • +
+

ArcaneMusic updated:

+
    +
  • Organic Pest Killer is now available in the biogenerator.
  • +
  • Pest Killer and Weed Killer now applies the correct amount of toxicity and doesn't individually harm the plant's health.
  • +
  • Pest/Week killer bottles now have a transfer rate of 1 ,2, and 5 units per use, and a max capacity of 30 units.
  • +
+

Fikou updated:

+
    +
  • atmos jumpsuit now has the same armor values as engi jumpsuit
  • +
  • replaces plasma in bluespace beaker design with plastic
  • +
+

Ryll/Shaps updated:

+
    +
  • Cigarette packets now have coupons on the back for small cargo items! Smoking DOES pay!
  • +
  • Single/small items in cargo have been rebranded as goodies, come in lockboxes rather than crates, and can only be purchased with private accounts. They also are immune to the 10% private account fee, obviously.
  • +
+

Skoglol updated:

+
    +
  • Removed some dead unused code in languages.
  • +
  • Box gravity generator and AI core APC rewired to smes, will not run out roundstart anymore. P.A.C.M.A.N. added to grav gen for emergencies.
  • +
+

TheChosenEvilOne updated:

+
    +
  • Dynamic will no longer give antagonist roles to jobs who shouldn't have them when restricted roles is set in the config.
  • +
+

Tlaltecuhtli updated:

+
    +
  • lightfloor makes colored lights and are more visible
  • +
  • you can turn them off/on by using your screwdriver
  • +
  • you can emp em
  • +
  • breaking them actually works
  • +
  • using a broken bulb wont fix em sprites: flicker states for each colour
  • +
+

necromanceranne updated:

+
    +
  • Neckgrabs and especially floor neckgrabs are no longer near impossible to escape.
  • +
  • Resisting a grab is more consistent across the board, but you get less chances at resisting a grab and take more stamina damage.
  • +
+ +

02 June 2020

+

ArcaneMusic updated:

+
    +
  • The hallway on icebox mining is slightly longer. and the ladder deposits you in the locker room.
  • +
  • The icebox mining ladder works again.
  • +
+

EOBGames, ArcaneMusic, LemonInTheDark updated:

+
    +
  • Nanotrasen is pleased to announce the 2560 Core Set of the NT TCG has been released! Aspiring collectors can purchase booster packs from the Fun Vendor, as well as bulk purchases at cargo. Happy hunting!
  • +
+

Kelenius updated:

+
    +
  • DNA scanner can now store any amount of mutations and chromosomes.
  • +
+ +

01 June 2020

+

Fhaxaris updated:

+
    +
  • baton, health analyzer, classic baton, PDA and pinpointer.
  • +
+

Fikou updated:

+
    +
  • Our Nanotrasen Elite Anti-Animal Team hunted down King Goat and stopped his reign forever. As a memorial of this event you can now get a cute goat plushie from the arcades.
  • +
+

PrimordialOoze updated:

+
    +
  • Split the Ignore verb into two verbs (Ignore and Unignore)
  • +
  • Unignore allows you to view your ignore list
  • +
  • Unignore allows you to unignore players who are offline
  • +
  • Ignore and Unignore should not interfere with Stealth Mode
  • +
+

SomeoneYouProbablyKnow updated:

+
    +
  • Psychologists gets a new Hud icon that's not a P
  • +
  • The "incarcerated" sec hud icon gets a new sprite that is not a P
  • +
+

TemporalOroboros updated:

+
    +
  • Firesuits and radiation suits can now fit most internals tanks.
  • +
+

Timberpoes updated:

+
    +
  • Only the Descendents of Asclepius who have taken the Hippocratic Oath may perform the Healing Touch miracle and conduct multiple concurrent surgeries. Everyone else is limited to a single surgery step at a time.
  • +
+

nemvar updated:

+
    +
  • Glow will now always be a random color.
  • +
  • Antiglow will now absorb all light equally.
  • +
  • Improved waddling for big things.
  • +
+ +

31 May 2020

+

Fikou updated:

+
    +
  • a bunch of items no longer give illegal tech
  • +
+

Helianthus00 updated:

+
    +
  • Fixed the air supply and scrubber pipes to be more neat, as well as fixing a few displaced vents in medbay
  • +
  • removed the double cable on one of the AI upload doors.
  • +
+

MacBlaze1 updated:

+
    +
  • fixed no one showing up on crew monitor or #51332
  • +
+ +

30 May 2020

+

ArcaneMusic updated:

+
    +
  • Plant sprites no longer ERROR when just planted.
  • +
+

Kathy Ryals updated:

+
    +
  • The Nanite Programmer and Nanite Program Hub can now be properly deconstructed.
  • +
+

MrDoomBringer updated:

+
    +
  • You should seriously consider playing for over five thousand hours, okay?
  • +
+

Ryll/Shaps updated:

+
    +
  • Characters of "Other" gender can now choose between male and female sprites in their preferences
  • +
+

Shadark updated:

+
    +
  • Plant analyzer can now be used on planted glowshrooms.
  • +
  • Planted glowshrooms are more influenced by their stats.
  • +
  • Planted glowshrooms expand more rapidly, but decay over time.
  • +
+ +

29 May 2020

+

ArcaneMusic updated:

+
    +
  • Standard Engineering tools now show up on the player when worn on the belt.
  • +
+

AsphaltEvidence updated:

+
    +
  • added directional sprites to the arcade machines
  • +
  • added directional sprites to the arcade machine screens
  • +
+

MrDoomBringer updated:

+
    +
  • Nanotrasen is pleased to announce that their employee's inner monologues will now be able to properly spell intricacies
  • +
+

Qustinnus updated:

+
    +
  • fixes a critical bug where you couldn't build toilets out of pizza or meat.
  • +
+

TheVekter updated:

+
    +
  • Nanotrasen is experimenting further regarding the interaction between hydrogen and plasma. A new cargo bounty has been added for a single tank of hydrogen.
  • +
  • Centcom no longer needs Phazon mechs delivered to them.
  • +
+

nemvar updated:

+
    +
  • Nerfed the power chromosome + (anti)-glowy mutation
  • +
+

willox updated:

+
    +
  • remove unnecessary var/id from /datum/material
  • +
+ +

27 May 2020

+

ArcaneMusic updated:

+
    +
  • Icebox's mining, EVA Exits, and cargo shuttle areas have been adjusted to distinguish them from boxstation.
  • +
  • Adds Liquid Earthquake, a botany biogenerator chem that increases production speed, but increases plant weed susceptibility.
  • +
  • Adds Enduro Grow, a botany biogenerator chem that improves a plant's endurance stat, but decreases it's yield and potency.
  • +
+

ArcaneMusic/Azlan updated:

+
    +
  • Updated the Ancient Spear sprite.
  • +
+

Kathy Ryals updated:

+
    +
  • You can now altClick to take out a disk from a DNA Console.
  • +
+

Krysonism updated:

+
    +
  • fixes the horticultural waders sprite by adding hand holes.
  • +
+

Kurgis updated:

+
    +
  • New mouse detective poster.
  • +
+

LemonInTheDark updated:

+
    +
  • Fixed smallscreen resizing on restart or when you die.
  • +
  • Pixel size and scaling method will properly save now.
  • +
+

MacBlaze1 updated:

+
    +
  • Prevents doomsday activation while shunting and disabled doomsday if a malf shunts after activation.
  • +
  • fixed #50792, also known as the cool amazing bug that makes taking your clothes on and off duplicate an unknown onto the crew monitor program/console/device
  • +
+

Qustinnus updated:

+
    +
  • You can no longer get hardcore random points by joining last second
  • +
+

Ryll/Shaps updated:

+
    +
  • You can no longer shotgun canned beverages
  • +
  • Removed errant TP from the admin full monty
  • +
+

WarlockD updated:

+
    +
  • Fixed the internal to use mask
  • +
  • flag change to the space heater and electrolyzer
  • +
+

actioninja updated:

+
    +
  • missing textures
  • +
+

nemvar updated:

+
    +
  • Scaling methods in the preference menu now have the correct names.
  • +
+

ohnoitsdixie updated:

+
    +
  • Paramedics now have access to the Engineering Foyer, and no longer have to crawl into Engineering through maintenance like filthy assistants.
  • +
+

willox updated:

+
    +
  • Botany grafts for traits other than 'perennial growth' are no longer non-functional
  • +
  • Cross-pollination can no longer result in plants entering an infinitely-harvestable state
  • +
+

zxaber updated:

+
    +
  • Two new apps for modular computers are available: Lifeline for Medical, and Fission360 for anyone with access to the Syndicate repository. Lifeline is an improved suit sensors tracker, and Fission360 is the same but for nuclear-related things.
  • +
+ +

26 May 2020

+

Fikou, spookydonut made the glove code sane updated:

+
    +
  • concussive gauntlets! available at your local tendril chest
  • +
  • tendril loot has changed a bit
  • +
  • hulks can now break rocks
  • +
+

JoshAdamPowell updated:

+
    +
  • Simplified granibitaluri recipe
  • +
+

MrDoomBringer updated:

+
    +
  • Reaching legendary levels of any given skill will grant you an otherwise unobtainable reward.
  • +
  • Nanotrasen has recently acquired new software to track employee skill development, straight from your PDA! Check it out! In unrelated news, the rate of summary executions handed out to Nanotrasen's lowest performing employees has risen sharply.
  • +
  • Modify player's skills with the new Skill Panel menu, available from the Player Panel!
  • +
+

Paxilmaniac updated:

+
    +
  • things to the bounty hunter ship that might be important, such as oxygen tanks, and a toolbox, along with two tiny fans in the airlocks
  • +
+

Pumpkinoe updated:

+
    +
  • Added a new large emergency shuttle for purchase at 8000 Cr, the Dynamic Enviornment Interaction Shuttle. Try it out today and frolic with the monkeys!
  • +
+

Ryll/Shaps updated:

+
    +
  • Sleeping carp no longer grants outright damage resistances to all forms of damage. Its price has been decreased to 12TC
  • +
+

TerraGS updated:

+
    +
  • Material containers are better at managing local storage
  • +
+

Timberpoes updated:

+
    +
  • SMES units now self-charge when containing yellow slime cores.
  • +
+

Tlaltecuhtli updated:

+
    +
  • janibelt/medibelt can be opened from backpack
  • +
  • removed some defunct code (picking a color of cable but its all yellow in belt.dm)
  • +
  • bandoliers now hold their intended 18 shells.
  • +
+

WarlockD updated:

+
    +
  • Swapped a few arguments out of the materials container
  • +
+

kevinz000 updated:

+
    +
  • Hierophant now uses its ranged abilities in melee attacks, meaning the strategy of standing still and tanking the hits is no longer viable in 99% of circumstances.
  • +
+ +

25 May 2020

+

Cyberboss updated:

+
    +
  • The `notify` TGS command will no longer work if the related config setting is disabled
  • +
  • Fixed not actually limiting chat sends to tagged channels as the config should allow when running under TGS4.
  • +
  • Fixed the `notify` command not working for IRC users.
  • +
+

Fikou updated:

+
    +
  • fixed science glasses recipe using beer goggles instead of science glasses
  • +
+

Gamer025 updated:

+
    +
  • Nanotrasen checked the last few expenses reports and decided to reduce payday spending. Because of this, the salary of all non human employees has been reduced by 25%. Please consult your local Head of Personal for more information.
  • +
+

Kelenius updated:

+
    +
  • Cyborgs (except Peacekeeper and Standard) now have access to their department's radio.
  • +
+

LemonInTheDark updated:

+
    +
  • Changed the way h2o interacts with the engine. It should acts similar to o2 normally, but in high concentrations it cools the engine down. Have fun :)
  • +
  • Mulebots no longer go insane when shit starts to lag
  • +
  • Refactored client.view into a datum, changed some zoom values to work properly
  • +
  • Spinning while using a binocular will work as expected
  • +
  • Fully adds widescreen support to zooming
  • +
  • I've moved the pixel scaling and zoom methods from the menu bar to the game preferences window. You'll need to reset them.
  • +
  • Pixel size will now automatically update on zoom, so you won't end up with ui buttons you can't see.
  • +
  • FIxed the epic gamer skill of binocular applied to advanced camera console
  • +
+

LemonInTheDark, with thanks to ArcaneDefence for the pointer updated:

+
    +
  • Scrubbers no longer cool pipenets attached to them when scrubbing space
  • +
+

MarioWizard119 updated:

+
    +
  • Synthflesh now also works via vapor.
  • +
+

NewSta updated:

+
    +
  • You might potentially see better a/an usage
  • +
+

Ryll/Shaps updated:

+
    +
  • You can now use ! and ? at the end of 'spawn' chatbar verb commands to search for only the ends of paths, or to automatically select a random type of the paths your search returns! Happy badminning!
  • +
  • Adds a config option for OOC kindness commendations! When enabled, a small percentage of the crew gets asked if anyone made their round better, and those people will get a little heart next to their name in OOC for 24h!
  • +
  • lobby menu work again
  • +
+

Shadark updated:

+
    +
  • Manually printed barcodes are now working correctly.
  • +
+

TetraK1 updated:

+
    +
  • Ghosts can no longer control atmos stuff with alt/ctrl click.
  • +
  • Added logging to ctrl/alt clicks on atmos stuff
  • +
+

TheVekter updated:

+
    +
  • Nanotrasen's export price for Hydrogen no longer violates the basic rules of supply and demand.
  • +
+

actioninja updated:

+
    +
  • smon,k weed
  • +
+

antropod updated:

+
    +
  • Fix PanDEMIC 2200 not showing Blood DNA and Blood Type
  • +
+

kevinz000 updated:

+
    +
  • dir_inverse_multiz() should work now. should.
  • +
+

nemvar updated:

+
    +
  • The camera console looks fancier now.
  • +
+

qustinnus updated:

+
    +
  • you can no longer move up when you are going to fall down anyways, or you know, dead.
  • +
  • simple multi-z audio
  • +
+

spessman-007 updated:

+
    +
  • Quite a few misspellings have been corrected
  • +
+

tralezab updated:

+
    +
  • anomaly crystal theme warping for the jungle now uses wooden walls instead of sandstone ones
  • +
+

wesoda25 updated:

+
    +
  • The progress bar for butchering large mobs is no longer offset.
  • +
+

zxaber updated:

+
    +
  • Explosions that were able to destroy doors before will now rip them from the universe.
  • +
+ +

24 May 2020

+

Cobby updated:

+
    +
  • Dissection will now give XP instead of research points.
  • +
+

Fikou updated:

+
    +
  • admins can now do html in ahelps properly
  • +
+

qustinnus updated:

+
    +
  • Fixes you being able to put in more than one license plate in the license plate machine
  • +
+ +

22 May 2020

+

ArcaneMusic updated:

+
    +
  • Adds a new assembly component, the freezer, for gradually making the environment colder.
  • +
+

Dorsidwarf updated:

+
    +
  • Swarmer structures are no longer broken.
  • +
+

Fikou updated:

+
    +
  • you can no longer inject html in ahelps
  • +
  • you cant either, jannies
  • +
+

Ghilker updated:

+
    +
  • Cryotubes can no longer reach fusion level heat
  • +
  • Cryotubes breakdown if the heat inside is higher than 2000 K
  • +
  • Cryotubes extinguish the mob if on fire
  • +
+

Mickyan updated:

+
    +
  • Fixed missing icon on wigs
  • +
+

Whoneedspacee updated:

+
    +
  • Icebox Station has been added, explore the depths of the Ice Moon with boxstation right on top of it, don't forget your coat and internals!
  • +
  • You can now mine rock flora into volcanic ash to make glass.
  • +
+

kevinz000 updated:

+
    +
  • Circlegame items now properly delete on drop and can't be made with full hands.
  • +
+

wesoda25 updated:

+
    +
  • fixes a misspelled xenobiology sign
  • +
+

willox updated:

+
    +
  • diseases now retain the ability to infect people after having 'inorganic biology' or 'necrotic metabolism' removed from them
  • +
+ +

20 May 2020

+

Skoglol updated:

+
    +
  • Another dynamic rolling restricted roles as antags fix.
  • +
+

Thebleh updated:

+
    +
  • Fixes MetaStation's disposals
  • +
+

dootdoom updated:

+
    +
  • Straight Jacket now has bigger bolder red text to alert you someone is putting it on you.
  • +
+ +

17 May 2020

+

Nebulacrity for the sprites, LemonInTheDark for chopshop job updated:

+
    +
  • Adds proper inhands to the singularity hammer, take a look, they're pretty neat.
  • +
+ +

15 May 2020

+

PKPenguin321 updated:

+
    +
  • You can no longer cheat at becoming a legendary gamer by committing suicide a lot in Orion Trail.
  • +
+

nemvar updated:

+
    +
  • Clicking links in goonchat will no longer eat your next input.
  • +
+ +

13 May 2020

+

ATHATH updated:

+
    +
  • (web) edits some soulstone messages
  • +
+

Fikou updated:

+
    +
  • you can now stroke heads with a bangammer in peace
  • +
+

Inept updated:

+
    +
  • "Devil, just come on back now if you ever want to try again, I told you once, you son of a bitch, I'm the best there's ever been."
  • +
+

ThePainkiller updated:

+
    +
  • Adds Gastrectomy, a surgery for healing damaged stomachs.
  • +
+

rdragan updated:

+
    +
  • Power has been restored to Pubby's Medbay
  • +
+ +

12 May 2020

+

Rodey125 updated:

+
    +
  • gumballs and spider lollipops are now a subtype of chewables
  • +
+

TheVekter updated:

+
    +
  • The Clarke's weight has been reduced, causing it not to break floor tiles anymore.
  • +
+
+ +GoonStation 13 Development Team +
+ Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
+ Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No
+
+
+

Creative Commons License
Except where otherwise noted, Goon Station 13 is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
Rights are currently extended to SomethingAwful Goons only.

+

Some icons by Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 License.

+
+ + diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 185cdd9992e..1b62d67fb90 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -40573,11 +40573,179 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. Fikou: - bugfix: fixes labor camp beacon sprite - balance: manly dorf now doesnt turn on dorf mode with alcohol tolerance + FloranOtten: + - balance: Space Cops now come equipped with appropriate environmental protection. Jared-Fogle: - bugfix: Fixed cryo cells locking up those with prosthetic limbs. - bugfix: Fixes tend wounds not healing and brain surgery not curing traumas. + Melbert: + - rscadd: Mech vs Mech combat system for toy mechs! Hit a toy mech with another + toy mech, or attack a player holding a toy mech with a toy mech, and you can + initiate battle between toys! + - rscadd: Each toy mech now has its own health stat and special attack move for + use in mech vs mech combat. Discover them all! + - rscadd: Suicide act for mech toys. If you wanted to take part in the toy mech + battles yourself. ShizCalev: - tweak: Added more examine text to bots. + - bugfix: Fixed player controlled statues being able to speak. + - bugfix: Fixed nonhuman that aren't able to speak being able to cast spoken spells + - bugfix: Fixed a minor runtime caused by removing a laser pointer's diode while + it's still turned on. + Tlaltecuhtli: + - admin: votes now play a beep noise when they get started + Wayland-Smithy: + - rscadd: Blob mobs from an overmind now see critical mass progress as a status. oranges: - tweak: Where some names might previously have been accepted, they will now be rejected, this should not affect any regular names in use + tralezab: + - rscdel: Removes the 9 assistants 3 changeling setup, yech. + - bugfix: Lotta bugfixes for mafia! + - soundadd: Mafia now alerts you when starting a game! + - spellcheck: grammar + better text for some roles at better times of the game + - code_imp: LET THERE BE MAFIA DOCUMENTATION! +2020-07-09: + EdgeLordExe: + - bugfix: You can no longer infinitely spawn heretics summons + Jared-Fogle: + - code_imp: Added surgery related unit tests and adds TEST_ASSERT, TEST_ASSERT_EQUAL, + and allocate to unit tests. + Melbert: + - bugfix: Fixes an infinite loop / infinite camera shake in the Bubblegum hallucination + Timberpoes: + - bugfix: Ghost orbit menu can now orbit things with weird metadata in their names + like medibots and MULEBOTs. + - tweak: Ghost orbit menu search bar looks prettier. + - tweak: Ghost orbit menu no longer auto-closes when you select something to orbit. + Indirectly buffs voyeurs. + nightred: + - bugfix: fixed destructive analyzer item visual not being removed when destroying + items + zxaber: + - bugfix: Borg machine conveyance has been repaired, to the delight of any "alternative"-functioning + AIs that wish to onboard new silicon employees. +2020-07-11: + ShizCalev: + - bugfix: Fixed the field generators in Delta's Singulo area being anchored but + not secured. + - bugfix: Fixed field generators continuing to function after being uprooted by + a mob. + Timberpoes: + - bugfix: Fix being unable to orbit player characters and antags from the observer + orbit menu. + nemvar: + - bugfix: Barrel melon description now makes a bit more sense now. + tralezab: + - rscadd: Cargo can purchase monkey sentience helmets under the science tab! +2020-07-12: + ATHATH: + - bugfix: To sacrifice someone on a sacrificial altar (such as the ones found in + the healing fountain ruin), you must now alt-click the altar, not normal-click + it. The default descriptions of sacrificial altars have been updated accordingly. + Alterist: + - bugfix: Upgraded Cybernetic Lungs (Tier3) now have improved oxygen absorption, + same as Cybernetic Lungs (Tier2) + - rscadd: Added 3 tier of Cybernetic Stomachs, researchable by R&D and buildable + in the Medical Lathe. + Angust: + - bugfix: fixed space vines / kudzu growing slower from better (lower) production + speed + - balance: random event space vines buffed to have 1-6 production instead of 5-10 + to compensate + ArcaneMusic: + - tweak: Icebox Maintenance, and Icebox Service Hallway have been rearranged to + be more spacious. + - bugfix: Bounty boards are properly responsive, and are mapped on icebox dorms + as intended. + Dennok: + - code_imp: Separate BLOCK_Z_FALL flag to BLOCK_Z_OUT_DOWN, BLOCK_Z_OUT_UP, BLOCK_Z_IN_DOWN, + BLOCK_Z_IN_UP + - rscadd: Now lattice can support spaceman + - bugfix: Catwalk block uplifting from below + - bugfix: now posting in shuttle propertly fails + EdgeLordExe: + - bugfix: Voiceless dead are now longe INVISIBILITY_ABSTRACT, god i hate bugs + - rscadd: Ascension will make you greentext + Fikou: + - bugfix: Bounty hunter hat sprite works again. + Jay Smith & MrDoomBringer: + - bugfix: Replaced faulty sprites for various bags and the Portable Chemical Mixer + in the belt slot + - bugfix: Replaced the DNA probe's old sprite (Hypospray) with a unique sprite + - imageadd: New icon and sprites for the DNA probe + - imageadd: Belt sprites for the Portable Chemical Mixer and various bags + Kathy Ryals and ArcaneMusic: + - tweak: Plant mutation chances at 80+ instability is now a sliding scale. + LemonInTheDark: + - bugfix: The tesla/sm will ground bolts less jankilly now + - bugfix: Wires will no longer burn if they're under a tile that's on fire + - code_imp: Reinserted some old checks for if something is over/under a tile + LoserWasTaken: + - tweak: blood cleave does only one wound instead of 3 now + Maurukas: + - rscadd: Added reconstructive surgery for moth wings, requiring synthflesh + - bugfix: Magical healing and aheals now restore moth wings + Melbert: + - bugfix: Fixes railings blocking bullets and immovable rods from a certain direction. + MrDoomBringer: + - imageadd: Nanotrasen's Transportation and Logistics Subdivision has spent the + better part of their budget developing a brand new model of Supplypod. Internal + investigations have revealed the only real differences are almost purely aesthetic. + Ryll/Shaps: + - admin: As an admin ghost, examining another ghost twice quickly will pull up clickable + links to their info in chat + - rscadd: Examining someone who has examined you within the last second will give + you both a small message saying you made eye contact. Having your face obscured + by a helmet or mask will prevent the other person from noticing, no matter who + looked first. + - rscadd: Those with social anxiety may find eye contact to be stressful, and those + who foster unhealthy obsessions over other crewmembers may outright staredown + their prey. + - rscadd: 'Throwing people really hard into vending machines is not advised if you + don''t want to clean them up afterwards. Things are considered thrown really + hard if: You''re throwing them as a hulk, the person you''re throwing is a dwarf, + and/or if you''re throwing someone from a neckgrab' + - rscadd: You can now adjust the speed disposal outlets eject contents at with a + multitool, and emag the disposal outlet to amp the speed up even further! + - bugfix: Player controlled medbots are no longer permanently crippled when tipped + over + - admin: New admin smite for knotting someone's shoes if possible + ShizCalev: + - bugfix: Fixed radiation immune mobs getting irradiated. + - bugfix: Plasmamen who have acquired the fireproofing trait will no longer get + spammed with messages saying they caught on fire. + - admin: Stacks will now update properly when you varedit their amount. It's clamped + to max_amount, so make sure to change that too if you want to increase the amount + beyond it. + - bugfix: Fixed some constant runtime spam when defib rechargers had their defib + destroyed. + - bugfix: Fixed a minor runtime when examining paper twice. + - refactor: Cleaned up arcade machine examine-more messages a little. + - bugfix: Map placed headpikes will now have heads... and pikes! + - bugfix: Fixed headpikes having the wrong mob name. + - bugfix: Fixed a minor runtime when removing a monkey's sentience helmet. + Skoglol: + - bugfix: Parrot possession now works. + - bugfix: Fixed some glowshroom runtimes. + - admin: Wendigo no longer spams admin messages. + Tlaltecuhtli: + - rscadd: conveyor switches now have a wire that can be pulsed with signalers/other + assemblies to active it + Wayland-Smithy: + - balance: Resource and Factory Blobs can only be placed on station where they count + towards critical mass. + YPOQ: + - bugfix: Fixed an issue that prevented AIs from tracking players in areas they + have not yet viewed. + silicons: + - bugfix: cameras no longer crash the server + tralezab: + - bugfix: Fixed up Mafia maps, at least in all the ways I caught! + - bugfix: mind mag helms losing their icon sometimes + uomo91: + - tweak: You can now leave Metastation's medbay after being treated without bugging + a doctor to let you out. +2020-07-13: + Tlaltecuhtli: + - tweak: monkey caps drop on the floor if no ghosts got polled diff --git a/icons/blanks/32x32.dmi b/icons/blanks/32x32.dmi new file mode 100644 index 00000000000..6c4f2b33e0f Binary files /dev/null and b/icons/blanks/32x32.dmi differ diff --git a/icons/blanks/96x96.dmi b/icons/blanks/96x96.dmi new file mode 100644 index 00000000000..d79e60c111a Binary files /dev/null and b/icons/blanks/96x96.dmi differ diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi index 9da6471842b..0f0afb12639 100644 Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi index 32ab3796592..f87616a15d2 100644 Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ diff --git a/icons/mob/gondolapod.dmi b/icons/mob/gondolapod.dmi index 4c56c1bb556..36a4825bceb 100644 Binary files a/icons/mob/gondolapod.dmi and b/icons/mob/gondolapod.dmi differ diff --git a/icons/mob/inhands/equipment/medical_lefthand.dmi b/icons/mob/inhands/equipment/medical_lefthand.dmi index a1e711eee38..2e05ca17cd9 100644 Binary files a/icons/mob/inhands/equipment/medical_lefthand.dmi and b/icons/mob/inhands/equipment/medical_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/medical_righthand.dmi b/icons/mob/inhands/equipment/medical_righthand.dmi index ff4060e4284..a570a3cd189 100644 Binary files a/icons/mob/inhands/equipment/medical_righthand.dmi and b/icons/mob/inhands/equipment/medical_righthand.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 2a9640df6fa..1cc9dd0a3f4 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/supplypods.dmi b/icons/obj/supplypods.dmi index d21da6d53ae..4dfc996f45b 100644 Binary files a/icons/obj/supplypods.dmi and b/icons/obj/supplypods.dmi differ diff --git a/icons/obj/supplypods_32x32.dmi b/icons/obj/supplypods_32x32.dmi new file mode 100644 index 00000000000..a7607f716f7 Binary files /dev/null and b/icons/obj/supplypods_32x32.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index c3c9efe8a1f..92417d8bbee 100755 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/obj/syringe.dmi b/icons/obj/syringe.dmi index f5dadf52566..9d47e452af0 100644 Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ diff --git a/icons/obj/terminals.dmi b/icons/obj/terminals.dmi index 131bcb5006d..e538a764441 100644 Binary files a/icons/obj/terminals.dmi and b/icons/obj/terminals.dmi differ diff --git a/sound/effects/license.txt b/sound/effects/license.txt index e1ca5c4e76f..77351397fde 100644 --- a/sound/effects/license.txt +++ b/sound/effects/license.txt @@ -1,4 +1,4 @@ -hit_punch.ogg and hit_kick.ogg are made by Taira Komori +hit_punch.ogg and hit_kick.ogg are made by Taira Komori (https://taira-komori.jpn.org/freesounden.html) cartoon_pop.ogg by Tobiasz 'unfa' Karoń diff --git a/sound/misc/bloop.ogg b/sound/misc/bloop.ogg new file mode 100644 index 00000000000..260e9e926e1 Binary files /dev/null and b/sound/misc/bloop.ogg differ diff --git a/sound/misc/license.txt b/sound/misc/license.txt new file mode 100644 index 00000000000..75a7cc1e93f --- /dev/null +++ b/sound/misc/license.txt @@ -0,0 +1,2 @@ +bloop.ogg by my man Tim Khan +(https://freesound.org/people/tim.kahn/sounds/130377/) diff --git a/tgstation.dme b/tgstation.dme index ef534df467e..ef43e3d17d3 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -634,6 +634,7 @@ #include "code\datums\wires\airlock.dm" #include "code\datums\wires\apc.dm" #include "code\datums\wires\autolathe.dm" +#include "code\datums\wires\conveyor.dm" #include "code\datums\wires\emitter.dm" #include "code\datums\wires\explosive.dm" #include "code\datums\wires\microwave.dm" @@ -1011,6 +1012,7 @@ #include "code\game\objects\items\teleprod.dm" #include "code\game\objects\items\theft_tools.dm" #include "code\game\objects\items\toys.dm" +#include "code\game\objects\items\toy_mechs.dm" #include "code\game\objects\items\trash.dm" #include "code\game\objects\items\vending_items.dm" #include "code\game\objects\items\wayfinding.dm" @@ -3023,6 +3025,7 @@ #include "code\modules\surgery\advanced\necrotic_revival.dm" #include "code\modules\surgery\advanced\pacification.dm" #include "code\modules\surgery\advanced\viral_bonding.dm" +#include "code\modules\surgery\advanced\wingreconstruction.dm" #include "code\modules\surgery\advanced\bioware\bioware.dm" #include "code\modules\surgery\advanced\bioware\bioware_surgery.dm" #include "code\modules\surgery\advanced\bioware\cortex_folding.dm" diff --git a/tgui/packages/tgui/interfaces/Orbit.js b/tgui/packages/tgui/interfaces/Orbit.js index 131c63651df..82739afbc3d 100644 --- a/tgui/packages/tgui/interfaces/Orbit.js +++ b/tgui/packages/tgui/interfaces/Orbit.js @@ -1,8 +1,10 @@ import { createSearch } from 'common/string'; -import { Box, Button, Input, Section } from '../components'; +import { Box, Button, Input, Icon, Section, Flex } from '../components'; import { Window } from '../layouts'; import { useBackend, useLocalState } from '../backend'; +import { createLogger } from '../logging'; + const PATTERN_DESCRIPTOR = / \[(?:ghost|dead)\]$/; const PATTERN_NUMBER = / \(([0-9]+)\)$/; @@ -44,7 +46,7 @@ const BasicSection = (props, context) => { key={thing.name} content={thing.name.replace(PATTERN_DESCRIPTOR, "")} onClick={() => act("orbit", { - name: thing.name, + ref: thing.ref, })} /> ))} @@ -59,7 +61,7 @@ const OrbitedButton = (props, context) => {