diff --git a/.editorconfig b/.editorconfig index df93ae3a16..13dcd5e029 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,3 +6,6 @@ indent_size = 4 [*.yml] indent_style = space indent_size = 2 + +[*.txt] +insert_final_newline = false diff --git a/README.md b/README.md index ed82fb08e6..2a1ffe65ec 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ - -##Citadel Station 13
-Based and maintained from /tg/station.
+## Citadel Station 13 +Based and maintained from /tg/station. [![forthebadge](http://forthebadge.com/images/badges/60-percent-of-the-time-works-every-time.svg)](https://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/pretty-risque.svg)](https://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/you-didnt-ask-for-this.svg)](http://forthebadge.com) @@ -10,18 +9,19 @@ Based and maintained from /tg/station.
[![Percentage of issues still open](http://isitmaintained.com/badge/open/Citadel-Station-13/Citadel-Station-13.svg)](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Percentage of issues still open") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/Citadel-Station-13/Citadel-Station-13.svg)](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Average time to resolve an issue") -**Upstream Information**
-**Website:** http://www.tgstation13.org
-**Code:** https://github.com/tgstation/tgstation
-**Wiki** http://tgstation13.org/wiki/Main_Page
-**IRC:** irc://irc.rizon.net/coderbus or if you dont have an IRC client, you can click [here](https://kiwiirc.com/client/irc.rizon.net:6667/?&theme=cli#coderbus).
- -**Citadel Station Information**
-**Forums:** http://citadel-station.net/forum/
-**Ban Appeals:** http://citadel-station.net/forum/forumdisplay.php?fid=8
-**Code:** https://github.com/Citadel-Station-13/Citadel-Station-13
-**Discord:** [Here](https://discord.gg/E6SQuhz).
- +**Upstream Information** +**Website:** https://tgstation13.org +**Code:** https://github.com/tgstation/tgstation +**Wiki** https://tgstation13.org/wiki/Main_Page +**IRC:** irc://irc.rizon.net/coderbus or if you dont have an IRC client, you can click [here](https://kiwiirc.com/client/irc.rizon.net:6667/?&theme=cli#coderbus). + +**Citadel Station Information** +**Website:** http://citadel-station.net +**Forums:** http://citadel-station.net/forum +**Ban Appeals:** http://citadel-station.net/forum/forumdisplay.php?fid=8 +**Code:** https://github.com/Citadel-Station-13/Citadel-Station-13 +**Discord:** [Here](https://discord.gg/E6SQuhz) + ## DOWNLOADING There are a number of ways to download the source code. Some are described here, an alternative all-inclusive guide is also located at http://www.tgstation13.org/wiki/Downloading_the_source_code diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 56126c6e37..f5b76d1ba9 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -173,6 +173,19 @@ "aay" = ( /turf/open/floor/plating, /area/security/prison) +"aaz" = ( +/obj/structure/lattice/catwalk, +/obj/item/stack/marker_beacon{ + anchored = 1; + icon_state = "markerburgundy-on"; + light_color = "#FA644B"; + light_power = 3; + light_range = 3; + name = "Docking Beacon"; + picked_color = "Burgundy" + }, +/turf/open/space/basic, +/area/space/nearstation) "aaA" = ( /obj/machinery/seed_extractor, /turf/open/floor/plasteel, @@ -234,10 +247,46 @@ /obj/structure/chair/stool, /turf/open/floor/plasteel, /area/security/prison) +"aaK" = ( +/obj/structure/lattice/catwalk, +/obj/item/stack/marker_beacon{ + anchored = 1; + icon_state = "markerburgundy-on"; + light_color = "#FA644B"; + light_power = 3; + light_range = 3; + name = "Docking Beacon"; + picked_color = "Burgundy" + }, +/turf/open/floor/plating, +/area/space/nearstation) +"aaL" = ( +/obj/machinery/photocopier, +/turf/open/floor/wood, +/area/library) +"aaM" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/brown, +/obj/effect/turf_decal/tile/brown{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/quartermaster/office) "aaN" = ( /obj/structure/chair/sofa/right, /turf/open/floor/plasteel, /area/security/prison) +"aaO" = ( +/obj/effect/spawner/lootdrop/keg, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "aaP" = ( /obj/machinery/computer/cryopod{ dir = 8; @@ -248,6 +297,12 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"aaQ" = ( +/obj/structure/sign/poster/contraband/random{ + pixel_y = 32 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "aaR" = ( /obj/structure/lattice, /obj/structure/sign/warning/securearea{ @@ -285,6 +340,15 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"aaY" = ( +/obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance{ + lootcount = 4; + name = "4maintenance loot spawner" + }, +/obj/item/poster/random_official, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "aaZ" = ( /turf/closed/wall/r_wall, /area/ai_monitored/security/armory) @@ -505,6 +569,11 @@ "abF" = ( /turf/open/floor/plasteel/freezer, /area/security/prison) +"abG" = ( +/obj/structure/door_assembly/door_assembly_mai, +/obj/item/electronics/airlock, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "abH" = ( /obj/structure/table, /obj/item/storage/box/chemimp{ @@ -1565,6 +1634,10 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/carpet, /area/crew_quarters/heads/hos) +"adO" = ( +/obj/effect/spawner/structure/window/shuttle, +/turf/open/floor/plating/airless, +/area/space/nearstation) "adP" = ( /obj/structure/cable{ icon_state = "2-8" @@ -1979,6 +2052,34 @@ }, /turf/open/floor/plating, /area/maintenance/fore/secondary) +"aeD" = ( +/obj/structure/grille/broken, +/turf/open/floor/plating/airless, +/area/space/nearstation) +"aeE" = ( +/obj/structure/girder, +/turf/open/floor/plating/airless, +/area/space/nearstation) +"aeF" = ( +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -23 + }, +/obj/machinery/computer/station_alert{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/turret_protected/aisat_interior) "aeG" = ( /obj/structure/cable, /obj/machinery/power/solar{ @@ -2357,6 +2458,12 @@ }, /turf/open/floor/plasteel, /area/security/main) +"afn" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) "afo" = ( /obj/machinery/door/airlock/external{ name = "Escape Pod Three" @@ -2377,6 +2484,39 @@ }, /turf/open/space/basic, /area/space) +"afq" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) +"afr" = ( +/obj/machinery/atmospherics/pipe/manifold4w/scrubbers, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) +"afs" = ( +/obj/machinery/computer/security/telescreen/entertainment{ + pixel_x = -31 + }, +/obj/machinery/computer/monitor{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "0-4" + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/turret_protected/aisat_interior) "aft" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 5 @@ -2687,6 +2827,15 @@ /obj/machinery/atmospherics/pipe/manifold4w/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) +"age" = ( +/obj/structure/chair/office/dark{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) "agf" = ( /obj/structure/table, /obj/item/stack/sheet/metal, @@ -2836,6 +2985,10 @@ /obj/machinery/suit_storage_unit/security, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) +"agv" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) "agw" = ( /obj/structure/table, /obj/machinery/syndicatebomb/training, @@ -2965,6 +3118,14 @@ }, /turf/open/floor/plasteel, /area/security/main) +"agH" = ( +/obj/machinery/bluespace_beacon, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/landmark/start/cyborg, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/turret_protected/aisat_interior) "agI" = ( /obj/machinery/airalarm{ pixel_y = 23 @@ -3094,6 +3255,12 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/security/warden) +"agX" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) "agY" = ( /obj/structure/table, /obj/item/storage/fancy/donut_box, @@ -3334,6 +3501,16 @@ }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) +"ahw" = ( +/obj/machinery/atmospherics/pipe/manifold4w/supply/hidden, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) "ahx" = ( /obj/structure/cable{ icon_state = "4-8" @@ -4474,6 +4651,16 @@ /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /turf/open/floor/plasteel, /area/security/brig) +"ajC" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) "ajD" = ( /obj/structure/cable{ icon_state = "4-8" @@ -4682,6 +4869,18 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plating, /area/maintenance/solars/port/fore) +"ajX" = ( +/obj/machinery/computer/teleporter{ + dir = 8 + }, +/turf/open/floor/plating, +/area/ai_monitored/turret_protected/aisat_interior) +"ajY" = ( +/obj/machinery/holopad, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/landmark/start/cyborg, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/turret_protected/aisat/atmos) "ajZ" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/warning/vacuum/external{ @@ -4965,6 +5164,18 @@ }, /turf/open/floor/plasteel, /area/security/courtroom) +"akz" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/holopad, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/landmark/start/cyborg, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/turret_protected/aisat_interior) "akA" = ( /obj/structure/chair{ dir = 8; @@ -29979,17 +30190,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"bwc" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel, -/area/quartermaster/office) "bwd" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -49288,47 +49488,9 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) -"ctu" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 - }, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) "ctv" = ( /turf/closed/wall/r_wall, /area/space/nearstation) -"ctw" = ( -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -23 - }, -/obj/machinery/computer/station_alert, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/turret_protected/aisat_interior) -"ctx" = ( -/obj/machinery/atmospherics/pipe/manifold4w/scrubbers, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) -"cty" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) "ctz" = ( /obj/machinery/door/poddoor/shutters{ id = "teledoor"; @@ -49373,41 +49535,6 @@ }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) -"ctG" = ( -/obj/structure/chair/office/dark{ - dir = 8 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) -"ctH" = ( -/obj/machinery/computer/security/telescreen/entertainment{ - pixel_x = -31 - }, -/obj/machinery/computer/monitor, -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/turret_protected/aisat_interior) -"ctI" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) "ctJ" = ( /obj/machinery/holopad, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -49431,13 +49558,6 @@ }, /turf/open/floor/plating, /area/ai_monitored/turret_protected/aisat_interior) -"ctM" = ( -/obj/machinery/bluespace_beacon, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/turret_protected/aisat_interior) "ctN" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible{ dir = 10 @@ -49445,13 +49565,6 @@ /obj/structure/lattice, /turf/open/space, /area/space/nearstation) -"ctP" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 - }, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) "ctQ" = ( /obj/structure/table, /obj/machinery/microwave{ @@ -49477,28 +49590,6 @@ /obj/structure/sign/warning/radiation/rad_area, /turf/closed/wall, /area/engine/engineering) -"ctS" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) -"ctT" = ( -/obj/machinery/atmospherics/pipe/manifold4w/supply/hidden, -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) "ctU" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -49521,10 +49612,6 @@ /obj/structure/chair, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) -"ctW" = ( -/obj/machinery/computer/teleporter, -/turf/open/floor/plating, -/area/ai_monitored/turret_protected/aisat_interior) "ctX" = ( /obj/machinery/camera{ c_tag = "MiniSat Teleporter"; @@ -49805,11 +49892,6 @@ }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat/atmos) -"cuC" = ( -/obj/machinery/holopad, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/turret_protected/aisat/atmos) "cuD" = ( /obj/machinery/light/small{ dir = 8 @@ -49858,17 +49940,6 @@ }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) -"cuG" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/holopad, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/turret_protected/aisat_interior) "cuH" = ( /obj/machinery/light/small{ dir = 8 @@ -53259,13 +53330,6 @@ }, /turf/open/floor/mineral/titanium/blue, /area/crew_quarters/dorms) -"dkk" = ( -/obj/machinery/photocopier{ - pixel_x = -5; - pixel_y = -5 - }, -/turf/open/floor/wood, -/area/library) "dok" = ( /obj/item/twohanded/required/kirbyplants{ icon_state = "plant-22" @@ -53692,18 +53756,6 @@ dir = 1 }, /area/crew_quarters/fitness) -"fsk" = ( -/obj/structure/lattice/catwalk, -/obj/item/stack/marker_beacon{ - anchored = 1; - icon_state = "markerburgundy-on"; - light_power = 3; - light_range = 3; - name = "Docking Beacon"; - picked_color = "Burgundy" - }, -/turf/open/floor/plating, -/area/space/nearstation) "ftv" = ( /obj/structure/table, /obj/effect/spawner/lootdrop/maintenance{ @@ -54203,18 +54255,6 @@ dir = 1 }, /area/crew_quarters/fitness) -"hho" = ( -/obj/structure/lattice/catwalk, -/obj/item/stack/marker_beacon{ - anchored = 1; - icon_state = "markerburgundy-on"; - light_power = 3; - light_range = 3; - name = "Docking Beacon"; - picked_color = "Burgundy" - }, -/turf/open/space/basic, -/area/space/nearstation) "hik" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -54439,9 +54479,6 @@ "iiW" = ( /turf/open/floor/wood, /area/maintenance/bar) -"ikx" = ( -/turf/open/floor/plating/foam, -/area/space/nearstation) "ilJ" = ( /obj/effect/turf_decal/tile/red, /obj/machinery/light{ @@ -55678,10 +55715,6 @@ /obj/structure/extinguisher_cabinet, /turf/closed/wall/r_wall, /area/hallway/primary/central) -"mwb" = ( -/obj/effect/spawner/structure/window/shuttle, -/turf/open/floor/plating, -/area/space/nearstation) "mwO" = ( /obj/structure/cable{ icon_state = "1-4" @@ -56489,7 +56522,8 @@ icon_state = "4-8" }, /obj/machinery/door/airlock/command{ - name = "Command Access To Vault" + name = "Command Access To Vault"; + req_access = "19" }, /turf/open/floor/plasteel/dark, /area/bridge/meeting_room) @@ -56803,10 +56837,6 @@ /obj/item/target/syndicate, /turf/open/floor/plating, /area/security/prison) -"rxH" = ( -/obj/structure/girder, -/turf/open/floor/plating, -/area/space/nearstation) "rzg" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -57253,12 +57283,6 @@ }, /turf/open/floor/plating, /area/maintenance/port/aft) -"thr" = ( -/obj/structure/frame/computer{ - dir = 1 - }, -/turf/open/floor/plating, -/area/space/nearstation) "tkU" = ( /turf/open/floor/wood{ icon_state = "wood-broken5" @@ -58554,10 +58578,6 @@ }, /turf/open/space/basic, /area/space/nearstation) -"xWM" = ( -/obj/structure/grille/broken, -/turf/open/floor/plating, -/area/space/nearstation) "xXY" = ( /obj/structure/closet/lasertag/red, /obj/item/clothing/under/pj/red, @@ -64623,11 +64643,11 @@ aaa aaa aaa aaa -fsk +aaK aaa aaa aaa -fsk +aaK aaa aaa aaa @@ -64874,9 +64894,9 @@ aaa aaa aaa aaa -fsk +aaK aaa -fsk +aaK aaa aaa aaa @@ -64888,9 +64908,9 @@ gXs aaa aaa aaa -fsk +aaK aaa -fsk +aaK aaa aaa aaa @@ -81103,7 +81123,7 @@ bpB bpB brR bsV -bwc +aaM bxA bvI bwX @@ -95688,9 +95708,9 @@ aaa aaa aaa aaa -hho +aaz aaa -hho +aaz aaa aaa aaa @@ -96072,7 +96092,7 @@ aaf ctZ cui cuq -cuC +ajY cuO cuz cvm @@ -96580,8 +96600,8 @@ czk cti cua cua -ctw -ctH +aeF +afs ctQ cuc cuj @@ -96837,9 +96857,9 @@ ctb cth cua ctr -ctu -ctG -ctP +afn +age +agX cub cuj cur @@ -97094,13 +97114,13 @@ ctc ctc cto ctt -cty +afq ctJ -ctT +ahw cue cul cuu -cuG +akz cuS cve cvo @@ -97351,9 +97371,9 @@ ctb ctj ctk cts -ctx -ctI -ctS +afr +agv +ajC cud cuk cus @@ -98123,7 +98143,7 @@ aaa aaf cua ctF -ctM +agH ctX cuf cum @@ -98381,7 +98401,7 @@ aaf cua ctE ctL -ctW +ajX cuf cum cuw @@ -101379,7 +101399,7 @@ bbE aIr bav aLf -dkk +aaL kLR aRO aQp @@ -101961,10 +101981,10 @@ aaa aaa aaa aaa -ikx -mwb -xWM -rxH +aaH +adO +aeD +aeE aaa aaa aaa @@ -102219,10 +102239,10 @@ xNY kvb aaa aaa -ikx -ikx -ikx -rxH +aaH +aaH +aaH +aeE aaa aaa aaa @@ -102473,13 +102493,13 @@ czZ cOT aaa jmC -dbM -dbM -ikx -ikx -ikx -thr -mwb +aaH +aaH +aaH +aaH +aaH +aaH +adO aaa aaa aaa @@ -102732,8 +102752,8 @@ gXs xNY kvb gJg -dbM -dbM +aaH +aaH aaa aaa gJg @@ -102990,8 +103010,8 @@ aaa aaa gJg gJg -mwb -ikx +adO +aaH gXs aaa aaa @@ -106072,7 +106092,7 @@ cNW clt cQw cNW -cNW +abG cNW cNW aaf @@ -106328,7 +106348,7 @@ aaa cOT clt cQw -cOe +aaO cOe cOe cNW @@ -106585,11 +106605,11 @@ aaa cOT clt cQw +aaQ cOe cOe -cOe -cOe -sQX +cNW +aaa jzi jzi jzi @@ -106842,11 +106862,11 @@ aaa cNW clt cQw -cOe +bNB cOe cOe cNW -aaf +lCL aaS aaa aaf @@ -107099,7 +107119,7 @@ cNW cNW clt cQw -cOe +aaY cOe cOe cNW diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 7fbd2921e8..cd50d90edb 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -44934,7 +44934,7 @@ /area/maintenance/port) "bKY" = ( /obj/machinery/power/apc{ - areastring = "/area/vacant_room/office"; + areastring = "/area/security/vacantoffice"; dir = 8; name = "Vacant Office APC"; pixel_x = -25 diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 4052dce40d..6913473e88 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -136,8 +136,12 @@ #define ORGAN_SLOT_TESTICLES "testicles" #define ORGAN_SLOT_BREASTS "breasts" - ////organ defines #define STANDARD_ORGAN_THRESHOLD 100 #define STANDARD_ORGAN_HEALING 0.001 -#define STANDARD_ORGAN_DECAY 0.00222 //designed to fail organs when left to decay for ~15 minutes \ No newline at end of file +#define STANDARD_ORGAN_DECAY 0.00222 //designed to fail organs when left to decay for ~15 minutes + +#define G_MALE 1 +#define G_FEMALE 2 +#define G_PLURAL 3 +#define G_NEUTER 4 diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index cc1b474c49..4304af77f3 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -184,7 +184,7 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define BODY_ZONE_PRECISE_R_FOOT "r_foot" //We will round to this value in damage calculations. -#define DAMAGE_PRECISION 0.1 +#define DAMAGE_PRECISION 0.01 //items total mass, used to calculate their attacks' stamina costs. If not defined, the cost will be (w_class * 1.25) #define TOTAL_MASS_TINY_ITEM 1.25 @@ -202,4 +202,4 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting. #define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting. #define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default. -#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs. \ No newline at end of file +#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs. diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 20679a95e6..a4ee7cc3cc 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -123,6 +123,7 @@ #define COMSIG_TURF_MULTIZ_NEW "turf_multiz_new" //from base of turf/New(): (turf/source, direction) // /atom/movable signals +#define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move" //from base of atom/movable/Moved(): (/atom) #define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir) #define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable) #define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable) diff --git a/code/__DEFINES/configuration.dm b/code/__DEFINES/configuration.dm index 3034876e36..6b70eb1e0f 100644 --- a/code/__DEFINES/configuration.dm +++ b/code/__DEFINES/configuration.dm @@ -1,6 +1,7 @@ //config files #define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X) #define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y) +#define CONFIG_GET_ENTRY(X) global.config.GetEntryDatum(/datum/config_entry/##X) #define CONFIG_MAPS_FILE "maps.txt" diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index 36ea64de2c..54f4648006 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -8,7 +8,7 @@ #define REAGENT_PURITY_ACCURACY 0.001 #define DEFAULT_SPECIFIC_HEAT 200 -// container_type defines +//reagents_holder_flags defines #define INJECTABLE (1<<0) // Makes it possible to add reagents through droppers and syringes. #define DRAWABLE (1<<1) // Makes it possible to remove reagents through syringes. @@ -29,6 +29,11 @@ #define PATCH 4 // patches #define INJECT 5 // injection +//container_flags +#define PH_WEAK (1 << 0) +#define TEMP_WEAK (1 << 1) +#define APTFT_VERB (1 << 2) //APTFT stands for "amount per transfer from this" +#define APTFT_ALTCLICK (1 << 3) //defines passed through to the on_reagent_change proc #define DEL_REAGENT 1 // reagent deleted (fully cleared) diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index d5e3f828b8..28a04c2a51 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -37,7 +37,7 @@ #define ROLE_GANG "gangster" #define ROLE_BLOODSUCKER "bloodsucker" //#define ROLE_MONSTERHUNTER "monster hunter" Disabled for now - +#define ROLE_GHOSTCAFE "ghostcafe" //Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. //The gamemode specific ones are just so the gamemodes can query whether a player is old enough //(in game days played) to play that role diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm index 3fd6b069d4..7e391caaed 100644 --- a/code/__DEFINES/tools.dm +++ b/code/__DEFINES/tools.dm @@ -14,7 +14,9 @@ #define TOOL_DRILL "drill" #define TOOL_SCALPEL "scalpel" #define TOOL_SAW "saw" - +//Glasswork Tools +#define TOOL_BLOW "blowing_rod" +#define TOOL_GLASS_CUT "glasskit" // If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY, // tool sound is only played when op is started. If not, it's played twice. diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 033636017d..d707f7e58a 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -234,6 +234,7 @@ #define ABDUCTOR_ANTAGONIST "abductor-antagonist" #define NUKEOP_ANTAGONIST "nukeop-antagonist" #define MADE_UNCLONEABLE "made-uncloneable" +#define TIMESTOP_TRAIT "timestop" #define NUKEOP_TRAIT "nuke-op" #define MEGAFAUNA_TRAIT "megafauna" #define DEATHSQUAD_TRAIT "deathsquad" diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 0aa9476fad..6ea1de0e2c 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -165,6 +165,12 @@ /proc/log_mapping(text) WRITE_LOG(GLOB.world_map_error_log, text) +/proc/log_reagent(text) + WRITE_LOG(GLOB.reagent_log, text) + +/proc/log_reagent_transfer(text) + log_reagent("TRANSFER: [text]") + /* For logging round startup. */ /proc/start_log(log) WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------") diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm index 4b52187e13..d7378abfa6 100644 --- a/code/__HELPERS/areas.dm +++ b/code/__HELPERS/areas.dm @@ -1,5 +1,81 @@ #define BP_MAX_ROOM_SIZE 300 +//Repopulates sortedAreas list +/proc/repopulate_sorted_areas() + GLOB.sortedAreas = list() + + for(var/area/A in world) + GLOB.sortedAreas.Add(A) + + sortTim(GLOB.sortedAreas, /proc/cmp_name_asc) + +/area/proc/addSorted() + GLOB.sortedAreas.Add(src) + sortTim(GLOB.sortedAreas, /proc/cmp_name_asc) + +//Takes: Area type as a text string from a variable. +//Returns: Instance for the area in the world. +/proc/get_area_instance_from_text(areatext) + if(istext(areatext)) + areatext = text2path(areatext) + return GLOB.areas_by_type[areatext] + +//Takes: Area type as text string or as typepath OR an instance of the area. +//Returns: A list of all areas of that type in the world. +/proc/get_areas(areatype, subtypes=TRUE) + if(istext(areatype)) + areatype = text2path(areatype) + else if(isarea(areatype)) + var/area/areatemp = areatype + areatype = areatemp.type + else if(!ispath(areatype)) + return null + + var/list/areas = list() + if(subtypes) + var/list/cache = typecacheof(areatype) + for(var/V in GLOB.sortedAreas) + var/area/A = V + if(cache[A.type]) + areas += V + else + for(var/V in GLOB.sortedAreas) + var/area/A = V + if(A.type == areatype) + areas += V + return areas + +//Takes: Area type as text string or as typepath OR an instance of the area. +//Returns: A list of all turfs in areas of that type of that type in the world. +/proc/get_area_turfs(areatype, target_z = 0, subtypes=FALSE) + if(istext(areatype)) + areatype = text2path(areatype) + else if(isarea(areatype)) + var/area/areatemp = areatype + areatype = areatemp.type + else if(!ispath(areatype)) + return null + + var/list/turfs = list() + if(subtypes) + var/list/cache = typecacheof(areatype) + for(var/V in GLOB.sortedAreas) + var/area/A = V + if(!cache[A.type]) + continue + for(var/turf/T in A) + if(target_z == 0 || target_z == T.z) + turfs += T + else + for(var/V in GLOB.sortedAreas) + var/area/A = V + if(A.type != areatype) + continue + for(var/turf/T in A) + if(target_z == 0 || target_z == T.z) + turfs += T + return turfs + // Gets an atmos isolated contained space // Returns an associative list of turf|dirs pairs // The dirs are connected turfs in the same space @@ -103,4 +179,62 @@ to_chat(creator, "You have created a new area, named [newA.name]. It is now weather proof, and constructing an APC will allow it to be powered.") return TRUE + +/** + * Returns the base area the target is located in if there is one. + * Alternatively, returns the area as is. + */ +/proc/get_base_area(atom/target) + var/area/A = get_area(target) + if(A?.base_area) + return A.base_area + return A + +/** + * Returns either null, or a list containing every sub area associated with our base area. + * If include_base is TRUE, the base area will also be added to the return list. + */ +/proc/get_sub_areas(atom/target, include_base = TRUE) + var/area/A = get_area(target) + if(!A) + return + . = list() + if(A.base_area) + A = A.base_area + if(include_base) + . += A + if(A.sub_areas) + . += A.sub_areas + +/** + * Proc used for purposes similar to get_areas_turfs(), but aimed to include associated areas. + * Only accepts area instances and paths for the first arg, no text strings. + * Returns a list of all turfs found in the sub areas (including the base's if include_base is TRUE) + * and located in a z level matching target_z, or anywhere if target_z is 0 + */ + +/proc/get_sub_areas_turfs(area/A, target_z = 0, include_base = TRUE) + var/list/contents = get_sub_areas_contents(A, include_base) + . = list() + for(var/turf/T in contents) + if(target_z == 0 || target_z == T.z) + . += T +/** + * Simple proc that returns a sum of all contents from every sub area, + * Think of the above but for all contents, not just turfs, and without target z. + */ + +/proc/get_sub_areas_contents(area/A, include_base = TRUE) + if(ispath(A)) + A = GLOB.areas_by_type[A] + else + A = get_area(A) //in case it's called on other atoms. + if(!A) + return + if(A.base_area) + A = A.base_area + . = list(A.contents) + for(var/i in A.sub_areas) + . += A.sub_areas[i].contents + #undef BP_MAX_ROOM_SIZE diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index ca4b913369..605f7f8ae7 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -8,8 +8,8 @@ #define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL)) #define CULT_POLL_WAIT 2400 -/proc/get_area_name(atom/X, format_text = FALSE) - var/area/A = isarea(X) ? X : get_area(X) +/proc/get_area_name(atom/X, format_text = FALSE, get_base_area = FALSE) + var/area/A = get_base_area ? get_base_area(X) : get_area(X) if(!A) return null return format_text ? format_text(A.name) : A.name @@ -145,20 +145,6 @@ turfs += T return turfs - -//This is the new version of recursive_mob_check, used for say(). -//The other proc was left intact because morgue trays use it. -//Sped this up again for real this time -/proc/recursive_hear_check(O) - var/list/processing_list = list(O) - . = list() - while(processing_list.len) - var/atom/A = processing_list[1] - if(A.flags_1 & HEAR_1) - . += A - processing_list.Cut(1, 2) - processing_list += A.contents - /** recursive_organ_check * inputs: O (object to start with) * outputs: @@ -238,35 +224,30 @@ return found_mobs - /proc/get_hearers_in_view(R, atom/source) - // Returns a list of hearers in view(R) from source (ignoring luminosity). Used in saycode. var/turf/T = get_turf(source) . = list() - if(!T) return - - var/list/processing_list = list() - if (R == 0) // if the range is zero, we know exactly where to look for, we can skip view - processing_list += T.contents // We can shave off one iteration by assuming turfs cannot hear - else // A variation of get_hear inlined here to take advantage of the compiler's fastpath for obj/mob in view + var/list/processing = list() + if(R == 0) + processing += T.contents + else var/lum = T.luminosity - T.luminosity = 6 // This is the maximum luminosity - var/list/cachedview = view(R, T) - for(var/mob/M in cachedview) - processing_list += M - for(var/obj/O in cachedview) - processing_list += O + T.luminosity = 6 + var/list/cached_view = view(R, T) + for(var/mob/M in cached_view) + processing += M + for(var/obj/O in cached_view) + processing += O T.luminosity = lum - - while(processing_list.len) // recursive_hear_check inlined here - var/atom/A = processing_list[1] + var/i = 0 + while(i < length(processing)) + var/atom/A = processing[++i] if(A.flags_1 & HEAR_1) . += A - SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing_list, .) - processing_list.Cut(1, 2) - processing_list += A.contents + SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing, .) + processing += A.contents /proc/get_mobs_in_radio_ranges(list/obj/item/radio/radios) . = list() diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index e916b2532a..2f960e350b 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -457,36 +457,35 @@ Turf and target are separate in case you want to teleport some distance from a t /atom/proc/GetAllContents(var/T) var/list/processing_list = list(src) - var/list/assembled = list() if(T) - while(processing_list.len) - var/atom/A = processing_list[1] - processing_list.Cut(1, 2) + . = list() + var/i = 0 + while(i < length(processing_list)) + var/atom/A = processing_list[++i] //Byond does not allow things to be in multiple contents, or double parent-child hierarchies, so only += is needed //This is also why we don't need to check against assembled as we go along processing_list += A.contents if(istype(A,T)) - assembled += A + . += A else - while(processing_list.len) - var/atom/A = processing_list[1] - processing_list.Cut(1, 2) + var/i = 0 + while(i < length(processing_list)) + var/atom/A = processing_list[++i] processing_list += A.contents - assembled += A - return assembled + return processing_list /atom/proc/GetAllContentsIgnoring(list/ignore_typecache) if(!length(ignore_typecache)) return GetAllContents() var/list/processing = list(src) - var/list/assembled = list() - while(processing.len) - var/atom/A = processing[1] - processing.Cut(1,2) + . = list() + var/i = 0 + while(i < length(processing)) + var/atom/A = processing[++i] if(!ignore_typecache[A.type]) processing += A.contents - assembled += A - return assembled + . += A + //Step-towards method of determining whether one atom can see another. Similar to viewers() /proc/can_see(atom/source, atom/target, length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate. @@ -566,82 +565,6 @@ Turf and target are separate in case you want to teleport some distance from a t else return 0 -//Repopulates sortedAreas list -/proc/repopulate_sorted_areas() - GLOB.sortedAreas = list() - - for(var/area/A in world) - GLOB.sortedAreas.Add(A) - - sortTim(GLOB.sortedAreas, /proc/cmp_name_asc) - -/area/proc/addSorted() - GLOB.sortedAreas.Add(src) - sortTim(GLOB.sortedAreas, /proc/cmp_name_asc) - -//Takes: Area type as a text string from a variable. -//Returns: Instance for the area in the world. -/proc/get_area_instance_from_text(areatext) - if(istext(areatext)) - areatext = text2path(areatext) - return GLOB.areas_by_type[areatext] - -//Takes: Area type as text string or as typepath OR an instance of the area. -//Returns: A list of all areas of that type in the world. -/proc/get_areas(areatype, subtypes=TRUE) - if(istext(areatype)) - areatype = text2path(areatype) - else if(isarea(areatype)) - var/area/areatemp = areatype - areatype = areatemp.type - else if(!ispath(areatype)) - return null - - var/list/areas = list() - if(subtypes) - var/list/cache = typecacheof(areatype) - for(var/V in GLOB.sortedAreas) - var/area/A = V - if(cache[A.type]) - areas += V - else - for(var/V in GLOB.sortedAreas) - var/area/A = V - if(A.type == areatype) - areas += V - return areas - -//Takes: Area type as text string or as typepath OR an instance of the area. -//Returns: A list of all turfs in areas of that type of that type in the world. -/proc/get_area_turfs(areatype, target_z = 0, subtypes=FALSE) - if(istext(areatype)) - areatype = text2path(areatype) - else if(isarea(areatype)) - var/area/areatemp = areatype - areatype = areatemp.type - else if(!ispath(areatype)) - return null - - var/list/turfs = list() - if(subtypes) - var/list/cache = typecacheof(areatype) - for(var/V in GLOB.sortedAreas) - var/area/A = V - if(!cache[A.type]) - continue - for(var/turf/T in A) - if(target_z == 0 || target_z == T.z) - turfs += T - else - for(var/V in GLOB.sortedAreas) - var/area/A = V - if(A.type != areatype) - continue - for(var/turf/T in A) - if(target_z == 0 || target_z == T.z) - turfs += T - return turfs - /proc/get_cardinal_dir(atom/A, atom/B) var/dx = abs(B.x - A.x) var/dy = abs(B.y - A.y) diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index a13a958ef7..2d5d2388ec 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -32,6 +32,8 @@ GLOBAL_VAR(world_map_error_log) GLOBAL_PROTECT(world_map_error_log) GLOBAL_VAR(subsystem_log) GLOBAL_PROTECT(subsystem_log) +GLOBAL_VAR(reagent_log) +GLOBAL_PROTECT(reagent_log) GLOBAL_VAR(world_crafting_log) GLOBAL_PROTECT(world_crafting_log) diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm index 8592383a4f..25a49c8d6b 100755 --- a/code/_onclick/hud/parallax.dm +++ b/code/_onclick/hud/parallax.dm @@ -146,6 +146,8 @@ /datum/hud/proc/update_parallax_motionblur(client/C, animatedir, new_parallax_movedir, matrix/newtransform) + if(!C) + return C.parallax_animate_timer = FALSE for(var/thing in C.parallax_layers) var/obj/screen/parallax_layer/L = thing @@ -167,7 +169,7 @@ /datum/hud/proc/update_parallax() var/client/C = mymob.client var/turf/posobj = get_turf(C.eye) - if(!posobj) + if(!posobj) return var/area/areaobj = posobj.loc diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 4ce0ccf361..ad1f869057 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -193,6 +193,13 @@ stat("[name]:", statclick) /datum/controller/configuration/proc/Get(entry_type) + var/datum/config_entry/E = GetEntryDatum(entry_type) + if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]") + log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]") + return + return E.config_entry_value + +/datum/controller/configuration/proc/GetEntryDatum(entry_type) var/datum/config_entry/E = entry_type var/entry_is_abstract = initial(E.abstract_type) == entry_type if(entry_is_abstract) @@ -200,10 +207,7 @@ E = entries_by_type[entry_type] if(!E) CRASH("Missing config entry for [entry_type]!") - if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]") - log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]") - return - return E.config_entry_value + return E /datum/controller/configuration/proc/Set(entry_type, new_val) var/datum/config_entry/E = entry_type diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 6efc9eab12..a3bc47ac91 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -249,6 +249,18 @@ /datum/config_entry/number/movedelay/walk_delay +/datum/config_entry/number/movedelay/sprint_speed_increase + config_entry_value = 1 + +/datum/config_entry/number/movedelay/sprint_buffer_max + config_entry_value = 42 + +/datum/config_entry/number/movedelay/sprint_stamina_cost + config_entry_value = 0.7 + +/datum/config_entry/number/movedelay/sprint_buffer_regen_per_ds + config_entry_value = 0.3 + /////////////////////////////////////////////////Outdated move delay /datum/config_entry/number/outdated_movedelay deprecated_by = /datum/config_entry/keyed_list/multiplicative_movespeed diff --git a/code/controllers/subsystem/fail2topic.dm b/code/controllers/subsystem/fail2topic.dm index a589ae2462..d17cce70f9 100644 --- a/code/controllers/subsystem/fail2topic.dm +++ b/code/controllers/subsystem/fail2topic.dm @@ -31,8 +31,8 @@ SUBSYSTEM_DEF(fail2topic) return ..() /datum/controller/subsystem/fail2topic/fire() - while (rate_limiting.len) - var/ip = rate_limiting[1] + for(var/i in 1 to length(rate_limiting)) + var/ip = rate_limiting[i] var/last_attempt = rate_limiting[ip] if (world.time - last_attempt > rate_limit) diff --git a/code/datums/brain_damage/brain_trauma.dm b/code/datums/brain_damage/brain_trauma.dm index 1aa1341c9c..eaaab8da45 100644 --- a/code/datums/brain_damage/brain_trauma.dm +++ b/code/datums/brain_damage/brain_trauma.dm @@ -14,7 +14,7 @@ var/can_gain = TRUE var/random_gain = TRUE //can this be gained through random traumas? var/resilience = TRAUMA_RESILIENCE_BASIC //how hard is this to cure? - var/clonable = TRUE // will this transfer if the brain is cloned? + var/clonable = TRUE // will this transfer if the brain is cloned? - currently has no effect /datum/brain_trauma/Destroy() if(brain && brain.traumas) diff --git a/code/datums/components/dejavu.dm b/code/datums/components/dejavu.dm new file mode 100644 index 0000000000..1bad589c97 --- /dev/null +++ b/code/datums/components/dejavu.dm @@ -0,0 +1,107 @@ +/** + * A component to reset the parent to its previous state after some time passes + */ +/datum/component/dejavu + /// The turf the parent was on when this components was applied, they get moved back here after the duration + var/turf/starting_turf + /// Determined by the type of the parent so different behaviours can happen per type + var/rewind_type + /// How many rewinds will happen before the effect ends + var/rewinds_remaining + /// How long to wait between each rewind + var/rewind_interval + + /// The starting value of clone loss at the beginning of the effect + var/clone_loss = 0 + /// The starting value of toxin loss at the beginning of the effect + var/tox_loss = 0 + /// The starting value of oxygen loss at the beginning of the effect + var/oxy_loss = 0 + /// The starting value of brain loss at the beginning of the effect + var/brain_loss = 0 + /// The starting value of brute loss at the beginning of the effect + /// This only applies to simple animals + var/brute_loss + /// The starting value of integrity at the beginning of the effect + /// This only applies to objects + var/integrity + /// A list of body parts saved at the beginning of the effect + var/list/datum/saved_bodypart/saved_bodyparts + +/datum/component/dejavu/Initialize(rewinds = 1, interval = 10 SECONDS) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + starting_turf = get_turf(parent) + rewinds_remaining = rewinds + rewind_interval = interval + + if(isliving(parent)) + var/mob/living/L = parent + clone_loss = L.getCloneLoss() + tox_loss = L.getToxLoss() + oxy_loss = L.getOxyLoss() + brain_loss = L.getOrganLoss(ORGAN_SLOT_BRAIN) + rewind_type = .proc/rewind_living + + if(iscarbon(parent)) + var/mob/living/carbon/C = parent + saved_bodyparts = C.save_bodyparts() + rewind_type = .proc/rewind_carbon + + else if(isanimal(parent)) + var/mob/living/simple_animal/M = parent + brute_loss = M.bruteloss + rewind_type = .proc/rewind_animal + + else if(isobj(parent)) + var/obj/O = parent + integrity = O.obj_integrity + rewind_type = .proc/rewind_obj + + addtimer(CALLBACK(src, rewind_type), rewind_interval) + +/datum/component/dejavu/Destroy() + starting_turf = null + saved_bodyparts = null + return ..() + +/datum/component/dejavu/proc/rewind() + to_chat(parent, "You remember a time not so long ago...") + + //comes after healing so new limbs comically drop to the floor + if(starting_turf) + var/atom/movable/master = parent + master.forceMove(starting_turf) + + rewinds_remaining -- + if(rewinds_remaining) + addtimer(CALLBACK(src, rewind_type), rewind_interval) + else + to_chat(parent, "But the memory falls out of your reach.") + qdel(src) + +/datum/component/dejavu/proc/rewind_living() + var/mob/living/master = parent + master.setCloneLoss(clone_loss) + master.setToxLoss(tox_loss) + master.setOxyLoss(oxy_loss) + master.setOrganLoss(ORGAN_SLOT_BRAIN, brain_loss) + rewind() + +/datum/component/dejavu/proc/rewind_carbon() + if(saved_bodyparts) + var/mob/living/carbon/master = parent + master.apply_saved_bodyparts(saved_bodyparts) + rewind_living() + +/datum/component/dejavu/proc/rewind_animal() + var/mob/living/simple_animal/master = parent + master.bruteloss = brute_loss + master.updatehealth() + rewind_living() + +/datum/component/dejavu/proc/rewind_obj() + var/obj/master = parent + master.obj_integrity = integrity + rewind() diff --git a/code/datums/components/virtual_reality.dm b/code/datums/components/virtual_reality.dm index 2f0405af2e..63e4f4f092 100644 --- a/code/datums/components/virtual_reality.dm +++ b/code/datums/components/virtual_reality.dm @@ -229,7 +229,7 @@ UnregisterSignal(mastermind, COMSIG_PRE_MIND_TRANSFER) mastermind = null if(cleanup) - var/obj/effect/vr_clean_master/cleanbot = locate() in get_area(M) + var/obj/effect/vr_clean_master/cleanbot = locate() in get_base_area(M) if(cleanbot) LAZYOR(cleanbot.corpse_party, M) qdel(src) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index ebfba43852..1622cc9dbf 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -236,7 +236,12 @@ G.fields["fingerprint"] = md5(H.dna.uni_identity) G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" - G.fields["sex"] = H.gender + if(H.gender == MALE) + G.fields["gender"] = "Male" + else if(H.gender == FEMALE) + G.fields["gender"] = "Female" + else + G.fields["gender"] = "Other" G.fields["photo_front"] = photo_front G.fields["photo_side"] = photo_side general += G @@ -274,7 +279,12 @@ L.fields["name"] = H.real_name L.fields["rank"] = H.mind.assigned_role L.fields["age"] = H.age - L.fields["sex"] = H.gender + if(H.gender == MALE) + G.fields["gender"] = "Male" + else if(H.gender == FEMALE) + G.fields["gender"] = "Female" + else + G.fields["gender"] = "Other" L.fields["blood_type"] = H.dna.blood_type L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.struc_enzymes diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index 6b72f2fdfc..1c21fb9528 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -110,7 +110,7 @@ // Randomly pick a symptom to activate. /datum/disease/advance/stage_act() ..() - if(carrier) + if(carrier || QDELETED(src)) // Could be cured in parent call. return if(symptoms && symptoms.len) diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm index 559d8f4754..6946a6a1d8 100644 --- a/code/datums/diseases/advance/symptoms/choking.dm +++ b/code/datums/diseases/advance/symptoms/choking.dm @@ -41,7 +41,7 @@ Bonus suppress_warning = TRUE /datum/symptom/choking/Activate(datum/disease/advance/A) - if(!..()) + if(!..() || HAS_TRAIT(A.affected_mob,TRAIT_NOBREATH)) return var/mob/living/M = A.affected_mob switch(A.stage) @@ -112,7 +112,7 @@ Bonus power = 2 /datum/symptom/asphyxiation/Activate(datum/disease/advance/A) - if(!..()) + if(!..() || HAS_TRAIT(A.affected_mob,TRAIT_NOBREATH)) return var/mob/living/M = A.affected_mob switch(A.stage) diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm index b1767d7cb5..62c64159d1 100644 --- a/code/datums/diseases/advance/symptoms/cough.dm +++ b/code/datums/diseases/advance/symptoms/cough.dm @@ -50,7 +50,7 @@ BONUS symptom_delay_max = 10 /datum/symptom/cough/Activate(datum/disease/advance/A) - if(!..()) + if(!..() || HAS_TRAIT(A.affected_mob,TRAIT_NOBREATH)) return var/mob/living/M = A.affected_mob switch(A.stage) diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm index 5d4d40fb95..9f1696c963 100644 --- a/code/datums/diseases/advance/symptoms/sneeze.dm +++ b/code/datums/diseases/advance/symptoms/sneeze.dm @@ -39,7 +39,7 @@ Bonus suppress_warning = TRUE /datum/symptom/sneeze/Activate(datum/disease/advance/A) - if(!..()) + if(!..() || HAS_TRAIT(A.affected_mob,TRAIT_NOBREATH)) return var/mob/living/M = A.affected_mob switch(A.stage) diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index 230a074bb1..71a5bcb99e 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -94,7 +94,7 @@ STI KALY - blind var/area/thearea = pick(theareas) var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) + for(var/turf/T in thearea) if(T.z != affected_mob.z) continue if(T.name == "space") diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 67dbbdfef7..5fa991c10c 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -92,7 +92,15 @@ . = "" var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS) - L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2) + switch(holder.gender) + if(MALE) + L[DNA_GENDER_BLOCK] = construct_block(G_MALE, 4) + if(FEMALE) + L[DNA_GENDER_BLOCK] = construct_block(G_FEMALE, 4) + if(PLURAL) + L[DNA_GENDER_BLOCK] = construct_block(G_PLURAL, 4) + else + L[DNA_GENDER_BLOCK] = construct_block(G_NEUTER, 4) if(ishuman(holder)) var/mob/living/carbon/human/H = holder if(!GLOB.hair_styles_list.len) @@ -165,7 +173,15 @@ if(DNA_EYE_COLOR_BLOCK) setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color)) if(DNA_GENDER_BLOCK) - setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2)) + switch(H.gender) + if(MALE) + setblock(uni_identity, blocknumber, construct_block(G_MALE, 4)) + if(FEMALE) + setblock(uni_identity, blocknumber, construct_block(G_FEMALE, 4)) + if(PLURAL) + setblock(uni_identity, blocknumber, construct_block(G_PLURAL, 4)) + else + setblock(uni_identity, blocknumber, construct_block(G_NEUTER, 4)) if(DNA_FACIAL_HAIR_STYLE_BLOCK) setblock(uni_identity, blocknumber, construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len)) if(DNA_HAIR_STYLE_BLOCK) @@ -307,7 +323,16 @@ /mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) if(!has_dna()) return - gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE + + switch(deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 4)) + if(G_MALE) + gender = MALE + if(G_FEMALE) + gender = FEMALE + if(G_PLURAL) + gender = PLURAL + else + gender = NEUTER /mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) ..() diff --git a/code/datums/elements/dusts_on_leaving_area.dm b/code/datums/elements/dusts_on_leaving_area.dm new file mode 100644 index 0000000000..9527e1fd3a --- /dev/null +++ b/code/datums/elements/dusts_on_leaving_area.dm @@ -0,0 +1,28 @@ +/datum/element/dusts_on_leaving_area + element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE + id_arg_index = 2 + var/list/attached_mobs = list() + var/list/area_types = list() + +/datum/element/dusts_on_leaving_area/Attach(datum/target,types) + . = ..() + if(!ismob(target)) + return ELEMENT_INCOMPATIBLE + attached_mobs += target + area_types = types + START_PROCESSING(SSprocessing,src) + +/datum/element/dusts_on_leaving_area/Detach(mob/M) + . = ..() + if(M in attached_mobs) + attached_mobs -= M + if(!attached_mobs.len) + STOP_PROCESSING(SSprocessing,src) + +/datum/element/dusts_on_leaving_area/process() + for(var/m in attached_mobs) + var/mob/M = m + var/area/A = get_area(M) + if(!(A.type in area_types)) + M.dust(force = TRUE) + Detach(M) diff --git a/code/datums/traits/_quirk.dm b/code/datums/traits/_quirk.dm index 12e34b0c90..d68b11135f 100644 --- a/code/datums/traits/_quirk.dm +++ b/code/datums/traits/_quirk.dm @@ -15,6 +15,7 @@ /datum/quirk/New(mob/living/quirk_mob, spawn_effects) if(!quirk_mob || (human_only && !ishuman(quirk_mob)) || quirk_mob.has_quirk(type)) qdel(src) + return quirk_holder = quirk_mob SSquirks.quirk_objects += src to_chat(quirk_holder, gain_text) diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm index b74f24c469..0d4a6a7b3f 100644 --- a/code/datums/traits/good.dm +++ b/code/datums/traits/good.dm @@ -201,13 +201,12 @@ medical_record_text = "Patient's blood tests report an abnormal concentration of red blood cells in their bloodstream." /datum/quirk/bloodpressure/add() - var/mob/living/M = quirk_holder - M.blood_ratio = 1.2 - M.blood_volume += 150 + quirk_holder.blood_ratio = 1.2 + quirk_holder.blood_volume += 150 /datum/quirk/bloodpressure/remove() - var/mob/living/M = quirk_holder - M.blood_ratio = 1 + if(quirk_holder) + quirk_holder.blood_ratio = 1 /datum/quirk/night_vision name = "Night Vision" diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index c5217d8e4b..b19c6a71f7 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -400,3 +400,12 @@ /datum/quirk/blindness/remove() quirk_holder?.cure_blind(ROUNDSTART_TRAIT) + +/datum/quirk/coldblooded + name = "Cold-blooded" + desc = "Your body doesn't create its own internal heat, requiring external heat regulation." + value = -2 + medical_record_text = "Patient is ectothermic." + mob_trait = TRAIT_COLDBLOODED + gain_text = "You feel cold-blooded." + lose_text = "You feel more warm-blooded." diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index d19efe486d..ab2a69e7e9 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -104,15 +104,6 @@ gain_text = "You desire to be hurt." lose_text = "Pain has become less exciting for you." -/datum/quirk/coldblooded - name = "Cold-blooded" - desc = "Your body doesn't create its own internal heat, requiring external heat regulation." - value = 0 - medical_record_text = "Patient is ectothermic." - mob_trait = TRAIT_COLDBLOODED - gain_text = "You feel cold-blooded." - lose_text = "You feel more warm-blooded." - /datum/quirk/alcohol_intolerance name = "Alcohol Intolerance" desc = "You take toxin damage from alcohol rather than getting drunk." diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm index a3b666dcc6..01b9facbb8 100644 --- a/code/datums/weather/weather.dm +++ b/code/datums/weather/weather.dm @@ -50,7 +50,10 @@ stage = STARTUP_STAGE var/list/affectareas = list() for(var/V in get_areas(area_type)) - affectareas += V + var/area/A = V + affectareas |= A + if(A.sub_areas) + affectareas |= A.sub_areas for(var/V in protected_areas) affectareas -= get_areas(V) for(var/V in affectareas) diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm index 6eb4dc04db..0c4715e27e 100644 --- a/code/datums/wires/airalarm.dm +++ b/code/datums/wires/airalarm.dm @@ -46,7 +46,7 @@ A.mode = 1 // AALARM_MODE_SCRUB A.apply_mode() if(WIRE_ALARM) // Clear alarms. - var/area/AA = get_area(A) + var/area/AA = get_base_area(A) if(AA.atmosalert(0, holder)) A.post_alert(0) A.update_icon() @@ -68,7 +68,7 @@ A.mode = 3 // AALARM_MODE_PANIC A.apply_mode() if(WIRE_ALARM) // Post alarm. - var/area/AA = get_area(A) + var/area/AA = get_base_area(A) if(AA.atmosalert(2, holder)) A.post_alert(2) A.update_icon() \ No newline at end of file diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 2d256aad27..99b8165306 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -63,6 +63,15 @@ var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default? var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with +/** + * These two vars allow for multiple unique areas to be linked to a master area + * and share some functionalities such as APC powernet nodes, fire alarms etc, without sacrificing + * their own flags, statuses, variables and more snowflakes. + * Friendly reminder: no map edited areas. + */ + var/list/area/sub_areas //list of typepaths of the areas you wish to link here, will be replaced with a list of references on mapload. + var/area/base_area //The area we wish to use in place of src for certain actions such as APC area linking. + var/nightshift_public_area = NIGHTSHIFT_AREA_NONE //considered a public area for nightshift /*Adding a wizard area teleport list because motherfucking lag -- Urist*/ @@ -123,10 +132,35 @@ GLOBAL_LIST_EMPTY(teleportlocs) reg_in_areas_in_z() + //so far I'm only implementing it on mapped unique areas, it's easier this way. + if(unique && sub_areas) + if(type in sub_areas) + WARNING("\"[src]\" typepath found inside its own sub-areas list, please make sure it doesn't share its parent type initial sub-areas value.") + sub_areas = null + else + var/paths = sub_areas.Copy() + sub_areas = null + for(var/type in paths) + var/area/A = GLOB.areas_by_type[type] + if(!A) //By chance an area not loaded in the current world, no warning report. + continue + if(A == src) + WARNING("\"[src]\" area a attempted to link with itself.") + continue + if(A.base_area) + WARNING("[src] attempted to link with [A] while the latter is already linked to another area ([A.base_area]).") + continue + LAZYADD(sub_areas, A) + A.base_area = src + else if(LAZYLEN(sub_areas)) + WARNING("sub-areas are currently not supported for non-unique areas such as [src].") + sub_areas = null + return INITIALIZE_HINT_LATELOAD /area/LateInitialize() - power_change() // all machines set to current power level, also updates icon + if(!base_area) //we don't want to run it twice. + power_change() // all machines set to current power level, also updates icon /area/proc/reg_in_areas_in_z() if(contents.len) @@ -149,6 +183,19 @@ GLOBAL_LIST_EMPTY(teleportlocs) /area/Destroy() if(GLOB.areas_by_type[type] == src) GLOB.areas_by_type[type] = null + if(base_area) + LAZYREMOVE(base_area, src) + base_area = null + if(sub_areas) + for(var/i in sub_areas) + var/area/A = i + A.base_area = null + sub_areas -= A + if(A.requires_power) + A.power_light = FALSE + A.power_equip = FALSE + A.power_environ = FALSE + INVOKE_ASYNC(A, .proc/power_change) STOP_PROCESSING(SSobj, src) return ..() @@ -214,9 +261,12 @@ GLOBAL_LIST_EMPTY(teleportlocs) var/datum/computer_file/program/alarm_monitor/p = item p.cancelAlarm("Atmosphere", src, source) - src.atmosalm = danger_level - return 1 - return 0 + atmosalm = danger_level + for(var/i in sub_areas) + var/area/A = i + A.atmosalm = danger_level + return TRUE + return FALSE /area/proc/ModifyFiredoors(opening) if(firedoors) @@ -241,11 +291,8 @@ GLOBAL_LIST_EMPTY(teleportlocs) return if (!fire) - set_fire_alarm_effect() + set_fire_alarm_effects(TRUE) ModifyFiredoors(FALSE) - for(var/item in firealarms) - var/obj/machinery/firealarm/F = item - F.update_icon() for (var/item in GLOB.alert_consoles) var/obj/machinery/computer/station_alert/a = item @@ -264,11 +311,8 @@ GLOBAL_LIST_EMPTY(teleportlocs) /area/proc/firereset(obj/source) if (fire) - unset_fire_alarm_effects() + set_fire_alarm_effects(FALSE) ModifyFiredoors(TRUE) - for(var/item in firealarms) - var/obj/machinery/firealarm/F = item - F.update_icon() for (var/item in GLOB.silicon_mobs) var/mob/living/silicon/aiPlayer = item @@ -300,9 +344,9 @@ GLOBAL_LIST_EMPTY(teleportlocs) return //Trigger alarm effect - set_fire_alarm_effect() + set_fire_alarm_effects(TRUE) //Lockdown airlocks - for(var/obj/machinery/door/DOOR in src) + for(var/obj/machinery/door/DOOR in get_sub_areas_contents(src)) close_and_lock_door(DOOR) for (var/i in GLOB.silicon_mobs) @@ -311,23 +355,20 @@ GLOBAL_LIST_EMPTY(teleportlocs) //Cancel silicon alert after 1 minute addtimer(CALLBACK(SILICON, /mob/living/silicon.proc/cancelAlarm,"Burglar",src,trigger), 600) -/area/proc/set_fire_alarm_effect() - fire = TRUE +/area/proc/set_fire_alarm_effects(boolean) + fire = boolean + for(var/i in sub_areas) + var/area/A = i + A.fire = boolean mouse_opacity = MOUSE_OPACITY_TRANSPARENT for(var/alarm in firealarms) var/obj/machinery/firealarm/F = alarm F.update_fire_light(fire) - for(var/obj/machinery/light/L in src) + F.update_icon() + for(var/obj/machinery/light/L in get_sub_areas_contents(src)) L.update() -/area/proc/unset_fire_alarm_effects() - fire = FALSE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - for(var/alarm in firealarms) - var/obj/machinery/firealarm/F = alarm - F.update_fire_light(fire) - for(var/obj/machinery/light/L in src) - L.update() +/area/proc/updateicon() /** * Update the icon state of the area * @@ -380,26 +421,35 @@ GLOBAL_LIST_EMPTY(teleportlocs) /area/proc/power_change() for(var/obj/machinery/M in src) // for each machine in the area M.power_change() // reverify power status (to update icons etc.) + if(sub_areas) + for(var/i in sub_areas) + var/area/A = i + A.power_light = power_light + A.power_equip = power_equip + A.power_environ = power_environ + INVOKE_ASYNC(A, .proc/power_change) update_icon() /area/proc/usage(chan) - var/used = 0 switch(chan) if(LIGHT) - used += used_light + . += used_light if(EQUIP) - used += used_equip + . += used_equip if(ENVIRON) - used += used_environ + . += used_environ if(TOTAL) - used += used_light + used_equip + used_environ + . += used_light + used_equip + used_environ if(STATIC_EQUIP) - used += static_equip + . += static_equip if(STATIC_LIGHT) - used += static_light + . += static_light if(STATIC_ENVIRON) - used += static_environ - return used + . += static_environ + if(sub_areas) + for(var/i in sub_areas) + var/area/A = i + . += A.usage(chan) /area/proc/addStaticPower(value, powerchannel) switch(powerchannel) @@ -414,6 +464,10 @@ GLOBAL_LIST_EMPTY(teleportlocs) used_equip = 0 used_light = 0 used_environ = 0 + if(sub_areas) + for(var/i in sub_areas) + var/area/A = i + A.clear_usage() /area/proc/use_power(amount, chan) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 829b66a060..42ccc4bbba 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -163,7 +163,7 @@ /atom/movable/proc/Move_Pulled(atom/A) if(!pulling) return - if(pulling.anchored || !pulling.Adjacent(src)) + if(pulling.anchored || pulling.move_resist > move_force || !pulling.Adjacent(src)) stop_pulling() return if(isliving(pulling)) @@ -190,7 +190,7 @@ log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.") stop_pulling() return - if(pulling.anchored) + if(pulling.anchored || pulling.move_resist > move_force) stop_pulling() return diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index df4a38cf60..718ed2c103 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -5,6 +5,7 @@ /datum/game_mode/traitor/bros name = "traitor+brothers" config_tag = "traitorbro" + required_players = 25 restricted_jobs = list("AI", "Cyborg") protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index d010da465e..b296ba7273 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -12,7 +12,7 @@ var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai) for(var/area/A in world) - if( !A.requires_power || A.always_unpowered ) + if( !A.requires_power || A.always_unpowered || A.base_area) continue var/skip = 0 @@ -61,8 +61,9 @@ S.output_attempt = 1 S.update_icon() S.power_change() + for(var/area/A in world) - if(!istype(A, /area/space) && !istype(A, /area/shuttle) && !istype(A, /area/arrival)) + if(!istype(A, /area/space) && !istype(A, /area/shuttle) && !istype(A, /area/arrival) && !A.always_unpowered && !A.base_area) A.power_light = TRUE A.power_equip = TRUE A.power_environ = TRUE diff --git a/code/game/gamemodes/gangs/dominator.dm b/code/game/gamemodes/gangs/dominator.dm index 8c1272dcbd..db060a6539 100644 --- a/code/game/gamemodes/gangs/dominator.dm +++ b/code/game/gamemodes/gangs/dominator.dm @@ -101,7 +101,7 @@ playsound(loc, 'sound/items/timer.ogg', 10, 0) if(!warned && (time_remaining < 180)) warned = TRUE - var/area/domloc = get_area(loc) + var/area/domloc = get_base_area(loc) gang.message_gangtools("Less than 3 minutes remains in hostile takeover. Defend your dominator at [domloc.map_name]!") for(var/G in GLOB.gangs) var/datum/team/gang/tempgang = G @@ -179,7 +179,7 @@ if((tempgang.domination_time != NOT_DOMINATING) || !tempgang.dom_attempts || !in_range(src, user) || !isturf(loc)) return 0 - var/area/A = get_area(loc) + var/area/A = get_base_area(loc) var/locname = A.map_name gang = tempgang diff --git a/code/game/gamemodes/gangs/gang_decals.dm b/code/game/gamemodes/gangs/gang_decals.dm index 6e5cb58891..7aaed769d9 100644 --- a/code/game/gamemodes/gangs/gang_decals.dm +++ b/code/game/gamemodes/gangs/gang_decals.dm @@ -19,7 +19,7 @@ return INITIALIZE_HINT_QDEL gang = G var/newcolor = G.color - var/area/territory = get_area(src) + var/area/territory = get_base_area(src) icon_state = G.name G.new_territories |= list(territory.type = territory.name) //If this isn't tagged by a specific gangster there's no bonus income. @@ -27,7 +27,7 @@ /obj/effect/decal/cleanable/crayon/gang/Destroy() if(gang) - var/area/territory = get_area(src) + var/area/territory = get_base_area(src) gang.territories -= territory.type gang.new_territories -= territory.type gang.lost_territories |= list(territory.type = territory.name) diff --git a/code/game/gamemodes/gangs/gang_items.dm b/code/game/gamemodes/gangs/gang_items.dm index 2e9ca4dcc0..688af3beea 100644 --- a/code/game/gamemodes/gangs/gang_items.dm +++ b/code/game/gamemodes/gangs/gang_items.dm @@ -401,7 +401,7 @@ datum/gang_item/equipment/gangsheild return "This device requires a 5x5 area clear of walls to FUNCTION. (Estimated Takeover Time: [round(gang.determine_domination_time()/60,0.1)] minutes)" /datum/gang_item/equipment/dominator/purchase(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool) - var/area/userarea = get_area(user) + var/area/userarea = get_base_area(user) if(!(userarea.type in gang.territories|gang.new_territories)) to_chat(user,"The dominator can be spawned only on territory controlled by your gang!") return FALSE diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 6d681f8108..cfb4c9a120 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -21,16 +21,16 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event //Meteor spawning global procs /////////////////////////////// -/proc/spawn_meteors(number = 10, list/meteortypes) +/proc/spawn_meteors(number = 10, list/meteortypes, dir) for(var/i = 0; i < number; i++) - spawn_meteor(meteortypes) + spawn_meteor(meteortypes, dir) -/proc/spawn_meteor(list/meteortypes) +/proc/spawn_meteor(list/meteortypes, dir) var/turf/pickedstart var/turf/pickedgoal var/max_i = 10//number of tries to spawn meteor. while(!isspaceturf(pickedstart)) - var/startSide = pick(GLOB.cardinals) + var/startSide = dir || pick(GLOB.cardinals) var/startZ = pick(SSmapping.levels_by_trait(ZTRAIT_STATION)) pickedstart = spaceDebrisStartLoc(startSide, startZ) pickedgoal = spaceDebrisFinishLoc(startSide, startZ) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index f99fe5c3e4..b7003e4f1e 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -527,7 +527,7 @@ GLOBAL_LIST_EMPTY(possible_items) else if(targetinfo.check_special_completion(I))//Returns 1 by default. Items with special checks will return 1 if the conditions are fulfilled. return TRUE - if(targetinfo && I.type in targetinfo.altitems) //Ok, so you don't have the item. Do you have an alternative, at least? + if(targetinfo && (I.type in targetinfo.altitems)) //Ok, so you don't have the item. Do you have an alternative, at least? if(targetinfo.check_special_completion(I))//Yeah, we do! Don't return 0 if we don't though - then you could fail if you had 1 item that didn't pass and got checked first! return TRUE return FALSE diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index bef5effb54..22c1ff811c 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -319,7 +319,8 @@ if(status) change_msg = "reactivates" triggerCameraAlarm() - addtimer(CALLBACK(src, .proc/cancelCameraAlarm), 100) + if(!QDELETED(src)) //We'll be doing it anyway in destroy + addtimer(CALLBACK(src, .proc/cancelCameraAlarm), 100) if(displaymessage) if(user) visible_message("[user] [change_msg] [src]!") diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index fc6cac785a..991577e123 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -46,7 +46,7 @@ var/area/a = loc.loc // Gets our locations location, like a dream within a dream if(!isarea(a)) return - if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power! + if(!a.powered(EQUIP)) // There's no APC in this area, don't try to cheat power! to_chat(user, "[src] blinks red as you try to insert the cell!") return if(!user.transferItemToLoc(W,src)) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 711b221c54..afb882598e 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -4,7 +4,7 @@ //Potential replacement for genetics revives or something I dunno (?) #define CLONE_INITIAL_DAMAGE 150 //Clones in clonepods start with 150 cloneloss damage and 150 brainloss damage, thats just logical -#define MINIMUM_HEAL_LEVEL 40 +#define MINIMUM_HEAL_LEVEL 20 #define SPEAK(message) radio.talk_into(src, message, radio_channel) @@ -61,18 +61,15 @@ QDEL_LIST(unattached_flesh) . = ..() -/obj/machinery/clonepod/RefreshParts() +/obj/machinery/clonepod/RefreshParts() speed_coeff = 0 efficiency = 0 for(var/obj/item/stock_parts/scanning_module/S in component_parts) efficiency += S.rating for(var/obj/item/stock_parts/manipulator/P in component_parts) - speed_coeff += P.rating - heal_level = (efficiency * 15) + 10 - if(heal_level < MINIMUM_HEAL_LEVEL) - heal_level = MINIMUM_HEAL_LEVEL - if(heal_level > 100) - heal_level = 100 + speed_coeff += (P.rating / 2) + speed_coeff = max(1, speed_coeff) + heal_level = CLAMP((efficiency * 10) + 10, MINIMUM_HEAL_LEVEL, 100) //The return of data disks?? Just for transferring between genetics machine/cloning machine. //TO-DO: Make the genetics machine accept them. @@ -169,9 +166,7 @@ var/mob/living/carbon/human/H = new /mob/living/carbon/human(src) H.hardset_dna(ui, se, H.real_name, null, mrace, features) - - if(prob(50 - efficiency*10)) //Chance to give a bad mutation. - H.randmutb() //100% bad mutation. Can be cured with mutadone. + H.randmutb() //100% bad mutation. Can be cured with mutadone. H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment. occupant = H diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index a238c4a451..b007bc0161 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -119,6 +119,9 @@ if(istype(P, /obj/item/circuitboard/machine)) var/obj/item/circuitboard/machine/B = P + if(!B.build_path) + to_chat(user, "This circuitboard seems to be broken.") + return if(!anchored && B.needs_anchored) to_chat(user, "The frame needs to be secured first!") return diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 91306585b8..c6b4f2fcf5 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -406,12 +406,11 @@ lying_prev = 0 /obj/machinery/jukebox/proc/dance_over() - SSjukeboxes.removejukebox(SSjukeboxes.findjukeboxindex(src)) + var/position = SSjukeboxes.findjukeboxindex(src) + if(!position) + return + SSjukeboxes.removejukebox(position) STOP_PROCESSING(SSobj, src) - for(var/mob/living/L in rangers) - if(!L || !L.client) - continue - L.stop_sound_channel(CHANNEL_JUKEBOX) rangers = list() /obj/machinery/jukebox/disco/dance_over() diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index ad0f372530..9db98b8314 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -288,9 +288,10 @@ return operating = TRUE - do_animate("closing") layer = closingLayer + if(!safe) + crush() sleep(5) density = TRUE sleep(5) @@ -302,8 +303,6 @@ update_freelook_sight() if(safe) CheckForMobs() - else - crush() return 1 /obj/machinery/door/proc/CheckForMobs() diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index f5bf8c8a1b..cb133978b2 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -44,7 +44,7 @@ /obj/machinery/door/firedoor/proc/CalculateAffectingAreas() remove_from_areas() - affecting_areas = get_adjacent_open_areas(src) | get_area(src) + affecting_areas = get_adjacent_open_areas(src) | get_base_area(src) for(var/I in affecting_areas) var/area/A = I LAZYADD(A.firedoors, src) diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 1ef3fc0a74..5555e05eb0 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -44,7 +44,7 @@ pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 update_icon() - myarea = get_area(src) + myarea = get_base_area(src) LAZYADD(myarea.firealarms, src) /obj/machinery/firealarm/Destroy() @@ -124,7 +124,7 @@ if(!is_operational() || (last_alarm+FIREALARM_COOLDOWN > world.time)) return last_alarm = world.time - var/area/A = get_area(src) + var/area/A = get_base_area(src) A.firealert(src) playsound(loc, 'goon/sound/machinery/FireAlarm.ogg', 75) if(user) @@ -133,7 +133,7 @@ /obj/machinery/firealarm/proc/reset(mob/user) if(!is_operational()) return - var/area/A = get_area(src) + var/area/A = get_base_area(src) A.firereset(src) if(user) log_game("[user] reset a fire alarm at [COORD(src)]") @@ -142,7 +142,7 @@ if(buildstage != 2) return ..() add_fingerprint(user) - var/area/A = get_area(src) + var/area/A = get_base_area(src) if(A.fire) reset(user) else @@ -198,7 +198,7 @@ return else if(W.force) //hit and turn it on ..() - var/area/A = get_area(src) + var/area/A = get_base_area(src) if(!A.fire) alarm() return @@ -322,7 +322,7 @@ /obj/machinery/firealarm/partyalarm/reset() if (stat & (NOPOWER|BROKEN)) return - var/area/A = get_area(src) + var/area/A = get_base_area(src) if (!A || !A.party) return A.party = FALSE @@ -331,7 +331,7 @@ /obj/machinery/firealarm/partyalarm/alarm() if (stat & (NOPOWER|BROKEN)) return - var/area/A = get_area(src) + var/area/A = get_base_area(src) if (!A || A.party || A.name == "Space") return A.party = TRUE diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 2211397f3e..f777c893f8 100755 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -70,7 +70,7 @@ //Checks to make sure he's not in space doing it, and that the area got proper power. var/area/a = get_area(src) - if(!isarea(a) || a.power_equip == 0) + if(!a || !a.powered(EQUIP)) to_chat(user, "[src] blinks red as you try to insert [G].") return 1 diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index fdb620cc67..5a907804ce 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -283,7 +283,7 @@ /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_charge() if(equip_ready) //disabled return - var/area/A = get_area(chassis) + var/area/A = get_base_area(chassis) var/pow_chan = get_power_channel(A) if(pow_chan) return 1000 //making magic @@ -328,7 +328,7 @@ occupant_message("No powercell detected.") return if(cur_charge < chassis.cell.maxcharge) - var/area/A = get_area(chassis) + var/area/A = get_base_area(chassis) if(A) var/pow_chan for(var/c in list(EQUIP,ENVIRON,LIGHT)) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index f556a75434..1dfd5c4143 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -49,6 +49,7 @@ var/lights = FALSE var/lights_power = 6 var/last_user_hud = 1 // used to show/hide the mecha hud while preserving previous preference + var/completely_disabled = FALSE //stops the mech from doing anything var/breach_time = 0 var/recharge_rate = 0 @@ -431,6 +432,8 @@ return if(!locate(/turf) in list(target,target.loc)) // Prevents inventory from being drilled return + if(completely_disabled) + return if(phasing) occupant_message("Unable to interact with objects while phasing") return @@ -508,6 +511,8 @@ return 1 /obj/mecha/relaymove(mob/user,direction) + if(completely_disabled) + return if(!direction) return if(user != occupant) //While not "realistic", this piece is player friendly. diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm index ddc805f3ff..05077bf898 100644 --- a/code/game/objects/effects/effect_system/effect_system.dm +++ b/code/game/objects/effects/effect_system/effect_system.dm @@ -48,6 +48,8 @@ would spawn and follow the beaker, even if it is carried or thrown. holder = atom /datum/effect_system/proc/start() + if(QDELETED(src)) + return for(var/i in 1 to number) if(total_effects > 20) return @@ -69,7 +71,8 @@ would spawn and follow the beaker, even if it is carried or thrown. for(var/j in 1 to steps_amt) sleep(5) step(E,direction) - addtimer(CALLBACK(src, .proc/decrement_total_effect), 20) + if(!QDELETED(src)) + addtimer(CALLBACK(src, .proc/decrement_total_effect), 20) /datum/effect_system/proc/decrement_total_effect() total_effects-- diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index aabf9acafa..38a1a6089e 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -126,7 +126,7 @@ T.PlaceOnTop(/turf/open/floor/plating/foam, flags = CHANGETURF_INHERIT_AIR) for(var/direction in GLOB.cardinals) var/turf/cardinal_turf = get_step(T, direction) - if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf! + if(get_base_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf! new/obj/structure/foamedmetal(T) break flick("[icon_state]-disolve", src) diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 8f09827bd2..3d63f4a553 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -456,7 +456,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) if(!SSmapping.station_room_templates[t]) log_world("Station room spawner placed at ([T.x], [T.y], [T.z]) has invalid ruin name of \"[t]\" in its list") templates -= t - template_name = pickweight(templates) + template_name = pickweightAllowZero(templates) if(!template_name) GLOB.stationroom_landmarks -= src qdel(src) @@ -485,4 +485,4 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) // Landmark for the mining station /obj/effect/landmark/stationroom/lavaland/station templates = list("Public Mining Base" = 3) - icon = 'icons/rooms/Lavaland/Mining.dmi' \ No newline at end of file + icon = 'icons/rooms/Lavaland/Mining.dmi' diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 49985f5c23..1186ea8001 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -146,7 +146,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(!proximity || lit) //can't dip if cigarette is lit (it will heat the reagents in the glass instead) return if(istype(glass)) //you can dip cigarettes into beakers - if(glass.reagents.trans_to(src, chem_volume)) //if reagents were transfered, show the message + if(glass.reagents.trans_to(src, chem_volume, log = "cigar fill: dip cigarette")) //if reagents were transfered, show the message to_chat(user, "You dip \the [src] into \the [glass].") else //if not, either the beaker was empty, or the cigarette was full if(!glass.reagents.total_volume) @@ -154,7 +154,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM else to_chat(user, "[src] is full.") - /obj/item/clothing/mask/cigarette/proc/light(flavor_text = null) if(lit) return @@ -438,7 +437,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM packeditem = 1 name = "[O.name]-packed [initial(name)]" if(O.reagents) - O.reagents.trans_to(src, O.reagents.total_volume) + O.reagents.trans_to(src, O.reagents.total_volume, log = "cigar fill: pipe pack") qdel(O) else to_chat(user, "It has to be dried first!") @@ -687,7 +686,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(O.dry) var/obj/item/clothing/mask/cigarette/rollie/R = new /obj/item/clothing/mask/cigarette/rollie(user.loc) R.chem_volume = target.reagents.total_volume - target.reagents.trans_to(R, R.chem_volume) + target.reagents.trans_to(R, R.chem_volume, log = "cigar fill: rolling paper afterattack") qdel(target) qdel(src) user.put_in_active_hand(R) @@ -903,7 +902,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM //Transfer reagents and remove the plant user.show_message("You stuff the [DP] into the [src]'s bowl.", MSG_VISUAL) - DP.reagents.trans_to(src, 100) + DP.reagents.trans_to(src, 100, log = "cigar fill: bong") qdel(DP) return else diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 143354b496..cb77a58769 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -427,7 +427,7 @@ /obj/item/toy/crayon/proc/can_claim_for_gang(mob/user, atom/target) // Check area validity. // Reject space, player-created areas, and non-station z-levels. - var/area/A = get_area(target) + var/area/A = get_base_area(target) if(!A || (!is_station_level(A.z)) || !A.valid_territory) to_chat(user, "[A] is unsuitable for tagging.") return FALSE @@ -461,7 +461,7 @@ qdel(old_marking) var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang) - var/area/territory = get_area(target) + var/area/territory = get_base_area(target) new /obj/effect/decal/cleanable/crayon/gang(target,G.gang,"graffiti",0,user) // Heres the gang tag. to_chat(user, "You tagged [territory] for your gang!") diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 07d58c1754..386b1fe668 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -452,14 +452,15 @@ return TRUE /obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H) - if(req_defib) - if(defib.pullshocksafely && isliving(H.pulledby)) - H.visible_message("The defibrillator safely discharges the excessive charge into the floor!") - else - var/mob/living/M = H.pulledby - if(M.electrocute_act(30, src)) - M.visible_message("[M] is electrocuted by [M.p_their()] contact with [H]!") - M.emote("scream") + if(!H.pulledby || !isliving(H.pulledby)) + return + if(req_defib && defib.pullshocksafely) + H.visible_message("The defibrillator safely discharges the excessive charge into the floor!") + return + var/mob/living/M = H.pulledby + if(M.electrocute_act(30, src)) + M.visible_message("[M] is electrocuted by [M.p_their()] contact with [H]!") + M.emote("scream") /obj/item/twohanded/shockpaddles/proc/do_disarm(mob/living/M, mob/living/user) if(req_defib && defib.safety) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index f80dd366be..51d8a88df8 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1,4 +1,3 @@ - //The advanced pea-green monochrome lcd of tomorrow. GLOBAL_LIST_EMPTY(PDAs) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index e4fa241907..ba3fdce9b9 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -326,7 +326,7 @@ Code: if(active1 in GLOB.data_core.general) menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]
" - menu += "Sex: [active1.fields["sex"]]
" + menu += "Sex: [active1.fields["gender"]]
" menu += "Age: [active1.fields["age"]]
" menu += "Rank: [active1.fields["rank"]]
" menu += "Fingerprint: [active1.fields["fingerprint"]]
" @@ -370,7 +370,7 @@ Code: if(active1 in GLOB.data_core.general) menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]
" - menu += "Sex: [active1.fields["sex"]]
" + menu += "Sex: [active1.fields["gender"]]
" menu += "Age: [active1.fields["age"]]
" menu += "Rank: [active1.fields["rank"]]
" menu += "Fingerprint: [active1.fields["fingerprint"]]
" diff --git a/code/game/objects/items/devices/desynchronizer.dm b/code/game/objects/items/devices/desynchronizer.dm index ff58af2405..0fa557f666 100644 --- a/code/game/objects/items/devices/desynchronizer.dm +++ b/code/game/objects/items/devices/desynchronizer.dm @@ -14,6 +14,7 @@ var/last_use = 0 var/next_use = 0 var/obj/effect/abstract/sync_holder/sync_holder + var/resync_timer /obj/item/desynchronizer/attack_self(mob/living/user) if(world.time < next_use) @@ -56,16 +57,20 @@ SEND_SIGNAL(AM, COMSIG_MOVABLE_SECLUDED_LOCATION) last_use = world.time icon_state = "desynchronizer-on" - addtimer(CALLBACK(src, .proc/resync), duration) + resync_timer = addtimer(CALLBACK(src, .proc/resync), duration , TIMER_STOPPABLE) /obj/item/desynchronizer/proc/resync() new /obj/effect/temp_visual/desynchronizer(sync_holder.drop_location()) QDEL_NULL(sync_holder) + if(resync_timer) + deltimer(resync_timer) + resync_timer = null icon_state = initial(icon_state) next_use = world.time + (world.time - last_use) // Could be 2*world.time-last_use but that would just be confusing /obj/item/desynchronizer/Destroy() - resync() + if(sync_holder) + resync() return ..() /obj/effect/abstract/sync_holder diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 8c6666085e..e04501144e 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -26,6 +26,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( slot_flags = ITEM_SLOT_EARS var/obj/item/encryptionkey/keyslot2 = null dog_fashion = null + var/bowman = FALSE /obj/item/radio/headset/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins putting \the [src]'s antenna up [user.p_their()] nose! It looks like [user.p_theyre()] trying to give [user.p_them()]self cancer!") @@ -52,6 +53,11 @@ GLOBAL_LIST_INIT(channel_tokens, list( else . += "A small screen on the headset flashes, it's too small to read without holding or wearing the headset." +/obj/item/radio/headset/ComponentInitialize() + . = ..() + if (bowman) + AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS)) + /obj/item/radio/headset/Initialize() . = ..() recalculateChannels() @@ -81,10 +87,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( desc = "A syndicate headset that can be used to hear all radio frequencies. Protects ears from flashbangs." icon_state = "syndie_headset" item_state = "syndie_headset" - -/obj/item/radio/headset/syndicate/alt/ComponentInitialize() - . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS)) + bowman = TRUE /obj/item/radio/headset/syndicate/alt/leader name = "team leader headset" @@ -112,10 +115,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( desc = "This is used by your elite security force. Protects ears from flashbangs." icon_state = "sec_headset_alt" item_state = "sec_headset_alt" - -/obj/item/radio/headset/headset_sec/alt/ComponentInitialize() - . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS)) + bowman = TRUE /obj/item/radio/headset/headset_eng name = "engineering radio headset" @@ -161,10 +161,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( desc = "The headset of the boss. Protects ears from flashbangs." icon_state = "com_headset_alt" item_state = "com_headset_alt" - -/obj/item/radio/headset/heads/captain/alt/ComponentInitialize() - . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS)) + bowman = TRUE /obj/item/radio/headset/heads/rd name = "\proper the research director's headset" @@ -183,10 +180,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( desc = "The headset of the man in charge of keeping order and protecting the station. Protects ears from flashbangs." icon_state = "com_headset_alt" item_state = "com_headset_alt" - -/obj/item/radio/headset/heads/hos/ComponentInitialize() - . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS)) + bowman = TRUE /obj/item/radio/headset/heads/ce name = "\proper the chief engineer's headset" @@ -258,10 +252,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( icon_state = "cent_headset_alt" item_state = "cent_headset_alt" keyslot = null - -/obj/item/radio/headset/headset_cent/alt/ComponentInitialize() - . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS)) + bowman = TRUE /obj/item/radio/headset/ai name = "\proper Integrated Subspace Transceiver " @@ -273,7 +264,11 @@ GLOBAL_LIST_INIT(channel_tokens, list( /obj/item/radio/headset/attackby(obj/item/W, mob/user, params) user.set_machine(src) - + if (istype(W,/obj/item/headsetupgrader)) + if (!bowman) + to_chat(user,"You upgrade [src].") + bowmanize() + qdel(W) if(istype(W, /obj/item/screwdriver)) if(keyslot || keyslot2) for(var/ch_name in channels) @@ -341,3 +336,24 @@ GLOBAL_LIST_INIT(channel_tokens, list( use_command = !use_command to_chat(user, "You toggle high-volume mode [use_command ? "on" : "off"].") return TRUE + +/obj/item/radio/headset/proc/bowmanize() + cut_overlays() + var/icon/yeas = icon(icon,icon_state) + icon_state = "antenna_alt" + var/mutable_appearance/center = mutable_appearance(icon,"center_alt") + center.color = yeas.GetPixel(15,18) + var/mutable_appearance/centeralt = mutable_appearance(icon,"centeralt_alt") + centeralt.color = yeas.GetPixel(14,22) + var/mutable_appearance/centercenter = mutable_appearance(icon,"centercenter_alt") + centercenter.color = yeas.GetPixel(13,19) + var/mutable_appearance/centerpixel = mutable_appearance(icon,"centerpixel_alt") + centerpixel.color = yeas.GetPixel(13,21) + add_overlay(center) + add_overlay(centeralt) + add_overlay(centercenter) + add_overlay(centerpixel) + name = replacetext(name,"headset", "bowman headset") + desc = "[desc] Protects ears from flashbangs." + bowman = TRUE + AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS)) diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index fc768cd38e..64e2830dd4 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -251,3 +251,9 @@ effective or pretty fucking useless. else GLOB.active_jammers -= src update_icon() + +/obj/item/headsetupgrader + name = "headset upgrader" + desc = "A tool that can be used to upgrade a normal headset to be able to protect from flashbangs." + icon = 'icons/obj/device.dmi' + icon_state = "headset_upgrade" diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index f6f14554ed..8ce0f33307 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -310,6 +310,7 @@ trap_damage = 0 item_flags = DROPDEL flags_1 = NONE + breakouttime = 50 /obj/item/restraints/legcuffs/beartrap/energy/New() ..() diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index f6bff2f880..21de34faa1 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -10,7 +10,15 @@ */ GLOBAL_LIST_INIT(glass_recipes, list ( \ new/datum/stack_recipe("directional window", /obj/structure/window/unanchored, time = 0, on_floor = TRUE, window_checks = TRUE), \ - new/datum/stack_recipe("fulltile window", /obj/structure/window/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE) \ + new/datum/stack_recipe("fulltile window", /obj/structure/window/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \ + null, \ + new/datum/stack_recipe_list("glass working bases", list( \ + new/datum/stack_recipe("chem dish", /obj/item/glasswork/glass_base/dish, 10), \ + new/datum/stack_recipe("lens", /obj/item/glasswork/glass_base/glass_lens, 15), \ + new/datum/stack_recipe("spout flask", /obj/item/glasswork/glass_base/spouty, 20), \ + new/datum/stack_recipe("small bulb flask", /obj/item/glasswork/glass_base/flask_small, 5), \ + new/datum/stack_recipe("large bottle flask", /obj/item/glasswork/glass_base/flask_large, 15), \ + )), \ )) /obj/item/stack/sheet/glass diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index a80f0d5a3b..31dd6d32a3 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -277,6 +277,9 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ recipes = GLOB.wood_recipes return ..() +/obj/item/stack/sheet/mineral/wood/twenty + amount = 20 + /obj/item/stack/sheet/mineral/wood/fifty amount = 50 @@ -306,6 +309,15 @@ GLOBAL_LIST_INIT(bamboo_recipes, list ( \ recipes = GLOB.bamboo_recipes return ..() +/obj/item/stack/sheet/mineral/bamboo/ten + amount = 10 + +/obj/item/stack/sheet/mineral/bamboo/twenty + amount = 20 + +/obj/item/stack/sheet/mineral/bamboo/fifty + amount = 50 + /* * Cloth */ @@ -782,3 +794,4 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra merge_type = /obj/item/stack/sheet/cotton/durathread pull_effort = 70 loom_result = /obj/item/stack/sheet/durathread + diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 18acb5e14d..fa4e5a3886 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -233,39 +233,111 @@ turf_type = /turf/open/floor/carpet/royalblue tableVariant = /obj/structure/table/wood/fancy/royalblue +/obj/item/stack/tile/carpet/ten + amount = 10 + +/obj/item/stack/tile/carpet/twenty + amount = 20 + /obj/item/stack/tile/carpet/fifty amount = 50 +/obj/item/stack/tile/carpet/black/ten + amount = 10 + +/obj/item/stack/tile/carpet/black/twenty + amount = 20 + /obj/item/stack/tile/carpet/black/fifty amount = 50 +/obj/item/stack/tile/carpet/blackred/ten + amount = 10 + +/obj/item/stack/tile/carpet/blackred/twenty + amount = 20 + /obj/item/stack/tile/carpet/blackred/fifty amount = 50 +/obj/item/stack/tile/carpet/monochrome/ten + amount = 10 + +/obj/item/stack/tile/carpet/monochrome/twenty + amount = 20 + /obj/item/stack/tile/carpet/monochrome/fifty amount = 50 +/obj/item/stack/tile/carpet/blue/ten + amount = 10 + +/obj/item/stack/tile/carpet/blue/twenty + amount = 20 + /obj/item/stack/tile/carpet/blue/fifty amount = 50 +/obj/item/stack/tile/carpet/cyan/ten + amount = 10 + +/obj/item/stack/tile/carpet/cyan/twenty + amount = 20 + /obj/item/stack/tile/carpet/cyan/fifty amount = 50 +/obj/item/stack/tile/carpet/green/ten + amount = 10 + +/obj/item/stack/tile/carpet/green/twenty + amount = 20 + /obj/item/stack/tile/carpet/green/fifty amount = 50 +/obj/item/stack/tile/carpet/orange/ten + amount = 10 + +/obj/item/stack/tile/carpet/orange/twenty + amount = 20 + /obj/item/stack/tile/carpet/orange/fifty amount = 50 +/obj/item/stack/tile/carpet/purple/ten + amount = 10 + +/obj/item/stack/tile/carpet/purple/twenty + amount = 20 + /obj/item/stack/tile/carpet/purple/fifty amount = 50 +/obj/item/stack/tile/carpet/red/ten + amount = 10 + +/obj/item/stack/tile/carpet/red/twenty + amount = 20 + /obj/item/stack/tile/carpet/red/fifty amount = 50 +/obj/item/stack/tile/carpet/royalblack/ten + amount = 10 + +/obj/item/stack/tile/carpet/royalblack/twenty + amount = 20 + /obj/item/stack/tile/carpet/royalblack/fifty amount = 50 +/obj/item/stack/tile/carpet/royalblue/ten + amount = 10 + +/obj/item/stack/tile/carpet/royalblue/twenty + amount = 20 + /obj/item/stack/tile/carpet/royalblue/fifty amount = 50 diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 31efabf210..880b714f76 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -293,7 +293,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) desc = replacetext(desc, "robust", "safe") desc = replacetext(desc, "heavier", "bouncier") DISABLE_BITFIELD(flags_1, CONDUCT_1) - materials = null + materials = typelist("materials", null) damtype = STAMINA force += 3 //to compensate the higher stamina K.O. threshold compared to actual health. throwforce += 3 @@ -317,8 +317,8 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) flags_1 = null materials = null damtype = STAMINA - force = 17 - throwforce = 17 + force = 15 + throwforce = 15 attack_verb = list("robusted", "bounced") can_rubberify = FALSE //we are already the future. diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index b9862c3423..28a6fd66ee 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -25,8 +25,8 @@ */ /obj/item/twohanded var/wielded = 0 - var/force_unwielded = 0 - var/force_wielded = 0 + var/force_unwielded // default to null, the number force will be set to on unwield() + var/force_wielded // same as above but for wield() var/wieldsound = null var/unwieldsound = null var/slowdown_wielded = 0 @@ -73,7 +73,7 @@ to_chat(user, "You don't have enough intact hands.") return wielded = 1 - if(force_wielded) + if(!isnull(force_wielded)) force = force_wielded name = "[name] (Wielded)" update_icon() @@ -738,7 +738,7 @@ on = !on to_chat(user, "As you pull the starting cord dangling from [src], [on ? "it begins to whirr." : "the chain stops moving."]") force = on ? force_on : initial(force) - throwforce = on ? force_on : initial(force) + throwforce = on ? force_on : force icon_state = "chainsaw_[on ? "on" : "off"]" var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering) butchering.butchering_enabled = on diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 5f3fc48eb7..0c1239e887 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -178,7 +178,7 @@ machine = null //called when the user unsets the machine. -/atom/movable/proc/on_unset_machine(mob/user) +/atom/proc/on_unset_machine(mob/user) return /mob/proc/set_machine(obj/O) diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm index 5b9a764925..fcd1f80a4f 100644 --- a/code/game/objects/structures/ai_core.dm +++ b/code/game/objects/structures/ai_core.dm @@ -52,7 +52,7 @@ var/area/A = get_area(src) if(!A.blob_allowed) return FALSE - if(!A.power_equip) + if(!A.powered(EQUIP)) return FALSE if(!SSmapping.level_trait(T.z,ZTRAIT_STATION)) return FALSE diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm index 053512a256..b72a4b816e 100644 --- a/code/game/objects/structures/barsigns.dm +++ b/code/game/objects/structures/barsigns.dm @@ -305,7 +305,7 @@ /datum/barsign/meow_mix name = "Meow Mix" - icon = "meow_mix" + icon = "Meow Mix" desc = "No, we don't serve catnip, officer!" /datum/barsign/hiddensigns diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 9a095bf69d..daf15832fb 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -532,7 +532,7 @@ /obj/structure/closet/CtrlShiftClick(mob/living/user) if(!HAS_TRAIT(user, TRAIT_SKITTISH)) return ..() - if(!user.canUseTopic(src) || !isturf(user.loc)) + if(!user.canUseTopic(src) || !isturf(user.loc) || !user.Adjacent(src) || !user.CanReach(src)) return dive_into(user) diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 8c25a2ca5c..70533df0ad 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -80,7 +80,7 @@ /obj/structure/displaycase/proc/trigger_alarm() //Activate Anti-theft if(alert) - var/area/alarmed = get_area(src) + var/area/alarmed = get_base_area(src) alarmed.burglaralert(src) playsound(src, 'sound/effects/alert.ogg', 50, 1) diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 271ae72d47..f35e9e7d55 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -205,6 +205,9 @@ if(!mineral) if(istype(G, /obj/item/stack/sheet/mineral) && G.sheettype) var/M = G.sheettype + var/mineralassembly = text2path("/obj/structure/door_assembly/door_assembly_[M]") + if(!mineralassembly) + return if(G.get_amount() >= 2) playsound(src, 'sound/items/crowbar.ogg', 100, 1) user.visible_message("[user] adds [G.name] to the airlock assembly.", \ @@ -214,7 +217,6 @@ return to_chat(user, "You install [M] plating into the airlock assembly.") G.use(2) - var/mineralassembly = text2path("/obj/structure/door_assembly/door_assembly_[M]") var/obj/structure/door_assembly/MA = new mineralassembly(loc) transfer_assembly_vars(src, MA, TRUE) else diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index d7e2d5564a..52441c2987 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -7,7 +7,7 @@ anchored = TRUE icon = 'icons/turf/walls/wall.dmi' icon_state = "wall" - layer = CLOSED_TURF_LAYER + layer = LOW_OBJ_LAYER density = TRUE opacity = 1 max_integrity = 100 diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index 92fb13c947..3ba9fea006 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -619,7 +619,7 @@ assignedrole = "Ghost Cafe Visitor" flavour_text = "Is this what life after death is like?" skip_reentry_check = TRUE - banType = "ghostcafe" + banType = ROLE_GHOSTCAFE /datum/action/toggle_dead_chat_mob icon_icon = 'icons/mob/mob.dmi' @@ -642,12 +642,14 @@ /obj/effect/mob_spawn/human/ghostcafe/special(mob/living/carbon/human/new_spawn) if(new_spawn.client) new_spawn.client.prefs.copy_to(new_spawn) + var/area/A = get_area(src) var/datum/outfit/O = new /datum/outfit/ghostcafe() O.equip(new_spawn, FALSE, new_spawn.client) SSjob.equip_loadout(null, new_spawn, FALSE) SSquirks.AssignQuirks(new_spawn, new_spawn.client, TRUE, TRUE, null, FALSE, new_spawn) new_spawn.AddElement(/datum/element/ghost_role_eligibility) new_spawn.AddElement(/datum/element/dusts_on_catatonia) + new_spawn.AddElement(/datum/element/dusts_on_leaving_area,list(A.type,/area/hilbertshotel)) ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT) ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT) ADD_TRAIT(new_spawn,TRAIT_PACIFISM,GHOSTROLE_TRAIT) diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 94619e1858..7c373f2734 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -166,6 +166,9 @@ if(S.sheettype && S.sheettype != "runed") var/M = S.sheettype if(state == GIRDER_DISPLACED) + var/F = text2path("/obj/structure/falsewall/[M]") + if(!F) + return if(S.get_amount() < 2) to_chat(user, "You need at least two sheets to create a false wall!") return @@ -174,11 +177,13 @@ return S.use(2) to_chat(user, "You create a false wall. Push on it to open or close the passage.") - var/F = text2path("/obj/structure/falsewall/[M]") var/obj/structure/FW = new F (loc) transfer_fingerprints_to(FW) qdel(src) else + var/F = text2path("/turf/closed/wall/mineral/[M]") + if(!F) + return if(S.get_amount() < 2) to_chat(user, "You need at least two sheets to add plating!") return @@ -189,7 +194,7 @@ S.use(2) to_chat(user, "You add the plating.") var/turf/T = get_turf(src) - T.PlaceOnTop(text2path("/turf/closed/wall/mineral/[M]")) + T.PlaceOnTop(F) transfer_fingerprints_to(T) qdel(src) return diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm index 3b4bbea559..611a6d024d 100644 --- a/code/game/objects/structures/guillotine.dm +++ b/code/game/objects/structures/guillotine.dm @@ -97,7 +97,7 @@ icon_state = "guillotine_raised" /obj/structure/guillotine/proc/drop_blade(mob/user) - if (buckled_mobs.len && blade_sharpness) + if (has_buckled_mobs() && blade_sharpness) var/mob/living/carbon/human/H = buckled_mobs[1] if (!H) diff --git a/code/game/objects/structures/headpike.dm b/code/game/objects/structures/headpike.dm index ceed9cb759..81433b562d 100644 --- a/code/game/objects/structures/headpike.dm +++ b/code/game/objects/structures/headpike.dm @@ -42,8 +42,9 @@ if(.) return to_chat(user, "You take down [src].") - victim.forceMove(drop_location()) - victim = null + if(victim) + victim.forceMove(drop_location()) + victim = null spear.forceMove(drop_location()) spear = null qdel(src) \ No newline at end of file diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 0a5794c59d..90408472e9 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -20,14 +20,14 @@ return if(broken || !Adjacent(user)) return - + if(ishuman(user)) var/mob/living/carbon/human/H = user //see code/modules/mob/dead/new_player/preferences.dm at approx line 545 for comments! //this is largely copypasted from there. //handle facial hair (if necessary) - if(H.gender == MALE) + if(H.gender != FEMALE) var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in GLOB.facial_hair_styles_list if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return //no tele-grooming diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm index be46d124ea..d55cb0b475 100644 --- a/code/game/turfs/simulated/wall/mineral_walls.dm +++ b/code/game/turfs/simulated/wall/mineral_walls.dm @@ -138,7 +138,8 @@ var/duration = (48/W.force) * 2 //In seconds, for now. if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/twohanded/fireaxe)) duration /= 4 //Much better with hatchets and axes. - if(do_after(user, duration*10, target=src)) //Into deciseconds. + var/src_type = type + if(do_after(user, duration*10, target=src) && type == src_type) //Into deciseconds. dismantle_wall(FALSE,FALSE) return return ..() diff --git a/code/game/world.dm b/code/game/world.dm index 7afaf62bb8..8c3e848106 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -116,6 +116,7 @@ GLOBAL_LIST(topic_status_cache) GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log" GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log" GLOB.subsystem_log = "[GLOB.log_directory]/subsystem.log" + GLOB.reagent_log = "[GLOB.log_directory]/reagents.log" GLOB.world_crafting_log = "[GLOB.log_directory]/crafting.log" #ifdef UNIT_TESTS @@ -132,6 +133,7 @@ GLOBAL_LIST(topic_status_cache) start_log(GLOB.world_runtime_log) start_log(GLOB.world_job_debug_log) start_log(GLOB.subsystem_log) + start_log(GLOB.reagent_log) start_log(GLOB.world_crafting_log) GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm index 7cda24d98b..29d7224950 100644 --- a/code/modules/VR/vr_sleeper.dm +++ b/code/modules/VR/vr_sleeper.dm @@ -222,18 +222,23 @@ /obj/effect/vr_clean_master/Initialize() . = ..() - vr_area = get_area(src) - addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES) + vr_area = get_base_area(src) + if(!vr_area) + return INITIALIZE_HINT_QDEL + addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES, TIMER_LOOP) /obj/effect/vr_clean_master/proc/clean_up() - if (vr_area) - for (var/obj/item/ammo_casing/casing in vr_area) - qdel(casing) - for(var/obj/effect/decal/cleanable/C in vr_area) - qdel(C) - for (var/A in corpse_party) - var/mob/M = A - if(M && M.stat == DEAD && get_area(M) == vr_area) - qdel(M) - corpse_party -= M - addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES) + if (!vr_area) + qdel(src) + return + var/list/contents = get_sub_areas_contents(vr_area) + for (var/obj/item/ammo_casing/casing in contents) + qdel(casing) + for(var/obj/effect/decal/cleanable/C in contents) + qdel(C) + for (var/A in corpse_party) + var/mob/M = A + if(!QDELETED(M) && (M in contents) && M.stat == DEAD) + qdel(M) + corpse_party -= M + addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES) diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index 70ae133a31..d7af763244 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -408,7 +408,7 @@ var/obj/item/organ/tail/cat/tail = new ears.Insert(H, drop_if_replaced=FALSE) tail.Insert(H, drop_if_replaced=FALSE) - var/list/honorifics = list("[MALE]" = list("kun"), "[FEMALE]" = list("chan","tan"), "[NEUTER]" = list("san")) //John Robust -> Robust-kun + var/list/honorifics = list("[MALE]" = list("kun"), "[FEMALE]" = list("chan","tan"), "[NEUTER]" = list("san"), "[PLURAL]" = list("san")) //John Robust -> Robust-kun var/list/names = splittext(H.real_name," ") var/forename = names.len > 1 ? names[2] : names[1] var/newname = "[forename]-[pick(honorifics["[H.gender]"])]" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index c66927b856..c76ecb52f5 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -845,7 +845,11 @@ dat += "Lavaland" else dat += "Lavaland" - + // Ghost cafe + if(jobban_isbanned(M,ROLE_GHOSTCAFE)) + dat += "Lavaland" + else + dat += "Lavaland" dat += "" //Antagonist (Orange) @@ -2878,6 +2882,8 @@ return if(SSdbcore.Connect()) var/datum/DBQuery/query_get_mentor = SSdbcore.NewQuery("SELECT id FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'") + if(!query_get_mentor.warn_execute()) + return if(query_get_mentor.NextRow()) to_chat(usr, "[ckey] is already a mentor.") return diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index f08112939a..ad2eeb7289 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -541,7 +541,9 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) var/list/areas_all = list() var/list/areas_with_APC = list() var/list/areas_with_multiple_APCs = list() + var/list/sub_areas_APC = list() var/list/areas_with_air_alarm = list() + var/list/sub_areas_air_alarm = list() var/list/areas_with_RC = list() var/list/areas_with_light = list() var/list/areas_with_LS = list() @@ -578,6 +580,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) if(!A) dat += "Skipped over [APC] in invalid location, [APC.loc]." continue + LAZYSET(sub_areas_APC, A.type, get_sub_areas(A, FALSE)) if(!(A.type in areas_with_APC)) areas_with_APC.Add(A.type) else if(A.type in areas_all) @@ -585,10 +588,11 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) CHECK_TICK for(var/obj/machinery/airalarm/AA in GLOB.machines) - var/area/A = get_area(AA) + var/area/A = get_base_area(AA) if(!A) //Make sure the target isn't inside an object, which results in runtimes. dat += "Skipped over [AA] in invalid location, [AA.loc].
" continue + LAZYSET(sub_areas_air_alarm, A.type, get_sub_areas(A, FALSE)) if(!(A.type in areas_with_air_alarm)) areas_with_air_alarm.Add(A.type) CHECK_TICK @@ -638,8 +642,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) areas_with_camera.Add(A.type) CHECK_TICK - var/list/areas_without_APC = areas_all - areas_with_APC - var/list/areas_without_air_alarm = areas_all - areas_with_air_alarm + var/list/areas_without_APC = areas_all - (areas_with_APC + flatten_list(sub_areas_APC)) + var/list/areas_without_air_alarm = areas_all - (areas_with_air_alarm + flatten_list(sub_areas_air_alarm)) var/list/areas_without_RC = areas_all - areas_with_RC var/list/areas_without_light = areas_all - areas_with_light var/list/areas_without_LS = areas_all - areas_with_LS @@ -656,12 +660,18 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) dat += "

AREAS WITH MULTIPLE APCS:

" for(var/areatype in areas_with_multiple_APCs) dat += "[areatype]
" + if(sub_areas_APC[areatype]) + dat += "  SUB-AREAS:
  " + dat += jointext(sub_areas_APC[areatype], "
  ") CHECK_TICK if(areas_without_air_alarm.len) dat += "

AREAS WITHOUT AN AIR ALARM:

" for(var/areatype in areas_without_air_alarm) dat += "[areatype]
" + if(sub_areas_air_alarm[areatype]) + dat += "  SUB-AREAS:
  " + dat += jointext(sub_areas_air_alarm[areatype], "
  ") CHECK_TICK if(areas_without_RC.len) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 1437555af1..f30e47c68e 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -419,7 +419,7 @@ Traitors and the like can also be revived with the previous role mostly intact. if(record_found)//If they have a record we can determine a few things. new_character.real_name = record_found.fields["name"] - new_character.gender = record_found.fields["sex"] + new_character.gender = record_found.fields["gender"] new_character.age = record_found.fields["age"] new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], record_found.fields["name"], record_found.fields["blood_type"], new record_found.fields["species"], record_found.fields["features"]) else diff --git a/code/modules/antagonists/abductor/abductee/abductee.dm b/code/modules/antagonists/abductor/abductee/abductee.dm new file mode 100644 index 0000000000..901d2f5b11 --- /dev/null +++ b/code/modules/antagonists/abductor/abductee/abductee.dm @@ -0,0 +1,34 @@ +/datum/antagonist/abductee + name = "Abductee" + roundend_category = "abductees" + antagpanel_category = "Abductee" + var/datum/brain_trauma/abductee/brain_trauma + +/datum/antagonist/abductee/on_gain() + give_objective() + . = ..() + +/datum/antagonist/abductee/greet() + to_chat(owner, "Your mind snaps!") + to_chat(owner, "You can't remember how you got here...") + owner.announce_objectives() + +/datum/antagonist/abductee/proc/give_objective() + var/mob/living/carbon/human/H = owner.current + if(istype(H)) + H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY) + var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random)) + var/datum/objective/abductee/O = new objtype() + objectives += O + +/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override) + update_abductor_icons_added(mob_override ? mob_override.mind : owner,"abductee") + var/mob/living/carbon/C = mob_override || owner?.current + if(istype(C)) + if(brain_trauma) + qdel(brain_trauma) //make sure there's no lingering trauma + brain_trauma = C.gain_trauma(/datum/brain_trauma/abductee, TRAUMA_RESILIENCE_SURGERY) + +/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override) + update_abductor_icons_removed(mob_override ? mob_override.mind : owner) + qdel(brain_trauma) diff --git a/code/modules/antagonists/abductor/abductee/abductee_objectives.dm b/code/modules/antagonists/abductor/abductee/abductee_objectives.dm index f188319644..2d62bf1ac9 100644 --- a/code/modules/antagonists/abductor/abductee/abductee_objectives.dm +++ b/code/modules/antagonists/abductor/abductee/abductee_objectives.dm @@ -18,7 +18,7 @@ /datum/objective/abductee/paint/New() var/color = pick(list("red", "blue", "green", "yellow", "orange", "purple", "black", "in rainbows", "in blood")) - explanation_text+= " [color]!" + explanation_text = " [color]!" /datum/objective/abductee/speech explanation_text = "Your brain is broken... you can only communicate in" diff --git a/code/modules/antagonists/abductor/abductee/trauma.dm b/code/modules/antagonists/abductor/abductee/trauma.dm new file mode 100644 index 0000000000..1518825e1b --- /dev/null +++ b/code/modules/antagonists/abductor/abductee/trauma.dm @@ -0,0 +1,18 @@ +/datum/brain_trauma/abductee + name = "abductee mindsnapped" + desc = "The patient's brain has been scrambled by experimental procedures." + scan_desc = "brain scrambling" + gain_text = "Your mind snaps.. you feel fragmented." + lose_text = "Your mind heals itself and you feel whole again." + random_gain = FALSE + clonable = TRUE + +/datum/brain_trauma/abductee/on_gain() + . = ..() + if(owner.mind) + if(!owner.mind.has_antag_datum(/datum/antagonist/abductee)) + owner.mind.add_antag_datum(/datum/antagonist/abductee) + +/datum/brain_trauma/abductee/on_lose() + . = ..() + owner.mind?.remove_antag_datum(/datum/antagonist/abductee) diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 92504641a9..564e9a8617 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -159,35 +159,6 @@ return "
[result.Join("
")]
" -/datum/antagonist/abductee - name = "Abductee" - roundend_category = "abductees" - antagpanel_category = "Abductee" - -/datum/antagonist/abductee/on_gain() - give_objective() - . = ..() - -/datum/antagonist/abductee/greet() - to_chat(owner, "Your mind snaps!") - to_chat(owner, "You can't remember how you got here...") - owner.announce_objectives() - -/datum/antagonist/abductee/proc/give_objective() - var/mob/living/carbon/human/H = owner.current - if(istype(H)) - H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY) - var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random)) - var/datum/objective/abductee/O = new objtype() - objectives += O - -/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override) - update_abductor_icons_added(mob_override ? mob_override.mind : owner,"abductee") - -/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override) - update_abductor_icons_removed(mob_override ? mob_override.mind : owner) - - // LANDMARKS /obj/effect/landmark/abductor var/team_number = 1 diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index dc6d12453d..332329a221 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -29,6 +29,11 @@ var/stealth_armor = list("melee" = 15, "bullet" = 15, "laser" = 15, "energy" = 15, "bomb" = 15, "bio" = 15, "rad" = 15, "fire" = 70, "acid" = 70) var/combat_armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 50, "rad" = 50, "fire" = 90, "acid" = 90) +/obj/item/clothing/suit/armor/abductor/vest/Initialize() + . = ..() + stealth_armor = getArmor(arglist(stealth_armor)) + combat_armor = getArmor(arglist(combat_armor)) + /obj/item/clothing/suit/armor/abductor/vest/proc/toggle_nodrop() if(HAS_TRAIT_FROM(src, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT)) REMOVE_TRAIT(src, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT) @@ -629,15 +634,12 @@ icon_state = "abductor_headset" item_state = "abductor_headset" keyslot2 = new /obj/item/encryptionkey/heads/captain + bowman = TRUE /obj/item/radio/headset/abductor/Initialize(mapload) . = ..() make_syndie() -/obj/item/radio/headset/abductor/ComponentInitialize() - . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS)) - /obj/item/radio/headset/abductor/attackby(obj/item/W, mob/user, params) if(W.tool_behaviour == TOOL_SCREWDRIVER) return // Stops humans from disassembling abductor headsets. diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index da002e568c..7948b30035 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -22,7 +22,7 @@ Runes can either be invoked by one's self or with many different cultists. Each icon = 'icons/obj/rune.dmi' icon_state = "1" resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF - layer = LOW_OBJ_LAYER + layer = SIGIL_LAYER color = RUNE_COLOR_RED var/invocation = "Aiy ele-mayo." //This is said by cultists when the rune is invoked. diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm index ce455d9e67..f2296d239f 100644 --- a/code/modules/antagonists/swarmer/swarmer.dm +++ b/code/modules/antagonists/swarmer/swarmer.dm @@ -274,7 +274,8 @@ /obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) S.DisIntegrate(src) - toggle_cam(S, 0) + if(!QDELETED(S)) //If it got blown up no need to turn it off. + toggle_cam(S, 0) return TRUE /obj/machinery/particle_accelerator/control_box/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm index 3cc3b48e50..e6ca95472e 100644 --- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm +++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm @@ -22,11 +22,19 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( desc = "You aren't entirely sure what this does, but it's very beepy and boopy." background_icon_state = "bg_tech_blue" icon_icon = 'icons/mob/actions/actions_AI.dmi' + check_flags = AB_CHECK_CONSCIOUS //can't doomsday if dead. var/mob/living/silicon/ai/owner_AI //The owner AI, so we don't have to typecast every time var/uses //If we have multiple uses of the same power var/auto_use_uses = TRUE //If we automatically use up uses on each activation var/cooldown_period //If applicable, the time in deciseconds we have to wait before using any more modules + +/datum/action/innate/ai/New() + ..() + if(uses > 1) + desc = "[desc] It has [uses] use\s remaining." + button.desc = desc + /datum/action/innate/ai/Grant(mob/living/L) . = ..() if(!isAI(owner)) @@ -38,7 +46,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /datum/action/innate/ai/IsAvailable() . = ..() if(owner_AI && owner_AI.malf_cooldown > world.time) - return + return FALSE /datum/action/innate/ai/Trigger() . = ..() @@ -49,12 +57,16 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /datum/action/innate/ai/proc/adjust_uses(amt, silent) uses += amt - if(!silent && uses) - to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.") - if(!uses) - if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway! - to_chat(owner, "[name] has run out of uses!") - qdel(src) + if(uses) + if(!silent) + to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.") + desc = "[initial(desc)] It has [uses] use\s remaining." + UpdateButtonIcon() + return + if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway! + to_chat(owner, "[name] has run out of uses!") + qdel(src) + //Framework for ranged abilities that can have different effects by left-clicking stuff. /datum/action/innate/ai/ranged @@ -74,13 +86,16 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /datum/action/innate/ai/ranged/adjust_uses(amt, silent) uses += amt - if(!silent && uses) - to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.") - if(!uses) - if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway! - to_chat(owner, "[name] has run out of uses!") - Remove(owner) - QDEL_IN(src, 100) //let any active timers on us finish up + if(uses) + if(!silent) + to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.") + desc = "[initial(desc)] It has [uses] use\s remaining." + UpdateButtonIcon() + return + if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway! + to_chat(owner, "[name] has run out of uses!") + Remove(owner) + QDEL_IN(src, 100) //let any active timers on us finish up /datum/action/innate/ai/ranged/Destroy() QDEL_NULL(linked_ability) @@ -97,7 +112,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( var/datum/action/innate/ai/ranged/attached_action /obj/effect/proc_holder/ranged_ai/Destroy() - QDEL_NULL(attached_action) + attached_action = null return ..() /obj/effect/proc_holder/ranged_ai/proc/toggle(mob/user) @@ -185,6 +200,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( A.playsound_local(A, AM.unlock_sound, 50, 0) else //Adding uses to an existing module action.uses += initial(action.uses) + action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining." + action.UpdateButtonIcon() temp = "Additional use[action.uses > 1 ? "s" : ""] added to [action.name]!" processing_time -= AM.cost @@ -238,6 +255,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( return if(alert(owner, "Send arming signal? (true = arm, false = cancel)", "purge_all_life()", "confirm = TRUE;", "confirm = FALSE;") != "confirm = TRUE;") return + if (active) + return //prevent the AI from activating an already active doomsday active = TRUE set_us_up_the_bomb(owner) @@ -245,64 +264,64 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( set waitfor = FALSE to_chat(owner, "run -o -a 'selfdestruct'") sleep(5) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Running executable 'selfdestruct'...") sleep(rand(10, 30)) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return owner.playsound_local(owner, 'sound/misc/bloblarm.ogg', 50, 0) to_chat(owner, "!!! UNAUTHORIZED SELF-DESTRUCT ACCESS !!!") to_chat(owner, "This is a class-3 security violation. This incident will be reported to Central Command.") for(var/i in 1 to 3) sleep(20) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Sending security report to Central Command.....[rand(0, 9) + (rand(20, 30) * i)]%") sleep(3) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "auth 'akjv9c88asdf12nb' ******************") owner.playsound_local(owner, 'sound/items/timer.ogg', 50, 0) sleep(30) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Credentials accepted. Welcome, akjv9c88asdf12nb.") owner.playsound_local(owner, 'sound/misc/server-ready.ogg', 50, 0) sleep(5) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Arm self-destruct device? (Y/N)") owner.playsound_local(owner, 'sound/misc/compiler-stage1.ogg', 50, 0) sleep(20) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Y") sleep(15) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Confirm arming of self-destruct device? (Y/N)") owner.playsound_local(owner, 'sound/misc/compiler-stage2.ogg', 50, 0) sleep(10) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Y") sleep(rand(15, 25)) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Please repeat password to confirm.") owner.playsound_local(owner, 'sound/misc/compiler-stage2.ogg', 50, 0) sleep(14) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "******************") sleep(40) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return to_chat(owner, "Credentials accepted. Transmitting arming signal...") owner.playsound_local(owner, 'sound/misc/server-ready.ogg', 50, 0) sleep(30) - if(!owner || QDELETED(owner)) + if(QDELETED(owner) || owner.stat == DEAD) return priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", "aimalf") set_security_level("delta") @@ -724,9 +743,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /datum/action/innate/ai/blackout name = "Blackout" - desc = "Overloads lights across the station." + desc = "Overloads random lights across the station." button_icon_state = "blackout" uses = 3 + auto_use_uses = FALSE /datum/action/innate/ai/blackout/Activate() for(var/obj/machinery/power/apc/apc in GLOB.apcs_list) @@ -736,6 +756,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( apc.overload++ to_chat(owner, "Overcurrent applied to the powernet.") owner.playsound_local(owner, "sparks", 50, 0) + adjust_uses(-1) //Disable Emergency Lights @@ -784,11 +805,6 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( auto_use_uses = FALSE cooldown_period = 30 -/datum/action/innate/ai/reactivate_cameras/New() - ..() - desc = "[desc] There are 30 reactivations remaining." - button.desc = desc - /datum/action/innate/ai/reactivate_cameras/Activate() var/fixed_cameras = 0 for(var/V in GLOB.cameranet.cameras) @@ -803,8 +819,6 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( to_chat(owner, "Diagnostic complete! Cameras reactivated: [fixed_cameras]. Reactivations remaining: [uses].") owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, 0) adjust_uses(0, TRUE) //Checks the uses remaining - if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe - desc = "[initial(desc)] There are [uses] reactivations remaining." //Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision. diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm index bd4f1a8acd..70cb29e7a3 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook.dm @@ -163,7 +163,7 @@ /datum/spellbook_entry/timestop name = "Time Stop" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop + spell_type = /obj/effect/proc_holder/spell/aoe_turf/timestop category = "Defensive" /datum/spellbook_entry/smoke diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index c67b79478e..7c8952eb33 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -46,7 +46,7 @@ return FALSE switch(type) if("feet") - if(!H.shoes) + if(!H.shoes || !(H.shoes.body_parts_covered & FEET)) affecting = H.get_bodypart(pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) H.Knockdown(60) if(BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND) diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index e49368016b..95063aadf6 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -207,7 +207,7 @@ pixel_y = (dir & 3)? (dir == 1 ? -24 : 24) : 0 if(name == initial(name)) - name = "[get_area_name(src)] Air Alarm" + name = "[get_area_name(src, get_base_area = TRUE)] Air Alarm" power_change() set_frequency(frequency) @@ -250,7 +250,7 @@ "danger_level" = danger_level, ) - var/area/A = get_area(src) + var/area/A = get_base_area(src) data["atmos_alarm"] = A.atmosalm data["fire_alarm"] = A.fire @@ -386,7 +386,7 @@ send_signal(device_id, list("checks" = text2num(params["val"])^2), usr) . = TRUE if("set_external_pressure", "set_internal_pressure") - var/area/A = get_area(src) + var/area/A = get_base_area(src) var/target = input("New target pressure:", name, A.air_vent_info[device_id][(action == "set_external_pressure" ? "external" : "internal")]) as num|null if(!isnull(target) && !..()) send_signal(device_id, list("[action]" = target), usr) @@ -420,12 +420,12 @@ apply_mode() . = TRUE if("alarm") - var/area/A = get_area(src) + var/area/A = get_base_area(src) if(A.atmosalert(2, src)) post_alert(2) . = TRUE if("reset") - var/area/A = get_area(src) + var/area/A = get_base_area(src) if(A.atmosalert(0, src)) post_alert(0) . = TRUE @@ -456,7 +456,7 @@ return 0 /obj/machinery/airalarm/proc/refresh_all() - var/area/A = get_area(src) + var/area/A = get_base_area(src) for(var/id_tag in A.air_vent_names) var/list/I = A.air_vent_info[id_tag] if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time) @@ -507,7 +507,7 @@ return "Flood" /obj/machinery/airalarm/proc/apply_mode() - var/area/A = get_area(src) + var/area/A = get_base_area(src) switch(mode) if(AALARM_MODE_SCRUBBING) for(var/device_id in A.air_scrub_names) @@ -645,7 +645,7 @@ icon_state = "alarm1" var/overlay_state = AALARM_OVERLAY_OFF - var/area/A = get_area(src) + var/area/A = get_base_area(src) switch(max(danger_level, A.atmosalm)) if(0) add_overlay(AALARM_OVERLAY_GREEN) @@ -715,7 +715,7 @@ return var/datum/signal/alert_signal = new(list( - "zone" = get_area_name(src), + "zone" = get_area_name(src, get_base_area = TRUE), "type" = "Atmospheric" )) if(alert_level==2) @@ -728,7 +728,7 @@ frequency.post_signal(src, alert_signal, range = -1) /obj/machinery/airalarm/proc/apply_danger_level() - var/area/A = get_area(src) + var/area/A = get_base_area(src) var/new_area_danger_level = 0 for(var/obj/machinery/airalarm/AA in A) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm index 5835912cd3..bc58ef158f 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm @@ -5,6 +5,7 @@ icon_state = "relief_valve-t-map" can_unwrench = TRUE construction_type = /obj/item/pipe/binary + interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE var/opened = FALSE var/open_pressure = ONE_ATMOSPHERE * 3 var/close_pressure = ONE_ATMOSPHERE @@ -50,9 +51,11 @@ if(!is_operational()) return - var/datum/gas_mixture/air_contents = airs[1] - var/our_pressure = air_contents.return_pressure() - if(opened && our_pressure < close_pressure) + var/datum/gas_mixture/air_one = airs[1] + var/datum/gas_mixture/air_two = airs[2] + var/air_one_pressure = air_one.return_pressure() + var/our_pressure = abs(air_one_pressure - air_two.return_pressure()) + if(opened && air_one_pressure < close_pressure) close() else if(!opened && our_pressure >= open_pressure) open() diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index ff2a655aac..86e8863b2b 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -30,7 +30,7 @@ underlays.Cut() var/turf/T = loc - if(level == 2 || !T.intact) + if(level == 2 || (istype(T) && !T.intact)) showpipe = TRUE plane = GAME_PLANE else diff --git a/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm b/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm index 9da9e49e01..4b6a4a4c10 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/atmospherics/components/relief_valve.dmi' icon_state = "relief_valve-e-map" can_unwrench = TRUE + interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE var/opened = FALSE var/open_pressure = ONE_ATMOSPHERE * 3 var/close_pressure = ONE_ATMOSPHERE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm index 3cbf1b4d0e..f2f2329661 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -38,7 +38,7 @@ id_tag = assign_uid_vents() /obj/machinery/atmospherics/components/unary/vent_pump/Destroy() - var/area/A = get_area(src) + var/area/A = get_base_area(src) if (A) A.air_vent_names -= id_tag A.air_vent_info -= id_tag @@ -155,7 +155,7 @@ "sigtype" = "status" )) - var/area/A = get_area(src) + var/area/A = get_base_area(src) if(!A.air_vent_names[id_tag]) name = "\improper [A.name] vent pump #[A.air_vent_names.len + 1]" A.air_vent_names[id_tag] = name diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index 22cd9d7fca..10eac9c717 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -39,7 +39,7 @@ filter_types += gas_id2path(f) /obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy() - var/area/A = get_area(src) + var/area/A = get_base_area(src) if (A) A.air_scrub_names -= id_tag A.air_scrub_info -= id_tag @@ -112,7 +112,7 @@ "sigtype" = "status" )) - var/area/A = get_area(src) + var/area/A = get_base_area(src) if(!A.air_scrub_names[id_tag]) name = "\improper [A.name] air scrubber #[A.air_scrub_names.len + 1]" A.air_scrub_names[id_tag] = name diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm index e8704b4c40..e0cf903465 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm @@ -1,6 +1,6 @@ //3-Way Manifold /obj/machinery/atmospherics/pipe/heat_exchanging/manifold - icon_state = "manifold" + icon_state = "manifold-2" name = "pipe manifold" desc = "A manifold composed of regular pipes." diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm index bd4e716357..8ceef76a06 100644 --- a/code/modules/awaymissions/capture_the_flag.dm +++ b/code/modules/awaymissions/capture_the_flag.dm @@ -7,8 +7,6 @@ #define AMMO_DROP_LIFETIME 300 #define CTF_REQUIRED_PLAYERS 4 - - /obj/item/twohanded/ctf name = "banner" icon = 'icons/obj/items_and_weapons.dmi' @@ -210,7 +208,6 @@ toggle_all_ctf(user) return - people_who_want_to_play |= user.ckey var/num = people_who_want_to_play.len var/remaining = CTF_REQUIRED_PLAYERS - num @@ -438,9 +435,9 @@ . = FALSE if(istype(target, /obj/structure/barricade/security/ctf)) . = TRUE - if(ishuman(target)) - var/mob/living/carbon/human/H = target - if(istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/shielded/ctf)) + if(isliving(target)) + var/mob/living/H = target + if((RED_TEAM in H.faction) || (BLUE_TEAM in H.faction)) . = TRUE // RED TEAM GUNS diff --git a/code/modules/cargo/bounties/silly.dm b/code/modules/cargo/bounties/silly.dm index f790126cf2..e0d2c87a2d 100644 --- a/code/modules/cargo/bounties/silly.dm +++ b/code/modules/cargo/bounties/silly.dm @@ -64,4 +64,3 @@ description = "Nanotrasen has secured a contract in a reenactment of a famous movie, but we only have lethal energy based swords. Send us some convincing replicas so we save on medical costs." reward = 1200 required_count = 3 - wanted_types = list(/obj/item/toy/sword, /obj/item/toy/sword/cx) \ No newline at end of file diff --git a/code/modules/cargo/exports/parts.dm b/code/modules/cargo/exports/parts.dm index e53db0bf7b..e4efaf0810 100644 --- a/code/modules/cargo/exports/parts.dm +++ b/code/modules/cargo/exports/parts.dm @@ -92,11 +92,42 @@ export_types = list(/obj/item/stock_parts/cell/bluespace) /datum/export/cellyellow - cost = 40 + cost = 200 unit_name = "slime power cell" export_types = list(/obj/item/stock_parts/cell/high/slime) /datum/export/cellyellowhyper - cost = 120 //Takes a lot to make and is really good + cost = 1200 //Takes a lot to make and is really good unit_name = "hyper slime power cell" - export_types = list(/obj/item/stock_parts/cell/high/slime/hypercharged) \ No newline at end of file + export_types = list(/obj/item/stock_parts/cell/high/slime/hypercharged) + +//Glass working stuff + +/datum/export/glasswork_dish + cost = 300 + unit_name = "small glass dish" + export_types = list(/obj/item/reagent_containers/glass/beaker/glass_dish) + include_subtypes = FALSE + +/datum/export/glasswork_lens + cost = 1800 + unit_name = "small glass lens" + export_types = list(/obj/item/lens) + +/datum/export/glasswork_spouty + cost = 1200 + unit_name = "flask with spout" + export_types = list(/obj/item/reagent_containers/glass/beaker/flask/spouty) + include_subtypes = FALSE + +/datum/export/glasswork_smallflask + cost = 600 + unit_name = "small flask" + export_types = list(/obj/item/reagent_containers/glass/beaker/flask) + include_subtypes = FALSE + +/datum/export/glasswork_largeflask + cost = 1000 + unit_name = "large flask" + export_types = list(/obj/item/reagent_containers/glass/beaker/flask/large) + include_subtypes = FALSE diff --git a/code/modules/cargo/packs/armory.dm b/code/modules/cargo/packs/armory.dm index 259ea2d7e3..ea8ef8ba0f 100644 --- a/code/modules/cargo/packs/armory.dm +++ b/code/modules/cargo/packs/armory.dm @@ -226,7 +226,7 @@ crate_name = "swat taser crate" /datum/supply_pack/security/armory/woodstock - name = "Classic WoodStock Shotguns Crate" + name = "WoodStock Classic Shotguns Crate" desc = "Contains three rustic, pumpaction shotguns. Requires Armory access to open." cost = 3000 contains = list(/obj/item/gun/ballistic/shotgun, diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm index 40d21e4505..4a64979502 100644 --- a/code/modules/cargo/packs/costumes_toys.dm +++ b/code/modules/cargo/packs/costumes_toys.dm @@ -3,12 +3,18 @@ // If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal // cost = 700- Minimum cost, or infinite points are possible. ////////////////////////////////////////////////////////////////////////////// -//////////////////////////// Costumes & Toys ///////////////////////////////// +////////////////////////////////// Toys ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /datum/supply_pack/costumes_toys group = "Costumes & Toys" +/datum/supply_pack/costumes_toys/randomised/fill(obj/structure/closet/crate/C) + var/list/L = contains.Copy() + for(var/i in 1 to num_contained) + var/item = pick_n_take(L) + new item(C) + /datum/supply_pack/costumes_toys/randomised name = "Collectable Hats Crate" desc = "Flaunt your status with three unique, highly-collectable hats!" @@ -92,40 +98,6 @@ /obj/item/ammo_box/magazine/toy/pistol) crate_name = "foam force crate" -/datum/supply_pack/costumes_toys/formalwear - name = "Formalwear Crate" - desc = "You're gonna like the way you look, I guaranteed it. Contains an asston of fancy clothing." - cost = 4750 //Lots of fancy clothing that can be sold back! - contains = list(/obj/item/clothing/under/blacktango, - /obj/item/clothing/under/assistantformal, - /obj/item/clothing/under/assistantformal, - /obj/item/clothing/under/lawyer/bluesuit, - /obj/item/clothing/suit/toggle/lawyer, - /obj/item/clothing/under/lawyer/purpsuit, - /obj/item/clothing/suit/toggle/lawyer/purple, - /obj/item/clothing/under/lawyer/blacksuit, - /obj/item/clothing/suit/toggle/lawyer/black, - /obj/item/clothing/accessory/waistcoat, - /obj/item/clothing/neck/tie/blue, - /obj/item/clothing/neck/tie/red, - /obj/item/clothing/neck/tie/black, - /obj/item/clothing/head/bowler, - /obj/item/clothing/head/fedora, - /obj/item/clothing/head/flatcap, - /obj/item/clothing/head/beret, - /obj/item/clothing/head/that, - /obj/item/clothing/shoes/laceup, - /obj/item/clothing/shoes/laceup, - /obj/item/clothing/shoes/laceup, - /obj/item/clothing/under/suit_jacket/charcoal, - /obj/item/clothing/under/suit_jacket/navy, - /obj/item/clothing/under/suit_jacket/burgundy, - /obj/item/clothing/under/suit_jacket/checkered, - /obj/item/clothing/under/suit_jacket/tan, - /obj/item/lipstick/random) - crate_name = "formalwear crate" - crate_type = /obj/structure/closet/crate/wooden - /datum/supply_pack/costumes_toys/clownpin name = "Hilarious Firing Pin Crate" desc = "I uh... I'm not really sure what this does. Wanna buy it?" @@ -167,47 +139,6 @@ contains = list(/obj/item/storage/box/lasertagpins) crate_name = "laser tag crate" -/datum/supply_pack/costumes_toys/costume_original - name = "Original Costume Crate" - desc = "Reenact Shakespearean plays with this assortment of outfits. Contains eight different costumes!" - cost = 1750 - contains = list(/obj/item/clothing/head/snowman, - /obj/item/clothing/suit/snowman, - /obj/item/clothing/head/chicken, - /obj/item/clothing/suit/chickensuit, - /obj/item/clothing/mask/gas/monkeymask, - /obj/item/clothing/suit/monkeysuit, - /obj/item/clothing/head/cardborg, - /obj/item/clothing/suit/cardborg, - /obj/item/clothing/head/xenos, - /obj/item/clothing/suit/xenos, - /obj/item/clothing/suit/hooded/ian_costume, - /obj/item/clothing/suit/hooded/carp_costume, - /obj/item/clothing/suit/hooded/bee_costume) - crate_name = "original costume crate" - crate_type = /obj/structure/closet/crate/wooden - -/datum/supply_pack/costumes_toys/costume - name = "Standard Costume Crate" - desc = "Supply the station's entertainers with the equipment of their trade with these Nanotrasen-approved costumes! Contains a full clown and mime outfit, along with a bike horn and a bottle of nothing." - cost = 1300 - access = ACCESS_THEATRE - contains = list(/obj/item/storage/backpack/clown, - /obj/item/clothing/shoes/clown_shoes, - /obj/item/clothing/mask/gas/clown_hat, - /obj/item/clothing/under/rank/clown, - /obj/item/bikehorn, - /obj/item/clothing/under/rank/mime, - /obj/item/clothing/shoes/sneakers/black, - /obj/item/clothing/gloves/color/white, - /obj/item/clothing/mask/gas/mime, - /obj/item/clothing/head/beret, - /obj/item/clothing/suit/suspenders, - /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing, - /obj/item/storage/backpack/mime) - crate_name = "standard costume crate" - crate_type = /obj/structure/closet/crate/wooden - /datum/supply_pack/costumes_toys/randomised/toys name = "Toy Crate" desc = "Who cares about pride and accomplishment? Skip the gaming and get straight to the sweet rewards with this product! Contains five random toys. Warranty void if used to prank research directors." @@ -278,6 +209,86 @@ crate_name = "plushie crate" crate_type = /obj/structure/closet/crate/wooden + +////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// Costumes ////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/costumes_toys/formalwear + name = "Formalwear Crate" + desc = "You're gonna like the way you look, I guaranteed it. Contains an asston of fancy clothing." + cost = 4750 //Lots of fancy clothing that can be sold back! + contains = list(/obj/item/clothing/under/blacktango, + /obj/item/clothing/under/assistantformal, + /obj/item/clothing/under/assistantformal, + /obj/item/clothing/under/lawyer/bluesuit, + /obj/item/clothing/suit/toggle/lawyer, + /obj/item/clothing/under/lawyer/purpsuit, + /obj/item/clothing/suit/toggle/lawyer/purple, + /obj/item/clothing/under/lawyer/blacksuit, + /obj/item/clothing/suit/toggle/lawyer/black, + /obj/item/clothing/accessory/waistcoat, + /obj/item/clothing/neck/tie/blue, + /obj/item/clothing/neck/tie/red, + /obj/item/clothing/neck/tie/black, + /obj/item/clothing/head/bowler, + /obj/item/clothing/head/fedora, + /obj/item/clothing/head/flatcap, + /obj/item/clothing/head/beret, + /obj/item/clothing/head/that, + /obj/item/clothing/shoes/laceup, + /obj/item/clothing/shoes/laceup, + /obj/item/clothing/shoes/laceup, + /obj/item/clothing/under/suit_jacket/charcoal, + /obj/item/clothing/under/suit_jacket/navy, + /obj/item/clothing/under/suit_jacket/burgundy, + /obj/item/clothing/under/suit_jacket/checkered, + /obj/item/clothing/under/suit_jacket/tan, + /obj/item/lipstick/random) + crate_name = "formalwear crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/costume_original + name = "Original Costume Crate" + desc = "Reenact Shakespearean plays with this assortment of outfits. Contains eight different costumes!" + cost = 1750 + contains = list(/obj/item/clothing/head/snowman, + /obj/item/clothing/suit/snowman, + /obj/item/clothing/head/chicken, + /obj/item/clothing/suit/chickensuit, + /obj/item/clothing/mask/gas/monkeymask, + /obj/item/clothing/suit/monkeysuit, + /obj/item/clothing/head/cardborg, + /obj/item/clothing/suit/cardborg, + /obj/item/clothing/head/xenos, + /obj/item/clothing/suit/xenos, + /obj/item/clothing/suit/hooded/ian_costume, + /obj/item/clothing/suit/hooded/carp_costume, + /obj/item/clothing/suit/hooded/bee_costume) + crate_name = "original costume crate" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/costume + name = "Standard Costume Crate" + desc = "Supply the station's entertainers with the equipment of their trade with these Nanotrasen-approved costumes! Contains a full clown and mime outfit, along with a bike horn and a bottle of nothing." + cost = 1300 + access = ACCESS_THEATRE + contains = list(/obj/item/storage/backpack/clown, + /obj/item/clothing/shoes/clown_shoes, + /obj/item/clothing/mask/gas/clown_hat, + /obj/item/clothing/under/rank/clown, + /obj/item/bikehorn, + /obj/item/clothing/under/rank/mime, + /obj/item/clothing/shoes/sneakers/black, + /obj/item/clothing/gloves/color/white, + /obj/item/clothing/mask/gas/mime, + /obj/item/clothing/head/beret, + /obj/item/clothing/suit/suspenders, + /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing, + /obj/item/storage/backpack/mime) + crate_name = "standard costume crate" + crate_type = /obj/structure/closet/crate/wooden + /datum/supply_pack/costumes_toys/wizard name = "Wizard Costume Crate" desc = "Pretend to join the Wizard Federation with this full wizard outfit! Nanotrasen would like to remind its employees that actually joining the Wizard Federation is subject to termination of job and life." @@ -288,82 +299,3 @@ /obj/item/clothing/head/wizard/fake) crate_name = "wizard costume crate" crate_type = /obj/structure/closet/crate/wooden - -/datum/supply_pack/costumes_toys/randomised/fill(obj/structure/closet/crate/C) - var/list/L = contains.Copy() - for(var/i in 1 to num_contained) - var/item = pick_n_take(L) - new item(C) - -/datum/supply_pack/costumes_toys/wardrobes/autodrobe - name = "Autodrobe Supply Crate" - desc = "Autodrobe missing your favorite dress? Solve that issue today with this autodrobe refill." - cost = 1500 - contains = list(/obj/item/vending_refill/autodrobe) - crate_name = "autodrobe supply crate" - -/datum/supply_pack/costumes_toys/wardrobes/cargo - name = "Cargo Wardrobe Supply Crate" - desc = "This crate contains a refill for the CargoDrobe." - cost = 750 - contains = list(/obj/item/vending_refill/wardrobe/cargo_wardrobe) - crate_name = "cargo department supply crate" - -/datum/supply_pack/costumes_toys/wardrobes/engineering - name = "Engineering Wardrobe Supply Crate" - desc = "This crate contains refills for the EngiDrobe and AtmosDrobe." - cost = 1500 - contains = list(/obj/item/vending_refill/wardrobe/engi_wardrobe, - /obj/item/vending_refill/wardrobe/atmos_wardrobe) - crate_name = "engineering department wardrobe supply crate" - -/datum/supply_pack/costumes_toys/wardrobes/general - name = "General Wardrobes Supply Crate" - desc = "This crate contains refills for the CuraDrobe, BarDrobe, ChefDrobe, JaniDrobe, ChapDrobe." - cost = 3750 - contains = list(/obj/item/vending_refill/wardrobe/curator_wardrobe, - /obj/item/vending_refill/wardrobe/bar_wardrobe, - /obj/item/vending_refill/wardrobe/chef_wardrobe, - /obj/item/vending_refill/wardrobe/jani_wardrobe, - /obj/item/vending_refill/wardrobe/chap_wardrobe) - crate_name = "general wardrobes vendor refills" - -/datum/supply_pack/costumes_toys/wardrobes/hydroponics - name = "Hydrobe Supply Crate" - desc = "This crate contains a refill for the Hydrobe." - cost = 750 - contains = list(/obj/item/vending_refill/wardrobe/hydro_wardrobe) - crate_name = "hydrobe supply crate" - -/datum/supply_pack/costumes_toys/wardrobes/medical - name = "Medical Wardrobe Supply Crate" - desc = "This crate contains refills for the MediDrobe, ChemDrobe, GeneDrobe, and ViroDrobe." - cost = 3000 - contains = list(/obj/item/vending_refill/wardrobe/medi_wardrobe, - /obj/item/vending_refill/wardrobe/chem_wardrobe, - /obj/item/vending_refill/wardrobe/gene_wardrobe, - /obj/item/vending_refill/wardrobe/viro_wardrobe) - crate_name = "medical department wardrobe supply crate" - -/datum/supply_pack/costumes_toys/wardrobes/science - name = "Science Wardrobe Supply Crate" - desc = "This crate contains refills for the SciDrobe and RoboDrobe." - cost = 1500 - contains = list(/obj/item/vending_refill/wardrobe/robo_wardrobe, - /obj/item/vending_refill/wardrobe/science_wardrobe) - crate_name = "science department wardrobe supply crate" - -/datum/supply_pack/costumes_toys/wardrobes/security - name = "Security Wardrobe Supply Crate" - desc = "This crate contains refills for the SecDrobe and LawDrobe." - cost = 1500 - contains = list(/obj/item/vending_refill/wardrobe/sec_wardrobe, - /obj/item/vending_refill/wardrobe/law_wardrobe) - crate_name = "security department supply crate" - -/datum/supply_pack/costumes_toys/kinkmate - name = "Kinkmate construction kit" - cost = 2000 - contraband = TRUE - contains = list(/obj/item/vending_refill/kink, /obj/item/circuitboard/machine/kinkmate) - crate_name = "Kinkmate construction kit" diff --git a/code/modules/cargo/packs/emergency.dm b/code/modules/cargo/packs/emergency.dm index 747e820f52..e32811f2d0 100644 --- a/code/modules/cargo/packs/emergency.dm +++ b/code/modules/cargo/packs/emergency.dm @@ -11,11 +11,13 @@ /datum/supply_pack/emergency/vehicle name = "Biker Gang Kit" //TUNNEL SNAKES OWN THIS TOWN - desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, and a complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!" + desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, two cans of spraypaint, and a complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!" cost = 2500 contraband = TRUE contains = list(/obj/vehicle/ridden/atv, /obj/item/key, + /obj/item/toy/crayon/spraycan, + /obj/item/toy/crayon/spraycan, /obj/item/clothing/suit/jacket/leather/overcoat, /obj/item/clothing/gloves/color/black, /obj/item/clothing/head/soft, @@ -126,21 +128,6 @@ crate_name = "emergency rcds" crate_type = /obj/structure/closet/crate/internals -/datum/supply_pack/emergency/soft_suit - name = "Emergency Space Suit" - desc = "Are there bombs going off left and right? Are there meteors shooting around the station? Well then! Here's two fragile space suits for emergencies. Comes with air and masks." - cost = 1200 - contains = list(/obj/item/tank/internals/air, - /obj/item/tank/internals/air, - /obj/item/clothing/mask/gas, - /obj/item/clothing/mask/gas, - /obj/item/clothing/suit/space/fragile, - /obj/item/clothing/suit/space/fragile, - /obj/item/clothing/head/helmet/space/fragile, - /obj/item/clothing/head/helmet/space/fragile) - crate_name = "emergency crate" - crate_type = /obj/structure/closet/crate/internals - /datum/supply_pack/emergency/bomb name = "Explosive Emergency Crate" desc = "Science gone bonkers? Beeping behind the airlock? Buy now and be the hero the station des... I mean needs! (Time not included.)" @@ -208,7 +195,7 @@ crate_name = "metal foam grenade crate" /datum/supply_pack/emergency/mre - name = "MRE supply kit (emergency rations)" + name = "MRE Packs (Emergency Rations)" desc = "The lights are out. Oxygen's running low. You've run out of food except space weevils. Don't let this be you! Order our NT branded MRE kits today! This pack contains 5 MRE packs with a randomized menu and an oxygen tank." cost = 2000 contains = list(/obj/item/storage/box/mre/menu1/safe, @@ -296,6 +283,21 @@ crate_name = "space suit crate" crate_type = /obj/structure/closet/crate/secure +/datum/supply_pack/emergency/soft_suit + name = "Space Suits (Fragile)" + desc = "Are there bombs going off left and right? Are there meteors shooting around the station? Well then! Here's two fragile space suits for emergencies. Comes with air and masks." + cost = 1200 + contains = list(/obj/item/tank/internals/air, + /obj/item/tank/internals/air, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/clothing/suit/space/fragile, + /obj/item/clothing/suit/space/fragile, + /obj/item/clothing/head/helmet/space/fragile, + /obj/item/clothing/head/helmet/space/fragile) + crate_name = "emergency crate" + crate_type = /obj/structure/closet/crate/internals + /datum/supply_pack/emergency/spacejets name = "Spare EVA Jetpacks" desc = "Contains three EVA grade jectpaks. Requires EVA access to open." diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm index 6492df5215..22258d19a7 100644 --- a/code/modules/cargo/packs/engineering.dm +++ b/code/modules/cargo/packs/engineering.dm @@ -3,7 +3,7 @@ // If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal // cost = 700- Minimum cost, or infinite points are possible. ////////////////////////////////////////////////////////////////////////////// -//////////////////////////// Engineering ///////////////////////////////////// +///////////////////////////// Engineering //////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /datum/supply_pack/engineering @@ -45,6 +45,7 @@ /obj/item/clothing/glasses/meson/engine, /obj/item/clothing/glasses/meson/engine) crate_name = "engineering gear crate" + crate_type = /obj/structure/closet/crate/secure/engineering /datum/supply_pack/engineering/engihardsuit name = "Engineering Hardsuit" @@ -55,6 +56,7 @@ /obj/item/clothing/mask/gas, /obj/item/clothing/suit/space/hardsuit/engine) crate_name = "engineering hardsuit" + crate_type = /obj/structure/closet/crate/secure/engineering /datum/supply_pack/engineering/atmoshardsuit name = "Atmospherics Hardsuit" @@ -114,6 +116,22 @@ crate_name = "PACMAN generator crate" crate_type = /obj/structure/closet/crate/engineering/electrical +/datum/supply_pack/engineering/airpump + name = "Portable Air Pump Crate" + desc = "We all know you work in a high pressure workplace. Keep it that way with two additional air pumps!" + cost = 3000 + contains = list(/obj/machinery/portable_atmospherics/pump, + /obj/machinery/portable_atmospherics/pump) + crate_name = "portable air pump crate" + +/datum/supply_pack/engineering/airscrubber + name = "Portable Scrubber Crate" + desc = "Miasma got you down? Plasma in the vents? Freshen up with these two brand-new air scrubbers!" + cost = 3000 + contains = list(/obj/machinery/portable_atmospherics/scrubber, + /obj/machinery/portable_atmospherics/scrubber) + crate_name = "portable scrubber crate" + /datum/supply_pack/engineering/power name = "Power Cell Crate" desc = "Looking for power overwhelming? Look no further. Contains three high-voltage power cells." diff --git a/code/modules/cargo/packs/materials.dm b/code/modules/cargo/packs/materials.dm index c9862282dc..6c1742896f 100644 --- a/code/modules/cargo/packs/materials.dm +++ b/code/modules/cargo/packs/materials.dm @@ -69,6 +69,11 @@ contains = list(/obj/item/grown/log) crate_name = "lumber crate" +/datum/supply_pack/materials/rawlumber/generate() + . = ..() + for(var/i in 1 to 49) + new /obj/item/grown/log(.) + /datum/supply_pack/materials/wood50 name = "50 Wood Planks" desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!" @@ -89,7 +94,7 @@ /datum/supply_pack/materials/rawcottonbulk name = "Raw Cotton Crate (Bulk)" desc = "We have so much of this stuff we need to get rid of it in -bulk- now. This crate contains 240 raw cotton sheets." - cost = 1300 // 100 net cost (per 40 cotton) , 20 x 20 = 400. 300 profit if turned into cloth sheets or more if turned to silk then 10 x 200 = 2000 + cost = 1300 // 600 net cost 20 x 120 = 2400 profit if turned into cloth sheets or if turned into silk 200 x 60 = 12000 contains = list(/obj/item/stack/sheet/cotton/thirty, /obj/item/stack/sheet/cotton/thirty, /obj/item/stack/sheet/cotton/thirty, @@ -102,13 +107,8 @@ crate_name = "bulk cotton crate" crate_type = /obj/structure/closet/crate/hydroponics -/datum/supply_pack/critter/animal_feed/generate() - . = ..() - for(var/i in 1 to 49) - new /obj/item/grown/log(.) - /datum/supply_pack/materials/rcdammo - name = "Spare RDC ammo" + name = "Spare RCD ammo" desc = "This crate contains sixteen RCD compressed matter packs, to help with any holes or projects people might be working on." cost = 3750 contains = list(/obj/item/rcd_ammo, diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index a60afe4f7a..ea327ae820 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -10,6 +10,10 @@ group = "Medical" crate_type = /obj/structure/closet/crate/medical +////////////////////////////////////////////////////////////////////////////// +/////////////////////////////// Equipment //////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + /datum/supply_pack/medical/bodybags name = "Bodybags" desc = "For when the bodies hit the floor. Contains 4 boxes of bodybags." @@ -20,24 +24,6 @@ /obj/item/storage/box/bodybags,) crate_name = "bodybag crate" -/datum/supply_pack/medical/firstaidbruises - name = "Bruise Treatment Kit Crate" - desc = "Contains three first aid kits focused on healing bruises and broken bones." - cost = 1000 - contains = list(/obj/item/storage/firstaid/brute, - /obj/item/storage/firstaid/brute, - /obj/item/storage/firstaid/brute) - crate_name = "brute treatment kit crate" - -/datum/supply_pack/medical/firstaidburns - name = "Burn Treatment Kit Crate" - desc = "Contains three first aid kits focused on healing severe burns." - cost = 1000 - contains = list(/obj/item/storage/firstaid/fire, - /obj/item/storage/firstaid/fire, - /obj/item/storage/firstaid/fire) - crate_name = "burn treatment kit crate" - /datum/supply_pack/medical/bloodpacks name = "Blood Pack Variety Crate" desc = "Contains nine different blood packs for reintroducing blood to patients, plus two universal synthetic blood packs." @@ -86,16 +72,6 @@ /obj/item/defibrillator/loaded) crate_name = "defibrillator crate" -/datum/supply_pack/medical/firstaid - name = "First Aid Kit Crate" - desc = "Contains four first aid kits for healing most types of wounds." - cost = 1000 - contains = list(/obj/item/storage/firstaid/regular, - /obj/item/storage/firstaid/regular, - /obj/item/storage/firstaid/regular, - /obj/item/storage/firstaid/regular) - crate_name = "first aid kit crate" - /datum/supply_pack/medical/iv_drip name = "IV Drip Crate" desc = "Contains a single IV drip stand for intravenous delivery." @@ -103,17 +79,6 @@ contains = list(/obj/machinery/iv_drip) crate_name = "iv drip crate" -/datum/supply_pack/science/adv_surgery_tools - name = "Med-Co Advanced surgery tools" - desc = "A full set of Med-Co advanced surgery tools! In addition to that it contains both a can of synthflesh and a can of sterilizine. Requires Surgery access to open." - cost = 5500 - access = ACCESS_SURGERY - contains = list(/obj/item/storage/belt/medical/surgery_belt_adv, - /obj/item/reagent_containers/medspray/synthflesh, - /obj/item/reagent_containers/medspray/sterilizine) - crate_name = "medco newest surgery tools" - crate_type = /obj/structure/closet/crate/medical - /datum/supply_pack/medical/medicalhardsuit name = "Medical Hardsuit" desc = "Got people being spaced left and right? Hole in the same room as the dead body of Hos or cap? Fear not, now you can buy one medical hardsuit with a mask and air tank to save your fellow crewmembers. Requires medical access to open." @@ -151,13 +116,57 @@ /obj/item/storage/pill_bottle/stimulant) crate_name = "medical supplies crate" -/datum/supply_pack/medical/vending - name = "Medical Vending Crate" - desc = "Contains refills for medical vending machines." - cost = 2000 - contains = list(/obj/item/vending_refill/medical, - /obj/item/vending_refill/wallmed) - crate_name = "medical vending crate" +/datum/supply_pack/medical/adv_surgery_tools + name = "Med-Co Advanced Surgery Tools" + desc = "A full set of Med-Co advanced surgery tools, this crate also comes with a spay of synth flesh as well as a can of . Requires Surgery access to open." + cost = 5500 + access = ACCESS_SURGERY + contains = list(/obj/item/storage/belt/medical/surgery_belt_adv, + /obj/item/reagent_containers/medspray/synthflesh, + /obj/item/reagent_containers/medspray/sterilizine) + crate_name = "medco surgery tools" + crate_type = /obj/structure/closet/crate/medical + +/datum/supply_pack/medical/surgery + name = "Surgical Supplies Crate" + desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed." + cost = 1300 + contains = list(/obj/item/storage/backpack/duffelbag/med/surgery, + /obj/item/reagent_containers/medspray/sterilizine, + /obj/item/roller) + crate_name = "surgical supplies crate" + +////////////////////////////////////////////////////////////////////////////// +///////////////////////////// Medical Kits /////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/medical/firstaidbruises + name = "Bruise Treatment Kit Crate" + desc = "Contains three first aid kits focused on healing bruises and broken bones." + cost = 1000 + contains = list(/obj/item/storage/firstaid/brute, + /obj/item/storage/firstaid/brute, + /obj/item/storage/firstaid/brute) + crate_name = "brute treatment kit crate" + +/datum/supply_pack/medical/firstaidburns + name = "Burn Treatment Kit Crate" + desc = "Contains three first aid kits focused on healing severe burns." + cost = 1000 + contains = list(/obj/item/storage/firstaid/fire, + /obj/item/storage/firstaid/fire, + /obj/item/storage/firstaid/fire) + crate_name = "burn treatment kit crate" + +/datum/supply_pack/medical/firstaid + name = "First Aid Kit Crate" + desc = "Contains four first aid kits for healing most types of wounds." + cost = 1000 + contains = list(/obj/item/storage/firstaid/regular, + /obj/item/storage/firstaid/regular, + /obj/item/storage/firstaid/regular, + /obj/item/storage/firstaid/regular) + crate_name = "first aid kit crate" /datum/supply_pack/medical/sprays name = "Medical Sprays" @@ -193,6 +202,15 @@ /obj/item/storage/firstaid/o2) crate_name = "oxygen deprivation kit crate" +/datum/supply_pack/medical/firstaidtoxins + name = "Toxin Treatment Kit Crate" + desc = "Contains three first aid kits focused on healing damage dealt by heavy toxins." + cost = 1000 + contains = list(/obj/item/storage/firstaid/toxin, + /obj/item/storage/firstaid/toxin, + /obj/item/storage/firstaid/toxin) + crate_name = "toxin treatment kit crate" + /datum/supply_pack/medical/advrad name = "Radiation Treatment Crate Deluxe" desc = "A crate for when radiation is out of hand... Contains two rad-b-gone kits, one bottle of anti radiation deluxe pills, as well as a radiation treatment deluxe pill bottle!" @@ -206,23 +224,9 @@ crate_name = "radiation protection crate" crate_type = /obj/structure/closet/crate/radiation -/datum/supply_pack/medical/surgery - name = "Surgical Supplies Crate" - desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed." - cost = 1300 - contains = list(/obj/item/storage/backpack/duffelbag/med/surgery, - /obj/item/reagent_containers/medspray/sterilizine, - /obj/item/roller) - crate_name = "surgical supplies crate" - -/datum/supply_pack/medical/firstaidtoxins - name = "Toxin Treatment Kit Crate" - desc = "Contains three first aid kits focused on healing damage dealt by heavy toxins." - cost = 1000 - contains = list(/obj/item/storage/firstaid/toxin, - /obj/item/storage/firstaid/toxin, - /obj/item/storage/firstaid/toxin) - crate_name = "toxin treatment kit crate" +////////////////////////////////////////////////////////////////////////////// +//////////////////////////////// Virology //////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// /datum/supply_pack/medical/virus name = "Virus Crate" @@ -266,4 +270,4 @@ /obj/item/storage/box/syringes, /obj/item/storage/box/beakers) crate_name = "virus containment unit crate" - crate_type = /obj/structure/closet/crate/secure/plasma + crate_type = /obj/structure/closet/crate/secure/plasma \ No newline at end of file diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm index f8656ef761..b53b7761e5 100644 --- a/code/modules/cargo/packs/misc.dm +++ b/code/modules/cargo/packs/misc.dm @@ -13,16 +13,6 @@ //////////////////// Paperwork and Writing Supplies ////////////////////////// ////////////////////////////////////////////////////////////////////////////// -/datum/supply_pack/misc/abandonedcrate - name = "Loot Box" - desc = "Try your luck with these highly secure loot boxes! Solve the lock, win great prizes! WARNING: EXPLOSIVE FAILURE." - contraband = TRUE - cost = 15000 - contains = list(/obj/structure/closet/crate/secure/loot) - crate_name = "abandoned crate" - crate_type = /obj/structure/closet/crate/large - dangerous = TRUE - /datum/supply_pack/misc/artsupply name = "Art Supplies" desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!" @@ -83,7 +73,7 @@ name = "Captain Pen" desc = "A spare Captain fountain pen." access = ACCESS_CAPTAIN - cost = 10000 + cost = 5000 contains = list(/obj/item/pen/fountain/captain) crate_name = "captain pen" crate_type = /obj/structure/closet/crate/secure/weapon //It is a combat pen @@ -153,7 +143,7 @@ /obj/item/bedsheet/purple, /obj/item/bedsheet/red, /obj/item/bedsheet/yellow, - /obj/item/bedsheet/brown, + /obj/item/bedsheet/brown, /obj/item/bedsheet/black, /obj/item/bedsheet/rainbow) crate_name = "colored bedsheet crate" @@ -182,18 +172,6 @@ /obj/structure/piano/unanchored) crate_type = /obj/structure/closet/crate/wooden -/datum/supply_pack/misc/cbtpack - name = "CBT Equipment" - desc = "(*!&@#CBT is a special term coined by high ranking syndicate operatives for a special form of information extraction. While the training required to use this shipment is highly classified, the distribution of it's contents are not. In addition to this crates unusual contents, we have added a bar of soap.#@*$" - hidden = TRUE - cost = 2400 - contains = list(/mob/living/simple_animal/chicken, - /obj/item/toy/beach_ball/holoball, - /obj/item/melee/baton/cattleprod, - /obj/item/soap/syndie) - crate_name = "cbt crate" - crate_type = /obj/structure/closet/crate/large - /datum/supply_pack/misc/casinocrate name = "Casino Crate" desc = "Start up your own grand casino with this crate filled with slot machine and arcade boards!" @@ -216,8 +194,8 @@ name = "Coin Crate" desc = "Psssst, hey, you. Yes, you. I've heard that coins can do some special things on your station, give you access to some pretty cool stuff. Here's the deal, you give me some credits, and I give so some coins. Sound like a deal? I'll give you 10 for 10000 creds." contraband = TRUE - cost = 10000 - contains = list(/obj/item/coin/silver) + cost = 3000 + contains = list(/obj/item/coin/silver) // 400 x 10 = 2 sheets of silver for 2300cr crate_name = "coin crate" crate_type = /obj/structure/closet/crate/large @@ -226,10 +204,41 @@ for(var/i in 1 to 9) new /obj/item/coin/silver(.) +/datum/supply_pack/misc/dirtymags + name = "Dirty Magazines" + desc = "Get your mind out of the gutter operative, you have work to do. Three items per order. Possible Results: .357 Speedloaders, Kitchen Gun Mags, Stetchkin Mags." + hidden = TRUE + cost = 12000 + var/num_contained = 3 + contains = list(/obj/item/ammo_box/a357, + /obj/item/ammo_box/a357, + /obj/item/ammo_box/a357, + /obj/item/ammo_box/magazine/pistolm9mm, + /obj/item/ammo_box/magazine/pistolm9mm, + /obj/item/ammo_box/magazine/pistolm9mm, + /obj/item/ammo_box/magazine/m45/kitchengun, + /obj/item/ammo_box/magazine/m45/kitchengun) + crate_name = "crate" + +/datum/supply_pack/misc/dirtymags/fill(obj/structure/closet/crate/C) + var/list/L = contains.Copy() + for(var/i in 1 to num_contained) + var/item = pick_n_take(L) + new item(C) + ////////////////////////////////////////////////////////////////////////////// -//////////////////////////////// Misc Supplies /////////////////////////////// +///////////////////////////////// Misc Supplies ////////////////////////////// ////////////////////////////////////////////////////////////////////////////// +/datum/supply_pack/misc/candles + name = "Candle Crate" + desc = "Set up a romantic dinner or host a séance with these extra candles and crayons." + cost = 850 + contains = list(/obj/item/storage/fancy/candle_box, + /obj/item/storage/fancy/candle_box, + /obj/item/storage/box/matches) + crate_name = "candle crate" + /datum/supply_pack/misc/exoticfootwear name = "Exotic Footwear Crate" desc = "Popularised by lizards and exotic dancers, the footwear included in this shipment is sure to give your feet the breathing room they deserve. Sweet Kicks Inc. is not responsible for any damage, distress, or @r0u$a1 caused by this shipment." @@ -246,13 +255,24 @@ /obj/item/clothing/shoes/kindleKicks) crate_name = "footie crate" -/datum/supply_pack/misc/wrapping_paper - name = "Festive Wrapping Paper Crate" - desc = "Want to mail your loved ones gift-wrapped chocolates, stuffed animals, or the Clown's severed head? You can do all that, with this crate full of wrapping paper." - cost = 1000 - contains = list(/obj/item/stack/wrapping_paper) - crate_type = /obj/structure/closet/crate/wooden - crate_name = "festive wrapping paper crate" +/datum/supply_pack/misc/funeral + name = "Funeral Supplies" + desc = "Mourn your dead properly buy sending them off with love filled notes, clean clothes, and a proper ceremony. Contains two candle packs, funeral garb, flowers, a paperbin , and crayons to help aid in religious rituals. Coffin included." + cost = 1200 + contains = list(/obj/item/clothing/under/burial, + /obj/item/storage/fancy/candle_box, + /obj/item/storage/fancy/candle_box, + /obj/item/reagent_containers/food/snacks/grown/harebell, + /obj/item/reagent_containers/food/snacks/grown/harebell, + /obj/item/reagent_containers/food/snacks/grown/poppy/geranium, + /obj/item/reagent_containers/food/snacks/grown/poppy/geranium, + /obj/item/reagent_containers/food/snacks/grown/poppy/lily, + /obj/item/reagent_containers/food/snacks/grown/poppy/lily, + /obj/item/storage/crayons, + /obj/item/paper_bin + ) + crate_name = "coffin" + crate_type = /obj/structure/closet/crate/coffin /datum/supply_pack/misc/jukebox name = "Jukebox" @@ -260,6 +280,16 @@ contains = list(/obj/machinery/jukebox) crate_name = "Jukebox" +/datum/supply_pack/misc/abandonedcrate + name = "Loot Box" + desc = "Try your luck with these highly secure loot boxes! Solve the lock, win great prizes! WARNING: EXPLOSIVE FAILURE." + contraband = TRUE + cost = 15000 + contains = list(/obj/structure/closet/crate/secure/loot) + crate_name = "abandoned crate" + crate_type = /obj/structure/closet/crate/large + dangerous = TRUE + /datum/supply_pack/misc/potted_plants name = "Potted Plants Crate" desc = "Spruce up the station with these lovely plants! Contains a random assortment of five potted plants from Nanotrasen's potted plant research division. Warranty void if thrown." @@ -284,25 +314,6 @@ /obj/item/clothing/suit/hooded/chaplain_hoodie) crate_name = "religious supplies crate" -/datum/supply_pack/misc/funeral - name = "Funeral Supplies" - desc = "Mourn your dead properly buy sending them off with love filled notes, clean clothes, and a proper ceremony. Contains two candle packs, funeral garb, flowers, a paperbin , and crayons to help aid in religious rituals. Coffin included." - cost = 1200 - contains = list(/obj/item/clothing/under/burial, - /obj/item/storage/fancy/candle_box, - /obj/item/storage/fancy/candle_box, - /obj/item/reagent_containers/food/snacks/grown/harebell, - /obj/item/reagent_containers/food/snacks/grown/harebell, - /obj/item/reagent_containers/food/snacks/grown/poppy/geranium, - /obj/item/reagent_containers/food/snacks/grown/poppy/geranium, - /obj/item/reagent_containers/food/snacks/grown/poppy/lily, - /obj/item/reagent_containers/food/snacks/grown/poppy/lily, - /obj/item/storage/crayons, - /obj/item/paper_bin - ) - crate_name = "coffin" - crate_type = /obj/structure/closet/crate/coffin - /datum/supply_pack/misc/shower name = "Shower Supplies" desc = "Everyone needs a bit of R&R. Make sure you get can get yours by ordering this crate filled with towels, rubber duckies, and some soap!" @@ -362,29 +373,6 @@ /obj/item/stack/tile/carpet/monochrome/fifty) crate_name = "premium carpet crate" -/datum/supply_pack/misc/party - name = "Party Equipment" - desc = "Celebrate both life and death on the station with Nanotrasen's Party Essentials(tm)! Contains seven colored glowsticks, four beers, two ales, a drinking shaker, and a bottle of patron & goldschlager!" - cost = 2000 - contains = list(/obj/item/storage/box/drinkingglasses, - /obj/item/reagent_containers/food/drinks/shaker, - /obj/item/reagent_containers/food/drinks/bottle/patron, - /obj/item/reagent_containers/food/drinks/bottle/goldschlager, - /obj/item/reagent_containers/food/drinks/ale, - /obj/item/reagent_containers/food/drinks/ale, - /obj/item/reagent_containers/food/drinks/beer, - /obj/item/reagent_containers/food/drinks/beer, - /obj/item/reagent_containers/food/drinks/beer, - /obj/item/reagent_containers/food/drinks/beer, - /obj/item/flashlight/glowstick, - /obj/item/flashlight/glowstick/red, - /obj/item/flashlight/glowstick/blue, - /obj/item/flashlight/glowstick/cyan, - /obj/item/flashlight/glowstick/orange, - /obj/item/flashlight/glowstick/yellow, - /obj/item/flashlight/glowstick/pink) - crate_name = "party equipment crate" - /datum/supply_pack/misc/noslipfloor name = "High-traction Floor Tiles" desc = "Make slipping a thing of the past with sixty industrial-grade anti-slip floortiles!" diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm index dd0f987d25..4aa991fc3f 100644 --- a/code/modules/cargo/packs/organic.dm +++ b/code/modules/cargo/packs/organic.dm @@ -3,22 +3,47 @@ // If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal // cost = 700- Minimum cost, or infinite points are possible. ////////////////////////////////////////////////////////////////////////////// -//////////////////////////// Organic ///////////////////////////////////////// +//////////////////////////////// Organic ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /datum/supply_pack/organic group = "Food & Hydroponics" crate_type = /obj/structure/closet/crate/freezer +/datum/supply_pack/organic/randomized + var/num_contained = 15 + +/datum/supply_pack/organic/randomized/fill(obj/structure/closet/crate/C) + for(var/i in 1 to num_contained) + var/item = pick(contains) + new item(C) + ////////////////////////////////////////////////////////////////////////////// -/////////////////////////////// Food ///////////////////////////////////////// +//////////////////////////////// Meals /////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -/datum/supply_pack/organic/candy/randomised +/datum/supply_pack/organic/combomeal2 + name = "Burger Combo #2" + desc = "We value our customers at the Greasy Griddle, so much so that we're willing to deliver -just for you.- This combo meal contains two burgers, a soda, fries, a toy, and some chicken nuggets." + cost = 3200 + contains = list(/obj/item/reagent_containers/food/snacks/burger/bigbite, + /obj/item/reagent_containers/food/snacks/burger/cheese, + /obj/item/reagent_containers/food/snacks/fries, + /obj/item/reagent_containers/food/condiment/pack/ketchup, + /obj/item/reagent_containers/food/condiment/pack/ketchup, + /obj/item/reagent_containers/food/snacks/nugget, + /obj/item/reagent_containers/food/snacks/nugget, + /obj/item/reagent_containers/food/snacks/nugget, + /obj/item/reagent_containers/food/snacks/nugget, + /obj/item/toy/plush/random) + crate_name = "combo meal w/toy" + crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/organic/randomized/candy name = "Candy Crate" desc = "For people that have an insatiable sweet tooth! Has ten candies to be eaten up.." cost = 2500 - var/num_contained = 10 //number of items picked to be contained in a randomised crate + num_contained = 10 contains = list(/obj/item/reagent_containers/food/snacks/candy, /obj/item/reagent_containers/food/snacks/lollipop, /obj/item/reagent_containers/food/snacks/gumball, @@ -47,91 +72,6 @@ /obj/item/storage/fancy/donut_box) crate_name = "candy crate" -/datum/supply_pack/organic/randomized/chef - name = "Excellent Meat Crate" - desc = "The best cuts in the whole galaxy." - cost = 2000 - contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime, - /obj/item/reagent_containers/food/snacks/meat/slab/killertomato, - /obj/item/reagent_containers/food/snacks/meat/slab/bear, - /obj/item/reagent_containers/food/snacks/meat/slab/xeno, - /obj/item/reagent_containers/food/snacks/meat/slab/spider, - /obj/item/reagent_containers/food/snacks/meat/rawbacon, - /obj/item/reagent_containers/food/snacks/spiderleg, - /obj/item/reagent_containers/food/snacks/carpmeat, - /obj/item/reagent_containers/food/snacks/meat/slab/human) - crate_name = "food crate" - -/datum/supply_pack/organic/randomized/chef/fill(obj/structure/closet/crate/C) - for(var/i in 1 to 15) - var/item = pick(contains) - new item(C) - -/datum/supply_pack/organic/exoticseeds - name = "Exotic Seeds Crate" - desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!" - cost = 1500 - contains = list(/obj/item/seeds/nettle, - /obj/item/seeds/replicapod, - /obj/item/seeds/replicapod, - /obj/item/seeds/replicapod, - /obj/item/seeds/plump, - /obj/item/seeds/liberty, - /obj/item/seeds/amanita, - /obj/item/seeds/reishi, - /obj/item/seeds/banana, - /obj/item/seeds/bamboo, - /obj/item/seeds/eggplant/eggy, - /obj/item/seeds/random, - /obj/item/seeds/random) - crate_name = "exotic seeds crate" - crate_type = /obj/structure/closet/crate/hydroponics - -/datum/supply_pack/organic/food - name = "Food Crate" - desc = "Get things cooking with this crate full of useful ingredients! Contains a two dozen eggs, three bananas, and two bags of flour and rice, two cartons of milk, soymilk, as well as salt and pepper shakers, an enzyme and sugar bottle, and three slabs of monkeymeat." - cost = 1000 - contains = list(/obj/item/reagent_containers/food/condiment/flour, - /obj/item/reagent_containers/food/condiment/flour, - /obj/item/reagent_containers/food/condiment/rice, - /obj/item/reagent_containers/food/condiment/rice, - /obj/item/reagent_containers/food/condiment/milk, - /obj/item/reagent_containers/food/condiment/milk, - /obj/item/reagent_containers/food/condiment/soymilk, - /obj/item/reagent_containers/food/condiment/saltshaker, - /obj/item/reagent_containers/food/condiment/peppermill, - /obj/item/storage/fancy/egg_box, - /obj/item/storage/fancy/egg_box, - /obj/item/reagent_containers/food/condiment/enzyme, - /obj/item/reagent_containers/food/condiment/sugar, - /obj/item/reagent_containers/food/snacks/meat/slab/monkey, - /obj/item/reagent_containers/food/snacks/meat/slab/monkey, - /obj/item/reagent_containers/food/snacks/meat/slab/monkey, - /obj/item/reagent_containers/food/snacks/grown/banana, - /obj/item/reagent_containers/food/snacks/grown/banana, - /obj/item/reagent_containers/food/snacks/grown/banana) - crate_name = "food crate" - -/datum/supply_pack/organic/randomized/chef/fruits - name = "Fruit Crate" - desc = "Rich in vitamins, may contain oranges." - cost = 1500 - contains = list(/obj/item/reagent_containers/food/snacks/grown/citrus/lime, - /obj/item/reagent_containers/food/snacks/grown/citrus/orange, - /obj/item/reagent_containers/food/snacks/grown/banana, - /obj/item/reagent_containers/food/snacks/grown/watermelon, - /obj/item/reagent_containers/food/snacks/grown/apple, - /obj/item/reagent_containers/food/snacks/grown/berries, - /obj/item/reagent_containers/food/snacks/grown/citrus/lemon, - /obj/item/reagent_containers/food/snacks/grown/pineapple, - /obj/item/reagent_containers/food/snacks/grown/cherries, - /obj/item/reagent_containers/food/snacks/grown/grapes, - /obj/item/reagent_containers/food/snacks/grown/grapes/green, - /obj/item/reagent_containers/food/snacks/grown/eggplant, - /obj/item/reagent_containers/food/snacks/grown/peach, - /obj/item/reagent_containers/food/snacks/grown/strawberry) - crate_name = "food crate" - /datum/supply_pack/organic/fiestatortilla name = "Fiesta Crate" desc = "Spice up the kitchen with this fiesta themed food order! Contains 8 tortilla based food items, as well as a sombrero, moustache, and cloak!" @@ -151,79 +91,6 @@ /obj/item/reagent_containers/glass/bottle/capsaicin) crate_name = "fiesta crate" -/datum/supply_pack/organic/grill - name = "Grilling Starter Kit" - desc = "Hey dad I'm Hungry. Hi Hungry I'm THE NEW GRILLING STARTER KIT ONLY 5000 BUX GET NOW! Contains a cooking grill and five fuel coal sheets." - cost = 3000 - crate_type = /obj/structure/closet/crate - contains = list(/obj/item/stack/sheet/mineral/coal/five, - /obj/machinery/grill/unwrenched) - crate_name = "grilling starter kit crate" - -/datum/supply_pack/organic/grillfuel - name = "Grilling Fuel Kit" - desc = "Contains coal and coal accessories. (Note: only ten coal sheets.)" - cost = 1000 - crate_type = /obj/structure/closet/crate - contains = list(/obj/item/stack/sheet/mineral/coal/ten) - crate_name = "grilling fuel kit crate" - -/datum/supply_pack/organic/cream_piee - name = "High-yield Clown-grade Cream Pie Crate" - desc = "Designed by Aussec's Advanced Warfare Research Division, these high-yield, Clown-grade cream pies are powered by a synergy of performance and efficiency. Guaranteed to provide maximum results." - cost = 6000 - contains = list(/obj/item/storage/backpack/duffelbag/clown/cream_pie) - crate_name = "party equipment crate" - contraband = TRUE - access = ACCESS_THEATRE - crate_type = /obj/structure/closet/crate/secure - -/datum/supply_pack/organic/fakemeat - name = "Meat Crate" - desc = "Run outta meat already? Keep the lizards content with this freezer filled with cruelty-free chemically compounded meat! Contains 12 slabs of meat product, and 4 slabs of *carp*." - cost = 1200 // Buying 3 food crates nets you 9 meat for 900 points, plus like, 6 bags of rice, flour, and egg boxes. This is 12 for 500, but you -only- get meat and carp. - contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, - /obj/item/reagent_containers/food/snacks/carpmeat/imitation, - /obj/item/reagent_containers/food/snacks/carpmeat/imitation, - /obj/item/reagent_containers/food/snacks/carpmeat/imitation, - /obj/item/reagent_containers/food/snacks/carpmeat/imitation) - crate_name = "meaty crate" - crate_type = /obj/structure/closet/crate/freezer - -/datum/supply_pack/organic/monkeydripmeat - name = "*Meat* Crate" - desc = "Need some meat? With this do-it-yourself kit you'll be swimming in it! Contains a monkey cube, an IV drip, and some cryoxadone!" - cost = 2150 - contraband = TRUE - contains = list(/obj/item/reagent_containers/food/snacks/monkeycube, - /obj/item/restraints/handcuffs/cable, - /obj/machinery/iv_drip, - /obj/item/reagent_containers/glass/beaker/cryoxadone, - /obj/item/reagent_containers/glass/beaker/cryoxadone) - crate_name = "monkey meat crate" - -/datum/supply_pack/organic/mixedboxes - name = "Mixed Ingredient Boxes" - desc = "Get overwhelmed with inspiration by ordering these boxes of surprise ingredients! Get four boxes filled with an assortment of products!" - cost = 2300 - contains = list(/obj/item/storage/box/ingredients/wildcard, - /obj/item/storage/box/ingredients/wildcard, - /obj/item/storage/box/ingredients/wildcard, - /obj/item/storage/box/ingredients/wildcard) - crate_name = "wildcard food crate" - crate_type = /obj/structure/closet/crate/freezer - /datum/supply_pack/organic/pizza name = "Pizza Crate" desc = "Best prices on this side of the galaxy. All deliveries are guaranteed to be 99% anomaly-free!" @@ -258,9 +125,129 @@ considered \[REDACTED\] and returned at your leisure. Note that objects the anomaly produces are specifically attuned exactly to the individual opening the anomaly; regardless \ of species, the individual will find the object edible and it will taste great according to their personal definitions, which vary significantly based on person and species.") -/datum/supply_pack/organic/randomized/chef/vegetables - name = "Vegetables Crate" - desc = "Grown in vats." +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Raw Ingredients ///////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/organic/food + name = "Food Crate" + desc = "Get things cooking with this crate full of useful ingredients! Contains a two dozen eggs, three bananas, and two bags of flour and rice, two cartons of milk, soymilk, as well as salt and pepper shakers, an enzyme and sugar bottle, and three slabs of monkeymeat." + cost = 1000 + contains = list(/obj/item/reagent_containers/food/condiment/flour, + /obj/item/reagent_containers/food/condiment/flour, + /obj/item/reagent_containers/food/condiment/rice, + /obj/item/reagent_containers/food/condiment/rice, + /obj/item/reagent_containers/food/condiment/milk, + /obj/item/reagent_containers/food/condiment/milk, + /obj/item/reagent_containers/food/condiment/soymilk, + /obj/item/reagent_containers/food/condiment/saltshaker, + /obj/item/reagent_containers/food/condiment/peppermill, + /obj/item/storage/fancy/egg_box, + /obj/item/storage/fancy/egg_box, + /obj/item/reagent_containers/food/condiment/enzyme, + /obj/item/reagent_containers/food/condiment/sugar, + /obj/item/reagent_containers/food/snacks/meat/slab/monkey, + /obj/item/reagent_containers/food/snacks/meat/slab/monkey, + /obj/item/reagent_containers/food/snacks/meat/slab/monkey, + /obj/item/reagent_containers/food/snacks/grown/banana, + /obj/item/reagent_containers/food/snacks/grown/banana, + /obj/item/reagent_containers/food/snacks/grown/banana) + crate_name = "food crate" + +/datum/supply_pack/organic/randomized/fruits + name = "Fruit Crate" + desc = "Rich in vitamins and possibly sugar. Contains 15 assorted fruits." + cost = 1500 + contains = list(/obj/item/reagent_containers/food/snacks/grown/citrus/lime, + /obj/item/reagent_containers/food/snacks/grown/citrus/orange, + /obj/item/reagent_containers/food/snacks/grown/banana, + /obj/item/reagent_containers/food/snacks/grown/watermelon, + /obj/item/reagent_containers/food/snacks/grown/apple, + /obj/item/reagent_containers/food/snacks/grown/berries, + /obj/item/reagent_containers/food/snacks/grown/citrus/lemon, + /obj/item/reagent_containers/food/snacks/grown/pineapple, + /obj/item/reagent_containers/food/snacks/grown/cherries, + /obj/item/reagent_containers/food/snacks/grown/grapes, + /obj/item/reagent_containers/food/snacks/grown/grapes/green, + /obj/item/reagent_containers/food/snacks/grown/eggplant, + /obj/item/reagent_containers/food/snacks/grown/peach, + /obj/item/reagent_containers/food/snacks/grown/strawberry) + crate_name = "fruit crate" + +/datum/supply_pack/organic/cream_piee + name = "High-yield Clown-grade Cream Pie Crate" + desc = "Designed by Aussec's Advanced Warfare Research Division, these high-yield, Clown-grade cream pies are powered by a synergy of performance and efficiency. Guaranteed to provide maximum results." + cost = 6000 + contains = list(/obj/item/storage/backpack/duffelbag/clown/cream_pie) + crate_name = "party equipment crate" + contraband = TRUE + access = ACCESS_THEATRE + crate_type = /obj/structure/closet/crate/secure + +/datum/supply_pack/organic/randomized + name = "Meat Crate (Exotic)" + desc = "The best cuts in the whole galaxy. Contains 15 assorted exotic meats." + cost = 2000 + contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime, + /obj/item/reagent_containers/food/snacks/meat/slab/killertomato, + /obj/item/reagent_containers/food/snacks/meat/slab/bear, + /obj/item/reagent_containers/food/snacks/meat/slab/xeno, + /obj/item/reagent_containers/food/snacks/meat/slab/spider, + /obj/item/reagent_containers/food/snacks/meat/rawbacon, + /obj/item/reagent_containers/food/snacks/spiderleg, + /obj/item/reagent_containers/food/snacks/carpmeat, + /obj/item/reagent_containers/food/snacks/meat/slab/human) + crate_name = "exotic meat crate" + +/datum/supply_pack/organic/monkeydripmeat + name = "Meat Crate (Fresh)" + desc = "Need some meat? With this do-it-yourself kit you'll be swimming in it! Contains a monkey cube, an IV drip, and some cryoxadone!" + cost = 2150 + contraband = TRUE + contains = list(/obj/item/reagent_containers/food/snacks/monkeycube, + /obj/item/restraints/handcuffs/cable, + /obj/machinery/iv_drip, + /obj/item/reagent_containers/glass/beaker/cryoxadone, + /obj/item/reagent_containers/glass/beaker/cryoxadone) + crate_name = "monkey meat crate" + +/datum/supply_pack/organic/fakemeat + name = "Meat Crate 'Synthetic'" + desc = "Run outta meat already? Keep the lizards content with this freezer filled with cruelty-free chemically compounded meat! Contains 12 slabs of meat product, and 4 slabs of *carp*." + cost = 1200 // Buying 3 food crates nets you 9 meat for 900 points, plus like, 6 bags of rice, flour, and egg boxes. This is 12 for 500, but you -only- get meat and carp. + contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct, + /obj/item/reagent_containers/food/snacks/carpmeat/imitation, + /obj/item/reagent_containers/food/snacks/carpmeat/imitation, + /obj/item/reagent_containers/food/snacks/carpmeat/imitation, + /obj/item/reagent_containers/food/snacks/carpmeat/imitation) + crate_name = "meaty crate" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/mixedboxes + name = "Mixed Ingredient Boxes" + desc = "Get overwhelmed with inspiration by ordering these boxes of surprise ingredients! Get four boxes filled with an assortment of products!" + cost = 2300 + contains = list(/obj/item/storage/box/ingredients/wildcard, + /obj/item/storage/box/ingredients/wildcard, + /obj/item/storage/box/ingredients/wildcard, + /obj/item/storage/box/ingredients/wildcard) + crate_name = "wildcard food crate" + crate_type = /obj/structure/closet/crate/freezer + +/datum/supply_pack/organic/randomized/vegetables + name = "Vegetable Crate" + desc = "Grown in vats. Contains 15 assorted vegetables." cost = 1300 contains = list(/obj/item/reagent_containers/food/snacks/grown/chili, /obj/item/reagent_containers/food/snacks/grown/corn, @@ -270,7 +257,7 @@ /obj/item/reagent_containers/food/snacks/grown/mushroom/chanterelle, /obj/item/reagent_containers/food/snacks/grown/onion, /obj/item/reagent_containers/food/snacks/grown/pumpkin) - crate_name = "food crate" + crate_name = "veggie crate" ////////////////////////////////////////////////////////////////////////////// //////////////////////////// Hydroponics ///////////////////////////////////// @@ -302,42 +289,6 @@ crate_name = "beekeeping starter crate" crate_type = /obj/structure/closet/crate/hydroponics -/datum/supply_pack/organic/exoticseeds - name = "Exotic Seeds Crate" - desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!" - cost = 1500 - contains = list(/obj/item/seeds/nettle, - /obj/item/seeds/replicapod, - /obj/item/seeds/replicapod, - /obj/item/seeds/replicapod, - /obj/item/seeds/plump, - /obj/item/seeds/liberty, - /obj/item/seeds/amanita, - /obj/item/seeds/reishi, - /obj/item/seeds/banana, - /obj/item/seeds/eggplant/eggy, - /obj/item/seeds/random, - /obj/item/seeds/random) - crate_name = "exotic seeds crate" - crate_type = /obj/structure/closet/crate/hydroponics - -/* Maintenance Garden Crate basically does this and more. -/datum/supply_pack/organic/hydroponics - name = "Hydroponics Crate" - desc = "Supplies for growing a great garden! Contains two bottles of ammonia, two Plant-B-Gone spray bottles, a hatchet, cultivator, plant analyzer, as well as a pair of leather gloves and a botanist's apron." - cost = 1750 - contains = list(/obj/item/reagent_containers/spray/plantbgone, - /obj/item/reagent_containers/spray/plantbgone, - /obj/item/reagent_containers/glass/bottle/ammonia, - /obj/item/reagent_containers/glass/bottle/ammonia, - /obj/item/hatchet, - /obj/item/cultivator, - /obj/item/plant_analyzer, - /obj/item/clothing/gloves/botanic_leather, - /obj/item/clothing/suit/apron) - crate_name = "hydroponics crate" - crate_type = /obj/structure/closet/crate/hydroponics -*/ /datum/supply_pack/organic/hydroponics/hydrotank name = "Hydroponics Backpack Crate" desc = "Bring on the flood with this high-capacity backpack crate. Contains 500 units of life-giving H2O. Requires hydroponics access to open." @@ -390,10 +341,30 @@ /obj/item/seeds/sunflower, /obj/item/seeds/chanter, /obj/item/seeds/potato, - /obj/item/seeds/sugarcane) + /obj/item/seeds/sugarcane, + /obj/item/seeds/ambrosia) crate_name = "seeds crate" crate_type = /obj/structure/closet/crate/hydroponics +/datum/supply_pack/organic/exoticseeds + name = "Seeds Crate (Exotic)" + desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!" + cost = 1500 + contains = list(/obj/item/seeds/nettle, + /obj/item/seeds/replicapod, + /obj/item/seeds/replicapod, + /obj/item/seeds/replicapod, + /obj/item/seeds/plump, + /obj/item/seeds/liberty, + /obj/item/seeds/amanita, + /obj/item/seeds/reishi, + /obj/item/seeds/banana, + /obj/item/seeds/eggplant/eggy, + /obj/item/seeds/random, + /obj/item/seeds/random) + crate_name = "exotic seeds crate" + crate_type = /obj/structure/closet/crate/hydroponics + ////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// Misc ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -414,6 +385,29 @@ crate_name = "sporting crate" crate_type = /obj/structure/closet/crate/secure // Would have liked a wooden crate but access >:( +/datum/supply_pack/organic/party + name = "Party Equipment" + desc = "Celebrate both life and death on the station with Nanotrasen's Party Essentials(tm)! Contains seven colored glowsticks, four beers, two ales, a drinking shaker, and a bottle of patron & goldschlager!" + cost = 2000 + contains = list(/obj/item/storage/box/drinkingglasses, + /obj/item/reagent_containers/food/drinks/shaker, + /obj/item/reagent_containers/food/drinks/bottle/patron, + /obj/item/reagent_containers/food/drinks/bottle/goldschlager, + /obj/item/reagent_containers/food/drinks/ale, + /obj/item/reagent_containers/food/drinks/ale, + /obj/item/reagent_containers/food/drinks/beer, + /obj/item/reagent_containers/food/drinks/beer, + /obj/item/reagent_containers/food/drinks/beer, + /obj/item/reagent_containers/food/drinks/beer, + /obj/item/flashlight/glowstick, + /obj/item/flashlight/glowstick/red, + /obj/item/flashlight/glowstick/blue, + /obj/item/flashlight/glowstick/cyan, + /obj/item/flashlight/glowstick/orange, + /obj/item/flashlight/glowstick/yellow, + /obj/item/flashlight/glowstick/pink) + crate_name = "party equipment crate" + /datum/supply_pack/organic/vday name = "Surplus Valentine Crate" desc = "Turns out we got warehouses of this love-y dove-y crap. We're sending out small bargain buddle of Valentine gear. This crate has two boxes of chocolate, three poppy flowers, five candy hearts, and three cards." diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm index f14bc37371..79675cf3ec 100644 --- a/code/modules/cargo/packs/science.dm +++ b/code/modules/cargo/packs/science.dm @@ -24,13 +24,12 @@ name = "Advanced Alien Alloy Crate Crate" desc = "Hello brothers from the stars!!! Our fellow brethren have made contact at long last and gave us gifts man! They really did build the prymi- Connection Error- Bro we’ll send you a sheet of advanced alien alloy." cost = 15000 - contraband = TRUE DropPodOnly = TRUE contains = list(/obj/item/stack/sheet/mineral/abductor) crate_name = "alien bro alloy crate" /datum/supply_pack/science/beakers - name = "Chemistry Beackers Crate" + name = "Chemistry Beakers Crate" desc = "Glassware for any chemistry lab! Contains four small beakers, three large, two plastic, and one metamaterial. As well as three droppers and two pairs of latex gloves." cost = 1500 contains = list(/obj/item/reagent_containers/glass/beaker, @@ -82,6 +81,16 @@ /obj/item/integrated_electronics/wirer) crate_name = "circuitry starter pack crate" +/datum/supply_pack/science/glasswork + name = "Glass Blower Kit Crate" + desc = "Learn and make glassworks of usefull things for a profit! Contains glassworking tools and blowing rods. Glass not included." + cost = 1000 + contains = list(/obj/item/glasswork/glasskit, + /obj/item/glasswork/glasskit, + /obj/item/glasswork/blowing_rod, + /obj/item/glasswork/blowing_rod) + crate_name = "glassblower gear crate" + /datum/supply_pack/science/monkey name = "Monkey Cube Crate" desc = "Stop monkeying around! Contains seven monkey cubes. Just add water!" diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm index 69967d65d1..3b602d54d2 100644 --- a/code/modules/cargo/packs/security.dm +++ b/code/modules/cargo/packs/security.dm @@ -163,13 +163,6 @@ /obj/item/storage/box/handcuffs) crate_name = "security supply crate" -/datum/supply_pack/security/vending/security - name = "SecTech Supply Crate" - desc = "Officer Paul bought all the donuts? Then refill the security vendor with ths crate." - cost = 1500 - contains = list(/obj/machinery/vending/security) - crate_name = "SecTech supply crate" - /datum/supply_pack/security/firingpins name = "Standard Firing Pins Crate" desc = "Upgrade your arsenal with 10 standard firing pins. Requires Security access to open." diff --git a/code/modules/cargo/packs/service.dm b/code/modules/cargo/packs/service.dm index 01524b1910..942720dd6b 100644 --- a/code/modules/cargo/packs/service.dm +++ b/code/modules/cargo/packs/service.dm @@ -10,9 +10,24 @@ group = "Service" ////////////////////////////////////////////////////////////////////////////// -/////////////////////////////// Cargo //////////////////////////////////////// +//////////////////////////////// Cargo /////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// +/datum/supply_pack/service/wrapping_paper + name = "Cargo Packaging Crate" + desc = "Want to mail your loved ones gift-wrapped chocolates, stuffed animals, or the Clown's severed head? You can do all that, with this crate full of festive (and normal) wrapping paper. Also contains a hand labeler and a destination tagger for easy shipping!" + cost = 1000 + contains = list(/obj/item/stack/wrapping_paper, + /obj/item/stack/wrapping_paper, + /obj/item/stack/wrapping_paper, + /obj/item/stack/packageWrap, + /obj/item/stack/packageWrap, + /obj/item/stack/packageWrap, + /obj/item/destTagger, + /obj/item/hand_labeler) + crate_type = /obj/structure/closet/crate/wooden + crate_name = "wrapping paper crate" + /datum/supply_pack/service/cargo_supples name = "Cargo Supplies Crate" desc = "Sold everything that wasn't bolted down? You can get right back to work with this crate containing stamps, an export scanner, destination tagger, hand labeler and some package wrapping. Now with extra toner cartidges!" @@ -101,6 +116,23 @@ crate_name = "ice cream vat crate" crate_type = /obj/structure/closet/crate +/datum/supply_pack/service/grill + name = "Grilling Starter Kit" + desc = "Hey dad I'm Hungry. Hi Hungry I'm THE NEW GRILLING STARTER KIT ONLY 5000 BUX GET NOW! Contains a cooking grill and five fuel coal sheets." + cost = 3000 + contains = list(/obj/item/stack/sheet/mineral/coal/five, + /obj/machinery/grill/unwrenched) + crate_name = "grilling starter kit crate" + crate_type = /obj/structure/closet/crate + +/datum/supply_pack/service/grillfuel + name = "Grilling Fuel Kit" + desc = "Contains coal and coal accessories. (Note: only ten coal sheets.)" + cost = 1000 + contains = list(/obj/item/stack/sheet/mineral/coal/ten) + crate_name = "grilling fuel kit crate" + crate_type = /obj/structure/closet/crate + /datum/supply_pack/service/cutlery name = "Kitchen Cutlery Deluxe Set" desc = "Need to slice and dice away those \"Tomatoes\"? Well we got what you need! From a nice set of knifes, forks, plates, glasses, and a whetstone for when you got some grizzle that is a bit harder to slice then normal." @@ -115,7 +147,7 @@ /obj/item/kitchen/knife, /obj/item/kitchen/knife/butcher, /obj/item/kitchen/knife/butcher, - /obj/item/kitchen/rollingpin, + /obj/item/kitchen/rollingpin, /obj/item/trash/plate, /obj/item/trash/plate, /obj/item/trash/plate, @@ -240,45 +272,3 @@ crate_name = "janitorial cart crate" crate_type = /obj/structure/closet/crate/large -////////////////////////////////////////////////////////////////////////////// -//////////////////////////// Vendor Refills ////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -/datum/supply_pack/service/vending/bartending - name = "Bartending Supply Crate" - desc = "Bring on the booze with vending machine refills, as well as a free book containing the well-kept secrets to the bartending trade!" - cost = 2000 - contains = list(/obj/item/vending_refill/boozeomat, - /obj/item/vending_refill/coffee, - /obj/item/book/granter/action/drink_fling) - crate_name = "bartending supply crate" - -/datum/supply_pack/service/vending/cigarette - name = "Cigarette Supply Crate" - desc = "Don't believe the reports - smoke today! Contains a cigarette vending machine refill." - cost = 1500 - contains = list(/obj/item/vending_refill/cigarette) - crate_name = "cigarette supply crate" - crate_type = /obj/structure/closet/crate - -/datum/supply_pack/service/vending/games - name = "Games Supply Crate" - desc = "Get your game on with this game vending machine refill." - cost = 1000 - contains = list(/obj/item/vending_refill/games) - crate_name = "games supply crate" - crate_type = /obj/structure/closet/crate - -/datum/supply_pack/service/vending/snack - name = "Snack Supply Crate" - desc = "One vending machine refill of cavity-bringin' goodness! The number one dentist recommended order!" - cost = 1500 - contains = list(/obj/item/vending_refill/snack) - crate_name = "snacks supply crate" - -/datum/supply_pack/service/vending/cola - name = "Softdrinks Supply Crate" - desc = "Got whacked by a toolbox, but you still have those pesky teeth? Get rid of those pearly whites with this soda machine refill, today!" - cost = 1500 - contains = list(/obj/item/vending_refill/cola) - crate_name = "soft drinks supply crate" diff --git a/code/modules/cargo/packs/vending.dm b/code/modules/cargo/packs/vending.dm new file mode 100644 index 0000000000..f9982d17b6 --- /dev/null +++ b/code/modules/cargo/packs/vending.dm @@ -0,0 +1,148 @@ + +//Reminders- +// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal +// cost = 700- Minimum cost, or infinite points are possible. +////////////////////////////////////////////////////////////////////////////// +/////////////////////////////// Vending ////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/vending + group = "Vending" + +////////////////////////////////////////////////////////////////////////////// +///////////////////////// Service, Medical, Sec ////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/vending/bartending + name = "Bartending Supply Crate" + desc = "Bring on the booze with vending machine refills, as well as a free book containing the well-kept secrets to the bartending trade!" + cost = 2000 + contains = list(/obj/item/vending_refill/boozeomat, + /obj/item/vending_refill/coffee, + /obj/item/book/granter/action/drink_fling) + crate_name = "bartending supply crate" + +/datum/supply_pack/vending/cigarette + name = "Cigarette Supply Crate" + desc = "Don't believe the reports - smoke today! Contains a cigarette vending machine refill." + cost = 1500 + contains = list(/obj/item/vending_refill/cigarette) + crate_name = "cigarette supply crate" + crate_type = /obj/structure/closet/crate + +/datum/supply_pack/vending/games + name = "Games Supply Crate" + desc = "Get your game on with this game vending machine refill." + cost = 1000 + contains = list(/obj/item/vending_refill/games) + crate_name = "games supply crate" + crate_type = /obj/structure/closet/crate + +/datum/supply_pack/vending/kinkmate + name = "Kinkmate Supply and Construction Kit" + cost = 2000 + contraband = TRUE + contains = list(/obj/item/vending_refill/kink, /obj/item/circuitboard/machine/kinkmate) + crate_name = "Kinkmate construction kit" + +/datum/supply_pack/vending/medical + name = "Medical Vending Crate" + desc = "Contains refills for medical vending machines." + cost = 2000 + contains = list(/obj/item/vending_refill/medical, + /obj/item/vending_refill/wallmed) + crate_name = "medical vending crate" + crate_type = /obj/structure/closet/crate/medical + +/datum/supply_pack/vending/security + name = "SecTech Supply Crate" + desc = "Officer Paul bought all the donuts? Then refill the security vendor with ths crate. Requires Security Access to open." + cost = 1500 + access = ACCESS_SECURITY + contains = list(/obj/machinery/vending/security) + crate_name = "SecTech supply crate" + crate_type = /obj/structure/closet/crate/secure/gear + +/datum/supply_pack/vending/snack + name = "Snack Supply Crate" + desc = "One vending machine refill of cavity-bringin' goodness! The number one dentist recommended order!" + cost = 1500 + contains = list(/obj/item/vending_refill/snack) + crate_name = "snacks supply crate" + +/datum/supply_pack/vending/cola + name = "Softdrinks Supply Crate" + desc = "Got whacked by a toolbox, but you still have those pesky teeth? Get rid of those pearly whites with this soda machine refill, today!" + cost = 1500 + contains = list(/obj/item/vending_refill/cola) + crate_name = "soft drinks supply crate" + +////////////////////////////////////////////////////////////////////////////// +//////////////////////////// Wardrobe Vendors //////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +/datum/supply_pack/vending/wardrobes/autodrobe + name = "Autodrobe Supply Crate" + desc = "Autodrobe missing your favorite dress? Solve that issue today with this autodrobe refill." + cost = 1500 + contains = list(/obj/item/vending_refill/autodrobe) + crate_name = "autodrobe supply crate" + +/datum/supply_pack/vending/wardrobes/cargo + name = "Cargo Wardrobe Supply Crate" + desc = "This crate contains a refill for the CargoDrobe." + cost = 750 + contains = list(/obj/item/vending_refill/wardrobe/cargo_wardrobe) + crate_name = "cargo department supply crate" + +/datum/supply_pack/vending/wardrobes/engineering + name = "Engineering Wardrobe Supply Crate" + desc = "This crate contains refills for the EngiDrobe and AtmosDrobe." + cost = 1500 + contains = list(/obj/item/vending_refill/wardrobe/engi_wardrobe, + /obj/item/vending_refill/wardrobe/atmos_wardrobe) + crate_name = "engineering department wardrobe supply crate" + +/datum/supply_pack/vending/wardrobes/general + name = "General Wardrobes Supply Crate" + desc = "This crate contains refills for the CuraDrobe, BarDrobe, ChefDrobe, JaniDrobe, ChapDrobe." + cost = 3750 + contains = list(/obj/item/vending_refill/wardrobe/curator_wardrobe, + /obj/item/vending_refill/wardrobe/bar_wardrobe, + /obj/item/vending_refill/wardrobe/chef_wardrobe, + /obj/item/vending_refill/wardrobe/jani_wardrobe, + /obj/item/vending_refill/wardrobe/chap_wardrobe) + crate_name = "general wardrobes vendor refills" + +/datum/supply_pack/vending/wardrobes/hydroponics + name = "Hydrobe Supply Crate" + desc = "This crate contains a refill for the Hydrobe." + cost = 750 + contains = list(/obj/item/vending_refill/wardrobe/hydro_wardrobe) + crate_name = "hydrobe supply crate" + +/datum/supply_pack/vending/wardrobes/medical + name = "Medical Wardrobe Supply Crate" + desc = "This crate contains refills for the MediDrobe, ChemDrobe, GeneDrobe, and ViroDrobe." + cost = 3000 + contains = list(/obj/item/vending_refill/wardrobe/medi_wardrobe, + /obj/item/vending_refill/wardrobe/chem_wardrobe, + /obj/item/vending_refill/wardrobe/gene_wardrobe, + /obj/item/vending_refill/wardrobe/viro_wardrobe) + crate_name = "medical department wardrobe supply crate" + +/datum/supply_pack/vending/wardrobes/science + name = "Science Wardrobe Supply Crate" + desc = "This crate contains refills for the SciDrobe and RoboDrobe." + cost = 1500 + contains = list(/obj/item/vending_refill/wardrobe/robo_wardrobe, + /obj/item/vending_refill/wardrobe/science_wardrobe) + crate_name = "science department wardrobe supply crate" + +/datum/supply_pack/vending/wardrobes/security + name = "Security Wardrobe Supply Crate" + desc = "This crate contains refills for the SecDrobe and LawDrobe." + cost = 1500 + contains = list(/obj/item/vending_refill/wardrobe/sec_wardrobe, + /obj/item/vending_refill/wardrobe/law_wardrobe) + crate_name = "security department supply crate" diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 08ecefb91f..75daaabb99 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -482,12 +482,20 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(gender == MALE) hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_male_list) facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_male_list) - else + undershirt = sanitize_inlist(undershirt, GLOB.undershirt_m) + underwear = sanitize_inlist(underwear, GLOB.underwear_m) + else if(gender == FEMALE) hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_female_list) facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_female_list) - underwear = sanitize_inlist(underwear, GLOB.underwear_list) + undershirt = sanitize_inlist(undershirt, GLOB.undershirt_f) + underwear = sanitize_inlist(underwear, GLOB.underwear_f) + else + hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_list) + facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_list) + underwear = sanitize_inlist(underwear, GLOB.underwear_list) + undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list) + undie_color = sanitize_hexcolor(undie_color, 3, FALSE, initial(undie_color)) - undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list) shirt_color = sanitize_hexcolor(shirt_color, 3, FALSE, initial(shirt_color)) socks = sanitize_inlist(socks, GLOB.socks_list) socks_color = sanitize_hexcolor(socks_color, 3, FALSE, initial(socks_color)) diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm index 1532f50808..bdbac1165e 100644 --- a/code/modules/clothing/outfits/ert.dm +++ b/code/modules/clothing/outfits/ert.dm @@ -18,8 +18,9 @@ R.freqlock = TRUE var/obj/item/card/id/W = H.wear_id - W.registered_name = H.real_name - W.update_label(W.registered_name, W.assignment) + if(W) + W.registered_name = H.real_name + W.update_label(W.registered_name, W.assignment) /datum/outfit/ert/commander name = "ERT Commander" diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm index b8287c7f4c..7d56fbe6dd 100644 --- a/code/modules/clothing/suits/cloaks.dm +++ b/code/modules/clothing/suits/cloaks.dm @@ -81,7 +81,7 @@ heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT - resistance_flags = FIRE_PROOF | ACID_PROOF + resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE /obj/item/clothing/head/hooded/cloakhood/drake name = "drake helm" @@ -90,4 +90,4 @@ armor = list("melee" = 70, "bullet" = 30, "laser" = 50, "energy" = 40, "bomb" = 70, "bio" = 60, "rad" = 50, "fire" = 100, "acid" = 100) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT - resistance_flags = FIRE_PROOF | ACID_PROOF + resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index a2081851e1..a4b8c920d3 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -945,4 +945,59 @@ icon_state = "christmasfemaleg" item_state = "christmasfemaleg" body_parts_covered = CHEST|GROIN - can_adjust = FALSE \ No newline at end of file + can_adjust = FALSE + +// Lunar Clothes +/obj/item/clothing/under/lunar/qipao + name = "Black Qipao" + desc = "A Qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is black." + icon_state = "qipao" + item_state = "qipao" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutantrace_variation = NONE + +/obj/item/clothing/under/lunar/qipao/white + name = "White Qipao" + desc = "A Qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is white." + icon_state = "qipao_white" + item_state = "qipao_white" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutantrace_variation = NONE + +/obj/item/clothing/under/lunar/qipao/red + name = "Red Qipao" + desc = "A Qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is red." + icon_state = "qipao_red" + item_state = "qipao_red" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutantrace_variation = NONE + +/obj/item/clothing/under/lunar/cheongsam + name = "Black Cheongsam" + desc = "A Cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is black." + icon_state = "cheong" + item_state = "cheong" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutantrace_variation = NONE + +/obj/item/clothing/under/lunar/cheongsam/white + name = "White Cheongsam" + desc = "A Cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is white." + icon_state = "cheongw" + item_state = "cheongw" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutantrace_variation = NONE + +/obj/item/clothing/under/lunar/cheongsam/red + name = "Red Cheongsam" + desc = "A Cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is red.." + icon_state = "cheongr" + item_state = "cheongr" + body_parts_covered = CHEST|GROIN + can_adjust = FALSE + mutantrace_variation = NONE \ No newline at end of file diff --git a/code/modules/crafting/glassware.dm b/code/modules/crafting/glassware.dm new file mode 100644 index 0000000000..22d7e01f8a --- /dev/null +++ b/code/modules/crafting/glassware.dm @@ -0,0 +1,299 @@ +//This file is for glass working types of things! + +/obj/item/glasswork + name = "This is a bug report it!" + desc = "Failer to code. Contact your local bug remover..." + icon = 'icons/obj/glassworks.dmi' + w_class = WEIGHT_CLASS_SMALL + force = 1 + throw_speed = 1 + throw_range = 3 + tool_behaviour = null + +/obj/item/glasswork/glasskit + name = "Glass working tools" + desc = "A lovely belt of most the tools you will need to shape, mold, and refine glass into more advanced shapes." + icon_state = "glass_tools" + tool_behaviour = TOOL_GLASS_CUT + +/obj/item/glasswork/blowing_rod + name = "Glass working blow rod" + desc = "A hollow metal stick made for glass blowing." + icon_state = "blowing_rods_unused" + tool_behaviour = TOOL_BLOW + +/obj/item/glasswork/glass_base + name = "Glass fodder sheet" + desc = "A sheet of glass set aside for glass working" + icon_state = "glass_base" + var/next_step = null + var/rod = /obj/item/glasswork/blowing_rod + +/obj/item/lens + name = "Optical lens" + desc = "Good for selling or crafting, by itself its useless" + icon = 'icons/obj/chemical.dmi' + icon_state = "glass_optics" + +//////////////////////Chem Disk///////////////////// +//Two Steps // +//Sells for 300 cr, takes 10 glass shets // +//Usefull for chem spliting // +//////////////////////////////////////////////////// + +/obj/item/glasswork/glass_base/dish + name = "Glass fodder sheet" + desc = "A set of glass sheets set aside for glass working, this one is ideal for a small glass dish. Needs to be cut with some tools." + next_step = /obj/item/glasswork/glass_base/dish_part1 + +/obj/item/glasswork/glass_base/dish/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/dish_part1 + name = "Half chem dish sheet" + desc = "A sheet of glass cut in half, looks like it still needs some more cutting down" + icon_state = "glass_base_half" + next_step = /obj/item/reagent_containers/glass/beaker/glass_dish + +/obj/item/glasswork/glass_base/dish_part1/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + new next_step(user.loc, 1) + qdel(src) + +//////////////////////Lens////////////////////////// +//Six Steps // +//Sells for 1800 cr, takes 15 glass shets // +//Usefull for selling and later crafting // +//////////////////////////////////////////////////// + +/obj/item/glasswork/glass_base/glass_lens + name = "Glass fodder sheet" + desc = "A set of glass sheets set aside for glass working, this one is ideal for a small glass lens. Needs to be cut with some tools." + next_step = /obj/item/glasswork/glass_base/glass_lens_part1 + +/obj/item/glasswork/glass_base/glass_lens/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/glass_lens_part1 + name = "Glass fodder sheet" + desc = "Cut glass ready to be heated. Needs to be heated with some tools." + icon_state = "glass_base_half" + next_step = /obj/item/glasswork/glass_base/glass_lens_part2 + +/obj/item/glasswork/glass_base/glass_lens_part1/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_WELDER) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/glass_lens_part2 + name = "Glass fodder sheet" + desc = "Cut glass that has been heated. Needs to be heated more with some tools." + icon_state = "glass_base_heat" + next_step = /obj/item/glasswork/glass_base/glass_lens_part3 + +/obj/item/glasswork/glass_base/glass_lens_part2/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_WELDER) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/glass_lens_part3 + name = "Glass fodder sheet" + desc = "Cut glass that has been heated into a blob of hot glass. Needs to be placed onto a blow tube." + icon_state = "glass_base_molding" + next_step = /obj/item/glasswork/glass_base/glass_lens_part4 + +/obj/item/glasswork/glass_base/glass_lens_part3/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_BLOW) + new next_step(user.loc, 1) + qdel(src) + qdel(I) + +/obj/item/glasswork/glass_base/glass_lens_part4 + name = "Glass fodder sheet" + desc = "Cut glass that has been heated into a blob of hot glass. Needs to be cut off onto a blow tube." + icon_state = "blowing_rods_inuse" + next_step = /obj/item/glasswork/glass_base/glass_lens_part5 + +/obj/item/glasswork/glass_base/glass_lens_part4/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/glass_lens_part5 + name = "Unpolished glass lens" + desc = "A small unpolished glass lens. Could be polished with some cloth." + icon = 'icons/obj/chemical.dmi' + icon_state = "glass_optics" + next_step = /obj/item/glasswork/glass_base/glass_lens_part6 + +/obj/item/glasswork/glass_base/glass_lens_part5/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/stack/sheet/cloth)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/glass_lens_part6 + name = "Unrefined glass lens" + desc = "A small polished glass lens. Just needs to be refined with some sandstone." + icon = 'icons/obj/chemical.dmi' + icon_state = "glass_optics" + next_step = /obj/item/lens + +/obj/item/glasswork/glass_base/glass_lens_part6/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/stack/sheet/mineral/sandstone)) + new next_step(user.loc, 1) + qdel(src) + +//////////////////////Spouty Flask////////////////// +//Four Steps // +//Sells for 1200 cr, takes 20 glass shets // +//Usefull for selling and chemical things // +//////////////////////////////////////////////////// + +/obj/item/glasswork/glass_base/spouty + name = "Glass fodder sheet" + desc = "A set of glass sheets set aside for glass working, this one is ideal for a spout beaker. Needs to be cut with some tools." + next_step = /obj/item/glasswork/glass_base/spouty_part2 + +/obj/item/glasswork/glass_base/spouty/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/spouty_part2 + name = "Glass fodder sheet" + desc = "Cut glass that has been heated. Needs to be heated with some tools." + icon_state = "glass_base_half" + next_step = /obj/item/glasswork/glass_base/spouty_part3 + +/obj/item/glasswork/glass_base/spouty_part2/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_WELDER) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/spouty_part3 + name = "Glass fodder sheet" + desc = "Cut glass that has been heated into a blob of hot glass. Needs to be placed onto a blow tube." + icon_state = "glass_base_molding" + next_step = /obj/item/glasswork/glass_base/spouty_part4 + +/obj/item/glasswork/glass_base/spouty_part3/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_BLOW) + new next_step(user.loc, 1) + qdel(src) + qdel(I) + +/obj/item/glasswork/glass_base/spouty_part4 + name = "Glass fodder sheet" + desc = "Cut glass that has been heated into a blob of hot glass. Needs to be cut off onto a blow tube." + icon_state = "blowing_rods_inuse" + next_step = /obj/item/reagent_containers/glass/beaker/flask/spouty + +/obj/item/glasswork/glass_base/spouty_part4/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) + +//////////////////////Small Bulb Flask////////////// +//Two Steps // +//Sells for 600 cr, takes 5 glass shets // +//Usefull for selling and chemical things // +//////////////////////////////////////////////////// + +/obj/item/glasswork/glass_base/flask_small + name = "Glass fodder sheet" + desc = "A set of glass sheets set aside for glass working, this one is ideal for a small flask. Needs to be heated with some tools." + next_step = /obj/item/glasswork/glass_base/flask_small_part1 + +/obj/item/glasswork/glass_base/flask_small/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_WELDER) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/flask_small_part1 + name = "Metled glass" + desc = "A blob of metled glass, this one is ideal for a small flask. Needs to be blown with some tools." + icon_state = "glass_base_molding" + next_step = /obj/item/glasswork/glass_base/flask_small_part2 + +/obj/item/glasswork/glass_base/flask_small_part1/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_BLOW) + new next_step(user.loc, 1) + qdel(src) + qdel(I) + +/obj/item/glasswork/glass_base/flask_small_part2 + name = "Metled glass" + desc = "A blob of metled glass on the end of a blowing rod. Needs to be cut off with some tools." + icon_state = "blowing_rods_inuse" + next_step = /obj/item/reagent_containers/glass/beaker/flask + +/obj/item/glasswork/glass_base/flask_small_part2/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) + +//////////////////////Large Bulb Flask////////////// +//Two Steps // +//Sells for 1000 cr, takes 15 glass shets // +//Usefull for selling and chemical things // +//////////////////////////////////////////////////// + +/obj/item/glasswork/glass_base/flask_large + name = "Glass fodder sheet" + desc = "A set of glass sheets set aside for glass working, this one is ideal for a large flask. Needs to be heated with some tools." + next_step = /obj/item/glasswork/glass_base/flask_large_part1 + +/obj/item/glasswork/glass_base/flask_large/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_WELDER) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/flask_large_part1 + name = "Metled glass" + desc = "A blob of metled glass, this one is ideal for a large flask. Needs to be blown with some tools." + icon_state = "glass_base_molding" + next_step = /obj/item/glasswork/glass_base/flask_large_part2 + +/obj/item/glasswork/glass_base/flask_large_part1/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_BLOW) + new next_step(user.loc, 1) + qdel(src) + qdel(I) + +/obj/item/glasswork/glass_base/flask_large_part2 + name = "Metled glass" + desc = "A blob of metled glass on the end of a blowing rod. Needs to be cut off with some tools." + icon_state = "blowing_rods_inuse" + next_step = /obj/item/reagent_containers/glass/beaker/flask/large + +/obj/item/glasswork/glass_base/flask_large_part2/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm index a1a82ea5f7..d4eb6ded4c 100644 --- a/code/modules/events/meteor_wave.dm +++ b/code/modules/events/meteor_wave.dm @@ -18,6 +18,7 @@ announceWhen = 1 var/list/wave_type var/wave_name = "normal" + var/direction /datum/round_event/meteor_wave/setup() announceWhen = 1 @@ -26,7 +27,6 @@ startWhen *= 1 - min(GLOB.singularity_counter * SINGULO_BEACON_DISTURBANCE, SINGULO_BEACON_MAX_DISTURBANCE) endWhen = startWhen + 60 - /datum/round_event/meteor_wave/New() ..() if(!wave_type) @@ -38,6 +38,8 @@ "normal" = 50, "threatening" = 40, "catastrophic" = 10)) + if(!direction) + direction = pick(GLOB.cardinals) switch(wave_name) if("normal") wave_type = GLOB.meteors_normal @@ -59,11 +61,21 @@ kill() /datum/round_event/meteor_wave/announce(fake) - priority_announce("Meteors have been detected on collision course with the station. Estimated time until impact: [round(startWhen/60)] minutes.[GLOB.singularity_counter ? " Warning: Anomalous gravity pulse detected, Syndicate technology interference likely." : ""]", "Meteor Alert", "meteors") + var/directionstring + switch(direction) + if(NORTH) + directionstring = " towards the fore" + if(SOUTH) + directionstring = " towards the aft" + if(EAST) + directionstring = " towards starboard" + if(WEST) + directionstring = " towards port" + priority_announce("Meteors have been detected on collision course with the station[directionstring]. Estimated time until impact: [round((startWhen * SSevents.wait) / 10, 0.1)] seconds.[GLOB.singularity_counter ? " Warning: Anomalous gravity pulse detected, Syndicate technology interference likely." : ""]", "Meteor Alert", "meteors") /datum/round_event/meteor_wave/tick() if(ISMULTIPLE(activeFor, 3)) - spawn_meteors(5, wave_type) //meteor list types defined in gamemode/meteor/meteors.dm + spawn_meteors(5, wave_type, direction) //meteor list types defined in gamemode/meteor/meteors.dm /datum/round_event_control/meteor_wave/threatening name = "Meteor Wave: Threatening" diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm index f006f2b358..c585961604 100644 --- a/code/modules/events/shuttle_loan.dm +++ b/code/modules/events/shuttle_loan.dm @@ -133,7 +133,7 @@ shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate/ranged/infiltrator) if(RUSKY_PARTY) - var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/misc/party] + var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/organic/party] pack.generate(pick_n_take(empty_shuttle_turfs)) shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian) diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm index c59a8004ca..56abef8cd6 100644 --- a/code/modules/fields/timestop.dm +++ b/code/modules/fields/timestop.dm @@ -9,7 +9,7 @@ pixel_x = -64 pixel_y = -64 mouse_opacity = MOUSE_OPACITY_TRANSPARENT - var/list/immune = list() // the one who creates the timestop is immune + var/list/immune = list() // the one who creates the timestop is immune, which includes wizards and the dead slime you murdered to make this chronofield var/turf/target var/freezerange = 2 var/duration = 140 @@ -27,10 +27,10 @@ for(var/A in immune_atoms) immune[A] = TRUE for(var/mob/living/L in GLOB.player_list) - if(locate(/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop) in L.mind.spell_list) //People who can stop time are immune to its effects + if(locate(/obj/effect/proc_holder/spell/aoe_turf/timestop) in L.mind.spell_list) //People who can stop time are immune to its effects immune[L] = TRUE for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.parasites) - if(G.summoner && locate(/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop) in G.summoner.mind.spell_list) //It would only make sense that a person's stand would also be immune. + if(G.summoner && locate(/obj/effect/proc_holder/spell/aoe_turf/timestop) in G.summoner.mind.spell_list) //It would only make sense that a person's stand would also be immune. immune[G] = TRUE if(start) timestop() @@ -46,9 +46,8 @@ chronofield = make_field(/datum/proximity_monitor/advanced/timestop, list("current_range" = freezerange, "host" = src, "immune" = immune, "check_anti_magic" = check_anti_magic, "check_holy" = check_holy)) QDEL_IN(src, duration) -/obj/effect/timestop/wizard +/obj/effect/timestop/magic check_anti_magic = TRUE - duration = 100 /datum/proximity_monitor/advanced/timestop name = "chronofield" @@ -56,9 +55,10 @@ field_shape = FIELD_SHAPE_RADIUS_SQUARE requires_processing = TRUE var/list/immune = list() - var/list/mob/living/frozen_mobs = list() - var/list/obj/item/projectile/frozen_projectiles = list() - var/list/atom/movable/frozen_throws = list() + var/list/frozen_things = list() + var/list/frozen_mobs = list() //cached separately for processing + var/list/frozen_structures = list() //Also machinery, and only frozen aestethically + var/list/frozen_turfs = list() //Only aesthetically var/check_anti_magic = FALSE var/check_holy = FALSE @@ -74,85 +74,125 @@ /datum/proximity_monitor/advanced/timestop/proc/freeze_atom(atom/movable/A) if(immune[A] || global_frozen_atoms[A] || !istype(A)) return FALSE - if(A.throwing) - freeze_throwing(A) + if(ismob(A)) + var/mob/M = A + if(M.anti_magic_check(check_anti_magic, check_holy)) + immune[A] = TRUE + return + var/frozen = TRUE if(isliving(A)) freeze_mob(A) else if(istype(A, /obj/item/projectile)) freeze_projectile(A) + else if(istype(A, /obj/mecha)) + freeze_mecha(A) + else if((ismachinery(A) && !istype(A, /obj/machinery/light)) || isstructure(A)) //Special exception for light fixtures since recoloring causes them to change light + freeze_structure(A) else - return FALSE + frozen = FALSE + if(A.throwing) + freeze_throwing(A) + frozen = TRUE + if(!frozen) + return + frozen_things[A] = A.move_resist + A.move_resist = INFINITY + global_frozen_atoms[A] = src into_the_negative_zone(A) + RegisterSignal(A, COMSIG_MOVABLE_PRE_MOVE, .proc/unfreeze_atom) + RegisterSignal(A, COMSIG_ITEM_PICKUP, .proc/unfreeze_atom) return TRUE /datum/proximity_monitor/advanced/timestop/proc/unfreeze_all() - for(var/i in frozen_projectiles) - unfreeze_projectile(i) - for(var/i in frozen_mobs) - unfreeze_mob(i) - for(var/i in frozen_throws) - unfreeze_throw(i) + for(var/i in frozen_things) + unfreeze_atom(i) + for(var/T in frozen_turfs) + unfreeze_turf(T) + +/datum/proximity_monitor/advanced/timestop/proc/unfreeze_atom(atom/movable/A) + if(A.throwing) + unfreeze_throwing(A) + if(isliving(A)) + unfreeze_mob(A) + else if(istype(A, /obj/item/projectile)) + unfreeze_projectile(A) + else if(istype(A, /obj/mecha)) + unfreeze_mecha(A) + + UnregisterSignal(A, COMSIG_MOVABLE_PRE_MOVE) + UnregisterSignal(A, COMSIG_ITEM_PICKUP) + escape_the_negative_zone(A) + A.move_resist = frozen_things[A] + frozen_things -= A + global_frozen_atoms -= A + +/datum/proximity_monitor/advanced/timestop/proc/freeze_mecha(obj/mecha/M) + M.completely_disabled = TRUE + +/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mecha(obj/mecha/M) + M.completely_disabled = FALSE /datum/proximity_monitor/advanced/timestop/proc/freeze_throwing(atom/movable/AM) var/datum/thrownthing/T = AM.throwing T.paused = TRUE - frozen_throws[AM] = T - global_frozen_atoms[AM] = TRUE -/datum/proximity_monitor/advanced/timestop/proc/unfreeze_throw(atom/movable/AM) - var/datum/thrownthing/T = frozen_throws[AM] - T.paused = FALSE - frozen_throws -= AM - global_frozen_atoms -= AM +/datum/proximity_monitor/advanced/timestop/proc/unfreeze_throwing(atom/movable/AM) + var/datum/thrownthing/T = AM.throwing + if(T) + T.paused = FALSE + +/datum/proximity_monitor/advanced/timestop/proc/freeze_turf(turf/T) + into_the_negative_zone(T) + frozen_turfs += T + +/datum/proximity_monitor/advanced/timestop/proc/unfreeze_turf(turf/T) + escape_the_negative_zone(T) + +/datum/proximity_monitor/advanced/timestop/proc/freeze_structure(obj/O) + into_the_negative_zone(O) + frozen_structures += O + +/datum/proximity_monitor/advanced/timestop/proc/unfreeze_structure(obj/O) + escape_the_negative_zone(O) /datum/proximity_monitor/advanced/timestop/process() for(var/i in frozen_mobs) var/mob/living/m = i - if(get_dist(get_turf(m), get_turf(host)) > current_range) - unfreeze_mob(m) - else - m.Stun(20, 1, 1) + m.Stun(20, 1, 1) /datum/proximity_monitor/advanced/timestop/setup_field_turf(turf/T) for(var/i in T.contents) freeze_atom(i) + freeze_turf(T) return ..() -/datum/proximity_monitor/advanced/timestop/proc/unfreeze_projectile(obj/item/projectile/P) - escape_the_negative_zone(P) - frozen_projectiles -= P - P.paused = FALSE - global_frozen_atoms -= P - /datum/proximity_monitor/advanced/timestop/proc/freeze_projectile(obj/item/projectile/P) - frozen_projectiles[P] = TRUE P.paused = TRUE - global_frozen_atoms[P] = TRUE + +/datum/proximity_monitor/advanced/timestop/proc/unfreeze_projectile(obj/item/projectile/P) + P.paused = FALSE /datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L) - if(L.anti_magic_check(check_anti_magic, check_holy)) - immune += L - return + frozen_mobs += L L.Stun(20, 1, 1) - frozen_mobs[L] = L.anchored - L.anchored = TRUE - global_frozen_atoms[L] = TRUE - if(ishostile(L)) - var/mob/living/simple_animal/hostile/H = L - H.toggle_ai(AI_OFF) - H.LoseTarget() + ADD_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT) + walk(L, 0) //stops them mid pathing even if they're stunimmune + if(isanimal(L)) + var/mob/living/simple_animal/S = L + S.toggle_ai(AI_OFF) + if(ishostile(L)) + var/mob/living/simple_animal/hostile/H = L + H.LoseTarget() /datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L) - escape_the_negative_zone(L) L.AdjustStun(-20, 1, 1) - L.anchored = frozen_mobs[L] + REMOVE_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT) frozen_mobs -= L - global_frozen_atoms -= L - if(ishostile(L)) - var/mob/living/simple_animal/hostile/H = L - H.toggle_ai(initial(H.AIStatus)) + if(isanimal(L)) + var/mob/living/simple_animal/S = L + S.toggle_ai(initial(S.AIStatus)) //you don't look quite right, is something the matter? /datum/proximity_monitor/advanced/timestop/proc/into_the_negative_zone(atom/A) @@ -160,4 +200,4 @@ //let's put some colour back into your cheeks /datum/proximity_monitor/advanced/timestop/proc/escape_the_negative_zone(atom/A) - A.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY) \ No newline at end of file + A.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY) diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index c28ae3b4c5..f459e97814 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -186,8 +186,8 @@ obj/item/seeds/proc/is_gene_forbidden(typepath) product_name = parent.myseed.plantname if(getYield() >= 1) SSblackbox.record_feedback("tally", "food_harvested", getYield(), product_name) + parent.investigate_log("[user] harvested [getYield()] of [src], with seed traits [english_list(genes)] and reagents_add [english_list(reagents_add)] and potency [potency].", INVESTIGATE_BOTANY) parent.update_tray(user) - return result diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm index d11299fd5b..34988f5656 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm @@ -7,6 +7,26 @@ // please make sure they're sorted alphabetically and categorized +/datum/sprite_accessory/facial_hair/threeoclock + name = "Beard (3 o\'Clock)" + icon_state = "facial_3oclock" + +/datum/sprite_accessory/facial_hair/fiveoclock + name = "Beard (5 o\'Clock)" + icon_state = "facial_5oclock" + +/datum/sprite_accessory/facial_hair/fiveoclockm + name = "Beard (5 o\'Clock with Moustache)" + icon_state = "facial_5oclockmoustache" + +/datum/sprite_accessory/facial_hair/sevenoclock + name = "Beard (7 o\'Clock)" + icon_state = "facial_7oclock" + +/datum/sprite_accessory/facial_hair/sevenoclockm + name = "Beard (7 o\'Clock with Moustache)" + icon_state = "facial_7oclockmoustache" + /datum/sprite_accessory/facial_hair/abe name = "Beard (Abraham Lincoln)" icon_state = "facial_abe" @@ -23,10 +43,6 @@ name = "Beard (Dwarf)" icon_state = "facial_dwarf" -/datum/sprite_accessory/facial_hair/fiveoclock - name = "Beard (Five o Clock Shadow)" - icon_state = "facial_fiveoclock" - /datum/sprite_accessory/facial_hair/fullbeard name = "Beard (Full)" icon_state = "facial_fullbeard" @@ -35,6 +51,10 @@ name = "Beard (Goatee)" icon_state = "facial_gt" +/datum/sprite_accessory/facial_hair/goatee + name = "Beard (Goatee 2)" + icon_state = "facial_goatee" + /datum/sprite_accessory/facial_hair/hip name = "Beard (Hipster)" icon_state = "facial_hip" @@ -43,18 +63,38 @@ name = "Beard (Jensen)" icon_state = "facial_jensen" +/datum/sprite_accessory/facial_hair/martialartist + name = "Beard (Martial Artist)" + icon_state = "facial_martialartist" + +/datum/sprite_accessory/facial_hair/moonshiner + name = "Beard (Moonshiner)" + icon_state = "facial_moonshiner" + /datum/sprite_accessory/facial_hair/neckbeard name = "Beard (Neckbeard)" icon_state = "facial_neckbeard" +/datum/sprite_accessory/facial_hair/tribeard + name = "Beard (Tribeard)" + icon_state = "facial_tribeard" + /datum/sprite_accessory/facial_hair/vlongbeard name = "Beard (Very Long)" icon_state = "facial_wise" +/datum/sprite_accessory/facial_hair/volaju + name = "Beard (Volaju)" + icon_state = "facial_volaju" + /datum/sprite_accessory/facial_hair/longbeard name = "Beard (Long)" icon_state = "facial_longbeard" +/datum/sprite_accessory/facial_hair/moustache + name = "Moustache" + icon_state = "facial_moustache" + /datum/sprite_accessory/facial_hair/fu name = "Moustache (Fu Manchu)" icon_state = "facial_fumanchu" @@ -63,6 +103,10 @@ name = "Moustache (Hulk Hogan)" icon_state = "facial_hogan" //-Neek +/datum/sprite_accessory/facial_hair/pencil + name = "Moustache (Pencil)" + icon_state = "facial_pencilstache" + /datum/sprite_accessory/facial_hair/selleck name = "Moustache (Selleck)" icon_state = "facial_selleck" @@ -75,56 +119,31 @@ name = "Moustache (Van Dyke)" icon_state = "facial_vandyke" +/datum/sprite_accessory/facial_hair/walrus + name = "Moustache (Walrus)" + icon_state = "facial_walrus" + /datum/sprite_accessory/facial_hair/watson name = "Moustache (Watson)" icon_state = "facial_watson" +/datum/sprite_accessory/facial_hair/mutton + name = "Mutton Chops" + icon_state = "facial_mutton" + +/datum/sprite_accessory/facial_hair/muttonmus + name = "Mutton Chops with Moustache" + icon_state = "facial_muttonmus" + /datum/sprite_accessory/facial_hair/shaved name = "Shaved" icon_state = null gender = NEUTER +/datum/sprite_accessory/facial_hair/sideburn + name = "Sideburns" + icon_state = "facial_sideburns" + /datum/sprite_accessory/facial_hair/elvis name = "Sideburns (Elvis)" - icon_state = "facial_elvis" - -#define VFACE(_name, new_state) /datum/sprite_accessory/facial_hair/##new_state/icon_state=#new_state;;/datum/sprite_accessory/facial_hair/##new_state/name= #_name + " (Virgo)" -VFACE("Watson", facial_watson_s) -VFACE("Chaplin", facial_chaplin_s) -VFACE("Fullbeard", facial_fullbeard_s) -VFACE("Vandyke", facial_vandyke_s) -VFACE("Elvis", facial_elvis_s) -VFACE("Abe", facial_abe_s) -VFACE("Chin", facial_chin_s) -VFACE("GT", facial_gt_s) -VFACE("Hip", facial_hip_s) -VFACE("Hogan", facial_hogan_s) -VFACE("Selleck", facial_selleck_s) -VFACE("Neckbeard", facial_neckbeard_s) -VFACE("Longbeard", facial_longbeard_s) -VFACE("Dwarf", facial_dwarf_s) -VFACE("Sideburn", facial_sideburn_s) -VFACE("Mutton", facial_mutton_s) -VFACE("Moustache", facial_moustache_s) -VFACE("Pencilstache", facial_pencilstache_s) -VFACE("Goatee", facial_goatee_s) -VFACE("Smallstache", facial_smallstache_s) -VFACE("Volaju", facial_volaju_s) -VFACE("3 O\'clock", facial_3oclock_s) -VFACE("5 O\'clock", facial_5oclock_s) -VFACE("7 O\'clock", facial_7oclock_s) -VFACE("5 O\'clock Moustache", facial_5oclockmoustache_s) -VFACE("7 O\'clock", facial_7oclockmoustache_s) -VFACE("Walrus", facial_walrus_s) -VFACE("Muttonmus", facial_muttonmus_s) -VFACE("Wise", facial_wise_s) -VFACE("Martial Artist", facial_martialartist_s) -VFACE("Dorsalfnil", facial_dorsalfnil_s) -VFACE("Hornadorns", facial_hornadorns_s) -VFACE("Spike", facial_spike_s) -VFACE("Chinhorns", facial_chinhorns_s) -VFACE("Cropped Fullbeard", facial_croppedfullbeard_s) -VFACE("Chinless Beard", facial_chinlessbeard_s) -VFACE("Moonshiner", facial_moonshiner_s) -VFACE("Tribearder", facial_tribearder_s) -#undef VFACE \ No newline at end of file + icon_state = "facial_elvis" \ No newline at end of file diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm index abcc90c0ee..b0ed2000a6 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm @@ -27,7 +27,7 @@ /datum/sprite_accessory/hair/bald name = "Bald" - icon_state = null + icon_state = "bald" /datum/sprite_accessory/hair/balding name = "Balding Hair" @@ -37,6 +37,14 @@ name = "Bedhead" icon_state = "hair_bedhead" +/datum/sprite_accessory/hair/bedhead_long + name = "Bedhead (Long)" + icon_state = "hair_long_bedhead" + +/datum/sprite_accessory/hair/bedhead_longer + name = "Bedhead (Longer)" + icon_state = "hair_longer_bedhead" + /datum/sprite_accessory/hair/bedhead2 name = "Bedhead 2" icon_state = "hair_bedheadv2" @@ -51,7 +59,7 @@ /datum/sprite_accessory/hair/beehive2 name = "Beehive 2" - icon_state = "hair_beehivev2" + icon_state = "hair_beehive2" /datum/sprite_accessory/hair/bob name = "Bob Hair" @@ -69,6 +77,14 @@ name = "Bobcurl" icon_state = "hair_bobcurl" +/datum/sprite_accessory/hair/bobcut + name = "Bobcut" + icon_state = "hair_bobcut" + +/datum/sprite_accessory/hair/bobcutalt + name = "Bobcut (Alt)" + icon_state = "hair_bobcutalt" + /datum/sprite_accessory/hair/boddicker name = "Boddicker" icon_state = "hair_boddicker" @@ -77,6 +93,10 @@ name = "Bowl" icon_state = "hair_bowlcut" +/datum/sprite_accessory/hair/bowl2 + name = "Bowl 2" + icon_state = "hair_bowlcut2" + /datum/sprite_accessory/hair/braid name = "Braid (Floorlength)" icon_state = "hair_braid" @@ -89,6 +109,10 @@ name = "Braided Front" icon_state = "hair_braidfront" +/datum/sprite_accessory/hair/grandebraid + name = "Braid (Grande)" + icon_state = "hair_grande" + /datum/sprite_accessory/hair/not_floorlength_braid name = "Braid (High)" icon_state = "hair_braid2" @@ -113,10 +137,26 @@ name = "Bun Head 2" icon_state = "hair_bunhead2" +/datum/sprite_accessory/hair/bun3 + name = "Bun Head 3" + icon_state = "hair_bunhead3" + +/datum/sprite_accessory/hair/bun4 + name = "Bun Head 4" + icon_state = "hair_bunhead4" + +/datum/sprite_accessory/hair/doublebun + name = "Bun Head (Double)" + icon_state = "hair_doublebun" + /datum/sprite_accessory/hair/largebun - name = "Bun (Large)" + name = "Bun Head (Large)" icon_state = "hair_largebun" +/datum/sprite_accessory/hair/tightbun + name = "Bun Head (Tight)" + icon_state = "hair_tightbun" + /datum/sprite_accessory/hair/business name = "Business Hair" icon_state = "hair_business" @@ -137,10 +177,22 @@ name = "Buzzcut" icon_state = "hair_buzzcut" +/datum/sprite_accessory/hair/cia + name = "CIA" + icon_state = "hair_cia" + /datum/sprite_accessory/hair/combover name = "Combover" icon_state = "hair_combover" +/datum/sprite_accessory/hair/coffeehouse + name = "Coffee House" + icon_state = "hair_coffeehouse" + +/datum/sprite_accessory/hair/country + name = "Country" + icon_state = "hair_country" + /datum/sprite_accessory/hair/crew name = "Crewcut" icon_state = "hair_crewcut" @@ -149,13 +201,21 @@ name = "Curls" icon_state = "hair_curls" +/datum/sprite_accessory/hair/curly + name = "Curly" + icon_state = "hair_curly" + /datum/sprite_accessory/hair/cut name = "Cut Hair" icon_state = "hair_c" +/datum/sprite_accessory/hair/dave + name = "Dave" + icon_state = "hair_dave" + /datum/sprite_accessory/hair/devillock name = "Devil Lock" - icon_state = "hair_devilock" + icon_state = "hair_devillock" /datum/sprite_accessory/hair/dreadlocks name = "Dreadlocks" @@ -173,22 +233,66 @@ name = "Emo" icon_state = "hair_emo" +/datum/sprite_accessory/hair/emo2 + name = "Emo 2" + icon_state = "hair_emo2" + +/datum/sprite_accessory/hair/emo_fringe + name = "Emo (Fringe)" + icon_state = "hair_emofringe" + +/datum/sprite_accessory/hair/emo_long + name = "Emo (Long)" + icon_state = "hair_emolong" + +/datum/sprite_accessory/hair/lowfade + name = "Fade (Low)" + icon_state = "hair_lowfade" + +/datum/sprite_accessory/hair/medfade + name = "Fade (Medium)" + icon_state = "hair_medfade" + +/datum/sprite_accessory/hair/highfade + name = "Fade (High)" + icon_state = "hair_highfade" + +/datum/sprite_accessory/hair/baldfade + name = "Fade (Bald)" + icon_state = "hair_baldfade" + +/datum/sprite_accessory/hair/nofade + name = "Fade (None)" + icon_state = "hair_nofade" + +/datum/sprite_accessory/hair/father + name = "Father" + icon_state = "hair_father" + /datum/sprite_accessory/hair/feather name = "Feather" icon_state = "hair_feather" +/datum/sprite_accessory/hair/flair + name = "Flair" + icon_state = "hair_flair" + /datum/sprite_accessory/hair/sargeant name = "Flat Top" - icon_state = "hair_sargeant" + icon_state = "hair_sergeant" /datum/sprite_accessory/hair/bigflattop name = "Flat Top (Big)" icon_state = "hair_bigflattop" -/datum/sprite_accessory/hair/fag +/datum/sprite_accessory/hair/fag //grimacing emoji name = "Flow Hair" icon_state = "hair_f" +/datum/sprite_accessory/hair/fringetail + name = "Fringe Tail" + icon_state = "hair_fringetail" + /datum/sprite_accessory/hair/gelled name = "Gelled Back" icon_state = "hair_gelled" @@ -205,10 +309,22 @@ name = "Half-banged Hair 2" icon_state = "hair_halfbang2" +/datum/sprite_accessory/hair/halfbangalt + name = "Half-banged Hair (Alt)" + icon_state = "hair_halfbang_alt" + +/datum/sprite_accessory/hair/halfshaved + name = "Half-shaved Hair" + icon_state = "hair_halfshaved" + /datum/sprite_accessory/hair/hedgehog name = "Hedgehog Hair" icon_state = "hair_hedgehog" +/datum/sprite_accessory/hair/hightight + name = "High and Tight" + icon_state = "hair_hightight" + /datum/sprite_accessory/hair/himecut name = "Hime Cut" icon_state = "hair_himecut" @@ -217,6 +333,10 @@ name = "Hime Cut 2" icon_state = "hair_himecut2" +/datum/sprite_accessory/hair/shorthime + name = "Hime Cut (Short)" + icon_state = "hair_shorthime" + /datum/sprite_accessory/hair/himeup name = "Hime Updo" icon_state = "hair_himeup" @@ -225,16 +345,28 @@ name = "Hitop" icon_state = "hair_hitop" +/datum/sprite_accessory/hair/jade + name = "Jade" + icon_state = "hair_jade" + /datum/sprite_accessory/hair/jensen - name = "Jensen Hair" + name = "Jensen" icon_state = "hair_jensen" +/datum/sprite_accessory/hair/joestar + name = "Joestar" + icon_state = "hair_joestar" + +/datum/sprite_accessory/hair/kagami + name = "Kagami" + icon_state = "hair_kagami" + /datum/sprite_accessory/hair/keanu - name = "Keanu Hair" + name = "Keanu" icon_state = "hair_keanu" /datum/sprite_accessory/hair/kusangi - name = "Kusanagi Hair" + name = "Kusanagi" icon_state = "hair_kusanagi" /datum/sprite_accessory/hair/long @@ -249,6 +381,10 @@ name = "Long Hair 3" icon_state = "hair_long3" +/datum/sprite_accessory/hair/longalt + name = "Long Hair (Alt)" + icon_state = "hair_longeralt" + /datum/sprite_accessory/hair/long_over_eye name = "Long Over Eye" icon_state = "hair_longovereye" @@ -269,6 +405,10 @@ name = "Long Side Part" icon_state = "hair_longsidepart" +/datum/sprite_accessory/hair/manbun + name = "Manbun" + icon_state = "hair_manbun" + /datum/sprite_accessory/hair/megaeyebrows name = "Mega Eyebrows" icon_state = "hair_megaeyebrows" @@ -277,6 +417,10 @@ name = "Messy" icon_state = "hair_messy" +/datum/sprite_accessory/hair/modern + name = "Modern" + icon_state = "hair_modern" + /datum/sprite_accessory/hair/mohawk name = "Mohawk" icon_state = "hair_d" @@ -285,6 +429,26 @@ name = "Mohawk (Reverse)" icon_state = "hair_reversemohawk" +/datum/sprite_accessory/hair/shavedmohawk + name = "Mohawk (Shaved)" + icon_state = "hair_shavedmohawk" + +/datum/sprite_accessory/hair/mohawk_unshaven + name = "Mohawk (Unshaven)" + icon_state = "hair_unshaven_mohawk" + +/datum/sprite_accessory/hair/mulder + name = "Mulder" + icon_state = "hair_mulder" + +/datum/sprite_accessory/hair/nia + name = "Nia" + icon_state = "hair_nia" + +/datum/sprite_accessory/hair/nitori + name = "Nitori" + icon_state = "hair_nitori" + /datum/sprite_accessory/hair/odango name = "Odango" icon_state = "hair_odango" @@ -301,6 +465,10 @@ name = "Over Eye" icon_state = "hair_shortovereye" +/datum/sprite_accessory/hair/oxton + name = "Oxton" + icon_state = "hair_oxton" + //Donator item - fractious /datum/sprite_accessory/hair/over_eye_fr name = "Over Eye (fract)" @@ -331,6 +499,10 @@ name = "Pixie Cut" icon_state = "hair_pixie" +/datum/sprite_accessory/hair/plait + name = "Plait" + icon_state = "hair_plait" + /datum/sprite_accessory/hair/pompadour name = "Pompadour" icon_state = "hair_pompadour" @@ -383,10 +555,66 @@ name = "Ponytail (Side) 4" icon_state = "hair_sidetail4" +/datum/sprite_accessory/hair/spikytail + name = "Ponytail (Spiky)" + icon_state = "hair_spikyponytail" + +/datum/sprite_accessory/hair/poofy + name = "Poofy" + icon_state = "hair_poofy" + +/datum/sprite_accessory/hair/poofy2 + name = "Poofy 2" + icon_state = "hair_poofy2" + /datum/sprite_accessory/hair/quiff name = "Quiff" icon_state = "hair_quiff" +/datum/sprite_accessory/hair/ronin + name = "Ronin" + icon_state = "hair_ronin" + +/datum/sprite_accessory/hair/row + name = "Rows" + icon_state = "hair_rows1" + +/datum/sprite_accessory/hair/row2 + name = "Rows 2" + icon_state = "hair_rows2" + +/datum/sprite_accessory/hair/rowbun + name = "Rows (Bun)" + icon_state = "hair_rowbun" + +/datum/sprite_accessory/hair/rowdualtail + name = "Rows (Pigtails)" + icon_state = "hair_rowdualtail" + +/datum/sprite_accessory/hair/rowbraid + name = "Rows (Braid)" + icon_state = "hair_rowbraid" + +/datum/sprite_accessory/hair/scully + name = "Scully" + icon_state = "hair_scully" + +/datum/sprite_accessory/hair/shaggy + name = "Shaggy" + icon_state = "hair_shaggy" + +/datum/sprite_accessory/hair/shaved + name = "Shaved" + icon_state = "hair_shaved" + +/datum/sprite_accessory/hair/shavedpart + name = "Shaved (Part)" + icon_state = "hair_shavedpart" + +/datum/sprite_accessory/hair/bangs_short + name = "Short Bangs" + icon_state = "hair_shortbangs" + /datum/sprite_accessory/hair/short name = "Short Hair" icon_state = "hair_a" @@ -399,10 +627,30 @@ name = "Short Hair 3" icon_state = "hair_shorthair3" +/datum/sprite_accessory/hair/shorthair4 + name = "Short Hair 4" + icon_state = "hair_shorthair4" + +/datum/sprite_accessory/hair/shorthair80s + name = "Short Hair 80s" + icon_state = "hair_80s" + +/datum/sprite_accessory/hair/shorthairrosa + name = "Short Hair Rosa" + icon_state = "hair_rosa" + +/datum/sprite_accessory/hair/stail + name = "Short Tail" + icon_state = "hair_stail" + /datum/sprite_accessory/hair/shoulderlength name = "Shoulder-length Hair" icon_state = "hair_b" +/datum/sprite_accessory/hair/shy + name = "Shy" + icon_state = "hair_shy" + /datum/sprite_accessory/hair/sidecut name = "Sidecut" icon_state = "hair_sidecut" @@ -411,6 +659,10 @@ name = "Skinhead" icon_state = "hair_skinhead" +/datum/sprite_accessory/hair/sleaze + name = "Sleaze" + icon_state = "hair_sleaze" + /datum/sprite_accessory/hair/protagonist name = "Slightly Long Hair" icon_state = "hair_protagonist" @@ -435,14 +687,58 @@ name = "Swept Back Hair 2" icon_state = "hair_swept2" +/datum/sprite_accessory/hair/thinning + name = "Thinning" + icon_state = "hair_thinning" + +/datum/sprite_accessory/hair/thinningfront + name = "Thinning (Front)" + icon_state = "hair_thinningfront" + +/datum/sprite_accessory/hair/thinningrear + name = "Thinning (Rear)" + icon_state = "hair_thinningrear" + +/datum/sprite_accessory/hair/topknot + name = "Topknot" + icon_state = "hair_topknot" + +/datum/sprite_accessory/hair/toriyama + name = "Toriyama" + icon_state = "hair_toriyama" + +/datum/sprite_accessory/hair/toriyama2 + name = "Toriyama 2" + icon_state = "hair_toriyama2" + /datum/sprite_accessory/hair/tressshoulder name = "Tress Shoulder" icon_state = "hair_tressshoulder" +/datum/sprite_accessory/hair/trimmed + name = "Trimmed" + icon_state = "hair_trimmed" + +/datum/sprite_accessory/hair/trimflat + name = "Trimmed (Flat)" + icon_state = "hair_trimflat" + +/datum/sprite_accessory/hair/twintails + name = "Twintails" + icon_state = "hair_twintail" + /datum/sprite_accessory/hair/longtwintails name = "Twintails (Long)" icon_state = "hair_longstraighttwintails" +/datum/sprite_accessory/hair/undercut + name = "Undercut" + icon_state = "hair_undercut" + +/datum/sprite_accessory/hair/unkempt + name = "Unkempt" + icon_state = "hair_unkempt" + /datum/sprite_accessory/hair/updo name = "Updo" icon_state = "hair_updo" @@ -463,161 +759,22 @@ name = "Very Long with Fringe" icon_state = "hair_vlongfringe" -/*************** VIRGO PORTED HAIRS ****************************/ -#define VHAIR(_name, new_state) /datum/sprite_accessory/hair/##new_state/icon_state=#new_state;/datum/sprite_accessory/hair/##new_state/name = #_name + " (Virgo)" -//VIRGO PORTED HAIRS -VHAIR("Short Hair Rosa", hair_rosa_s) -VHAIR("Short Hair 80s", hair_80s_s) -VHAIR("Long Bedhead", hair_long_bedhead_s) -VHAIR("Dave", hair_dave_s) -VHAIR("Country", hair_country_s) -VHAIR("Shy", hair_shy_s) -VHAIR("Unshaven Mohawk", hair_unshaven_mohawk_s) -VHAIR("Manbun", hair_manbun_s) -VHAIR("Longer Bedhead", hair_longer_bedhead_s) -VHAIR("Ponytail", hair_ponytail_s) -VHAIR("Ziegler", hair_ziegler_s) -VHAIR("Emo Fringe", hair_emofringe_s) -VHAIR("Very Short Over Eye Alt", hair_veryshortovereyealternate_s) -VHAIR("Shorthime", hair_shorthime_s) -VHAIR("High Tight", hair_hightight_s) -VHAIR("Thinning Front", hair_thinningfront_s) -VHAIR("Big Afro", hair_bigafro_s) -VHAIR("Afro", hair_afro_s) -VHAIR("High Braid", hair_hbraid_s) -VHAIR("Braid", hair_braid_s) -VHAIR("Sargeant", hair_sargeant_s) -VHAIR("Gelled", hair_gelled_s) -VHAIR("Kagami", hair_kagami_s) -VHAIR("ShortTail", hair_stail_s) -VHAIR("Gentle", hair_gentle_s) -VHAIR("Grande", hair_grande_s) -VHAIR("Bobcurl", hair_bobcurl_s) -VHAIR("Pompadeur", hair_pompadour_s) -VHAIR("Plait", hair_plait_s) -VHAIR("Long", hair_long_s) -VHAIR("Rattail", hair_rattail_s) -VHAIR("Tajspiky", hair_tajspiky_s) -VHAIR("Messy", hair_messy_s) -VHAIR("Bangs", hair_bangs_s) -VHAIR("TBraid", hair_tbraid_s) -VHAIR("Toriyama2", hair_toriyama2_s) -VHAIR("CIA", hair_cia_s) -VHAIR("Mulder", hair_mulder_s) -VHAIR("Scully", hair_scully_s) -VHAIR("Nitori", hair_nitori_s) -VHAIR("Joestar", hair_joestar_s) -VHAIR("Ponytail4", hair_ponytail4_s) -VHAIR("Ponytail5", hair_ponytail5_s) -VHAIR("Beehive2", hair_beehive2_s) -VHAIR("Short Braid", hair_shortbraid_s) -VHAIR("Reverse Mohawk", hair_reversemohawk_s) -VHAIR("SHort Bangs", hair_shortbangs_s) -VHAIR("Half Shaved", hair_halfshaved_s) -VHAIR("Longer Alt 2", hair_longeralt2_s) -VHAIR("Bun", hair_bun_s) -VHAIR("Curly", hair_curly_s) -VHAIR("Victory", hair_victory_s) -VHAIR("Ponytail6", hair_ponytail6_s) -VHAIR("Undercut3", hair_undercut3_s) -VHAIR("Bobcut Alt", hair_bobcultalt_s) -VHAIR("Fingerwave", hair_fingerwave_s) -VHAIR("Oxton", hair_oxton_s) -VHAIR("Poofy2", hair_poofy2_s) -VHAIR("Fringe Tail", hair_fringetail_s) -VHAIR("Bun3", hair_bun3_s) -VHAIR("Wisp", hair_wisp_s) -VHAIR("Undercut2", hair_undercut2_s) -VHAIR("TBob", hair_tbob_s) -VHAIR("Spiky Ponytail", hair_spikyponytail_s) -VHAIR("Rowbun", hair_rowbun_s) -VHAIR("Rowdualtail", hair_rowdualtail_s) -VHAIR("Rowbraid", hair_rowbraid_s) -VHAIR("Shaved Mohawk", hair_shavedmohawk_s) -VHAIR("Topknot", hair_topknot_s) -VHAIR("Ronin", hair_ronin_s) -VHAIR("Bowlcut2", hair_bowlcut2_s) -VHAIR("Thinning Rear", hair_thinningrear_s) -VHAIR("Thinning", hair_thinning_s) -VHAIR("Jade", hair_jade_s) -VHAIR("Bedhead", hair_bedhead_s) -VHAIR("Dreadlocks", hair_dreads_s) -VHAIR("Very Long", hair_vlong_s) -VHAIR("Jensen", hair_jensen_s) -VHAIR("Halfbang", hair_halfbang_s) -VHAIR("Kusangi", hair_kusangi_s) -VHAIR("Ponytail", hair_ponytail_s) -VHAIR("Ponytail3", hair_ponytail3_s) -VHAIR("Halfbang Alt", hair_halfbang_alt_s) -VHAIR("Bedhead V2", hair_bedheadv2_s) -VHAIR("Long Fringe", hair_longfringe_s) -VHAIR("Flair", hair_flair_s) -VHAIR("Bedhead V3", hair_bedheadv3_s) -VHAIR("Himecut", hair_himecut_s) -VHAIR("Curls", hair_curls_s) -VHAIR("Very Long Fringe", hair_vlongfringe_s) -VHAIR("Longest", hair_longest_s) -VHAIR("Father", hair_father_s) -VHAIR("Emo Long", hair_emolong_s) -VHAIR("Short Hair 3", hair_shorthair3_s) -VHAIR("Double Bun", hair_doublebun_s) -VHAIR("Sleeze", hair_sleeze_s) -VHAIR("Twintail", hair_twintail_s) -VHAIR("Emo 2", hair_emo2_s) -VHAIR("Low Fade", hair_lowfade_s) -VHAIR("Med Fade", hair_medfade_s) -VHAIR("High Fade", hair_highfade_s) -VHAIR("Bald Fade", hair_baldfade_s) -VHAIR("No Fade", hair_nofade_s) -VHAIR("Trim Flat", hair_trimflat_s) -VHAIR("Shaved", hair_shaved_s) -VHAIR("Trimmed", hair_trimmed_s) -VHAIR("Tight Bun", hair_tightbun_s) -VHAIR("Short Hair 4", hair_d_s) -VHAIR("Short Hair 5", hair_e_s) -VHAIR("Short Hair 6", hair_f_s) -VHAIR("Skinhead", hair_skinhead_s) -VHAIR("Afro2", hair_afro2_s) -VHAIR("Bobcut", hair_bobcut_s) -VHAIR("Emo", hair_emo_s) -VHAIR("Long Over Eye", hair_longovereye_s) -VHAIR("Feather", hair_feather_s) -VHAIR("Hitop", hair_hitop_s) -VHAIR("Short Over Eye", hair_shortoverye_s) -VHAIR("Straight", hair_straight_s) -VHAIR("Buzzcut", hair_buzzcut_s) -VHAIR("Combover", hair_combover_s) -VHAIR("Crewcut", hair_crewcut_s) -VHAIR("Devillock", hair_devilock_s) -VHAIR("Clean", hair_clean_s) -VHAIR("Shaggy", hair_shaggy_s) -VHAIR("Updo", hair_updo_s) -VHAIR("Mohawk", hair_mohawk_s) -VHAIR("Odango", hair_odango_s) -VHAIR("Ombre", hair_ombre_s) -VHAIR("Parted", hair_parted_s) -VHAIR("Quiff", hair_quiff_s) -VHAIR("Volaju", hair_volaju_s) -VHAIR("Bun2", hair_bun2_s) -VHAIR("Rows1", hair_rows1_s) -VHAIR("Rows2", hair_rows2_s) -VHAIR("Dandy Pompadour", hair_dandypompadour_s) -VHAIR("Poofy", hair_poofy_s) -VHAIR("Toriyama", hair_toriyama_s) -VHAIR("Drillruru", hair_drillruru_s) -VHAIR("Bowlcut", hair_bowlcut_s) -VHAIR("Coffee House", hair_coffeehouse_s) -VHAIR("Family Man", hair_thefamilyman_s) -VHAIR("Shaved Part", hair_shavedpart_s) -VHAIR("Modern", hair_modern_s) -VHAIR("One Shoulder", hair_oneshoulder_s) -VHAIR("Very Short Over Eye", hair_veryshortovereye_s) -VHAIR("Unkept", hair_unkept_s) -VHAIR("Wife", hair_wife_s) -VHAIR("Nia", hair_nia_s) -VHAIR("Undercut", hair_undercut_s) -VHAIR("Bobcut Alt", hair_bobcutalt_s) -VHAIR("Short Hair 4 alt", hair_shorthair4_s) -VHAIR("Tressshoulder", hair_tressshoulder_s) - //END -#undef VHAIR \ No newline at end of file +/datum/sprite_accessory/hair/short_oe + name = "Very Short Over Eye" + icon_state = "hair_veryshortovereye" + +/datum/sprite_accessory/hair/short_oe_alt + name = "Very Short Over Eye (Alt)" + icon_state = "hair_veryshortovereyealternate" + +/datum/sprite_accessory/hair/volaju + name = "Volaju" + icon_state = "hair_volaju" + +/datum/sprite_accessory/hair/wisp + name = "Wisp" + icon_state = "hair_wisp" + +/datum/sprite_accessory/hair/ziegler + name = "Ziegler" + icon_state = "hair_ziegler" \ No newline at end of file diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index f2ea4f2b01..15cab5fc64 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -389,6 +389,7 @@ if(resilience) actual_trauma.resilience = resilience SSblackbox.record_feedback("tally", "traumas", 1, actual_trauma.type) + return actual_trauma //Add a random trauma of a certain subtype /obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience) diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm index 1333bc4399..6141a97c12 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm @@ -13,7 +13,7 @@ var/alt_inhands_file = 'icons/mob/alienqueen.dmi' -/mob/living/carbon/alien/humanoid/royal/can_inject() +/mob/living/carbon/alien/humanoid/royal/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE) return 0 /mob/living/carbon/alien/humanoid/royal/queen diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index a6595100a1..d6f6b6d9ae 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -44,7 +44,8 @@ if(M.occupant == src) M.go_out() - dna.species.spec_death(gibbed, src) + if(!QDELETED(dna)) //The gibbed param is bit redundant here since dna won't exist at this point if they got deleted. + dna.species.spec_death(gibbed, src) if(SSticker.HasRoundStarted()) SSblackbox.ReportDeath(src) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 8edd5847de..ef8a745b89 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -385,20 +385,17 @@ else if(isobserver(user) && traitstring) . += "Traits: [traitstring]" - if(print_flavor_text()) - if(get_visible_name() == "Unknown") //Are we sure we know who this is? Don't show flavor text unless we can recognize them. Prevents certain metagaming with impersonation. - . += "...?" - else if(skipface) //Sometimes we're not unknown, but impersonating someone in a hardsuit, let's not reveal our flavor text then either. - . += "...?" - else - . += "[print_flavor_text()]" - if(print_flavor_text_2()) - if(get_visible_name() == "Unknown") //Are we sure we know who this is? Don't show flavor text unless we can recognize them. Prevents certain metagaming with impersonation. - . += "...?" - else if(skipface) //Sometimes we're not unknown, but impersonating someone in a hardsuit, let's not reveal our flavor text then either. - . += "...?" - else - . += "[print_flavor_text_2()]" + //No flavor text unless the face can be seen. Prevents certain metagaming with impersonation. + var/invisible_man = skipface || get_visible_name() == "Unknown" + if(invisible_man) + . += "...?" + else + var/flavor = print_flavor_text() + if(flavor) + . += flavor + var/temp_flavor = print_flavor_text_2() + if(temp_flavor) + . += temp_flavor . += "*---------*" /mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects! diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 934e0f08dc..accaab3ac1 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -336,7 +336,8 @@ if(bomb_armor < EXPLODE_GIB_THRESHOLD) //gibs the mob if their bomb armor is lower than EXPLODE_GIB_THRESHOLD for(var/I in contents) var/atom/A = I - A.ex_act(severity) + if(!QDELETED(A)) + A.ex_act(severity) gib() return else diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 2a5ec51b55..eb1e194c0f 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -849,6 +849,8 @@ linked_mobs.Add(M) if(!selflink) to_chat(M, "You are now connected to [slimelink_owner.real_name]'s Slime Link.") + RegisterSignal(M, COMSIG_MOB_DEATH , .proc/unlink_mob) + RegisterSignal(M, COMSIG_PARENT_QDELETING, .proc/unlink_mob) var/datum/action/innate/linked_speech/action = new(src) linked_actions.Add(action) action.Grant(M) @@ -858,6 +860,7 @@ var/link_id = linked_mobs.Find(M) if(!(link_id)) return + UnregisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING)) var/datum/action/innate/linked_speech/action = linked_actions[link_id] action.Remove(M) to_chat(M, "You are no longer connected to [slimelink_owner.real_name]'s Slime Link.") @@ -890,18 +893,11 @@ Remove(H) return - if(QDELETED(H) || H.stat == DEAD) - species.unlink_mob(H) - return - if(message) var/msg = "\[[species.slimelink_owner.real_name]'s Slime Link\] [H]: [message]" log_directed_talk(H, species.slimelink_owner, msg, LOG_SAY, "slime link") for(var/X in species.linked_mobs) var/mob/living/M = X - if(QDELETED(M) || M.stat == DEAD) - species.unlink_mob(M) - continue to_chat(M, msg) for(var/X in GLOB.dead_mob_list) 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 5a7710fe29..4a7399f287 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -54,7 +54,7 @@ ..() /datum/species/plasmaman/before_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE) - var/current_job = J.title + var/current_job = J?.title var/datum/outfit/plasmaman/O = new /datum/outfit/plasmaman switch(current_job) if("Chaplain") diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index c4088317b1..cd68dabbef 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -382,9 +382,6 @@ There are several things that need to be remembered: if(wear_suit) var/obj/item/clothing/suit/S = wear_suit - var/item_level_support = FALSE // LISTEN! If you must degrade the code with further snowflake checks, at least keep it compatible with worn non-clothing items! - if(!istype(S)) - item_level_support = TRUE wear_suit.screen_loc = ui_oclothing if(client && hud_used && hud_used.hud_shown) if(hud_used.inventory_shown) @@ -400,7 +397,7 @@ There are several things that need to be remembered: if("taur" in dna.species.mutant_bodyparts) T = GLOB.taur_list[dna.features["taur"]] - if(!item_level_support && S.mutantrace_variation) + if(S.mutantrace_variation) if(T?.taur_mode) var/init_worn_icon = worn_icon variation_flag |= S.mutantrace_variation & T.taur_mode || S.mutantrace_variation & T.alt_taur_mode diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 33b9dffaf0..e83f67f796 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -30,6 +30,9 @@ /mob/living/carbon/monkey/handle_mutations_and_radiation() if(radiation) + if(radiation > RAD_MOB_MUTATE && prob((radiation - RAD_MOB_MUTATE) / 25)) + gorillize() + return if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB)) if(!IsKnockdown()) emote("collapse") @@ -41,10 +44,6 @@ randmutb() emote("gasp") domutcheck() - - if(radiation > RAD_MOB_MUTATE * 2 && prob(50)) - gorillize() - return if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB)) vomit(10, TRUE) return ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 72b7b580f7..90ada3d718 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -90,8 +90,10 @@ if(now_pushing) return TRUE + var/they_can_move = TRUE if(isliving(M)) var/mob/living/L = M + they_can_move = L.canmove //L.mobility_flags & MOBILITY_MOVE //Also spread diseases for(var/thing in diseases) var/datum/disease/D = thing @@ -144,13 +146,17 @@ return 1 if(!M.buckled && !M.has_buckled_mobs()) - var/mob_swap - //the puller can always swap with its victim if on grab intent - if(M.pulledby == src && a_intent == INTENT_GRAB) - mob_swap = 1 - //restrained people act if they were on 'help' intent to prevent a person being pulled from being separated from their puller - else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP)) - mob_swap = 1 + var/mob_swap = FALSE + var/too_strong = (M.move_resist > move_force) //can't swap with immovable objects unless they help us + if(!they_can_move) //we have to physically move them + if(!too_strong) + mob_swap = TRUE + else + if(M.pulledby == src && a_intent == INTENT_GRAB) + mob_swap = TRUE + //restrained people act if they were on 'help' intent to prevent a person being pulled from being separated from their puller + else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP)) + mob_swap = TRUE if(mob_swap) //switch our position with M if(loc && !loc.Adjacent(M.loc)) @@ -453,7 +459,7 @@ return ret // Living mobs use can_inject() to make sure that the mob is not syringe-proof in general. -/mob/living/proc/can_inject() +/mob/living/proc/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE) return TRUE /mob/living/is_injectable(allowmobs = TRUE) diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 15a04235cc..1147042c8c 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -53,11 +53,11 @@ if(NONE) return FALSE if(POWER_REQ_ALL) - return !T || !A || ((!A.power_equip || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha))) + return !T || !A || ((!A.powered(EQUIP) || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha))) if(POWER_REQ_CLOCKCULT) for(var/obj/effect/clockwork/sigil/transmission/ST in range(src, SIGIL_ACCESS_RANGE)) return FALSE - return !T || !A || (!istype(T, /turf/open/floor/clockwork) && (!A.power_equip || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha))) + return !T || !A || (!istype(T, /turf/open/floor/clockwork) && (!A.powered(EQUIP) || isspaceturf(T)) && !is_type_in_list(loc, list(/obj/item, /obj/mecha))) /mob/living/silicon/ai/updatehealth() if(status_flags & GODMODE) @@ -100,7 +100,7 @@ sleep(50) var/turf/T = get_turf(src) var/area/AIarea = get_area(src) - if(AIarea && AIarea.power_equip) + if(AIarea && AIarea.powered(EQUIP)) if(!isspaceturf(T)) ai_restore_power() return @@ -120,7 +120,7 @@ var/PRP //like ERP with the code, at least this stuff is no more 4x sametext for (PRP=1, PRP<=4, PRP++) T = get_turf(src) - AIarea = get_area(src) + AIarea = get_base_area(src) if(AIarea) for (var/obj/machinery/power/apc/APC in AIarea) if (!(APC.stat & BROKEN)) @@ -134,7 +134,7 @@ to_chat(src, "Lost connection with the APC!") aiRestorePowerRoutine = POWER_RESTORATION_SEARCH_APC return - if(AIarea.power_equip) + if(AIarea.powered(EQUIP)) if(!isspaceturf(T)) ai_restore_power() return diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 8215f84c50..55f4bdd65d 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -438,7 +438,7 @@ if(1) . += "
Medical Record

" if(medicalActive1 in GLOB.data_core.general) - . += "Name: [medicalActive1.fields["name"]] ID: [medicalActive1.fields["id"]]
\nSex: [medicalActive1.fields["sex"]]
\nAge: [medicalActive1.fields["age"]]
\nFingerprint: [medicalActive1.fields["fingerprint"]]
\nPhysical Status: [medicalActive1.fields["p_stat"]]
\nMental Status: [medicalActive1.fields["m_stat"]]
" + . += "Name: [medicalActive1.fields["name"]] ID: [medicalActive1.fields["id"]]
\nGender: [medicalActive1.fields["gender"]]
\nAge: [medicalActive1.fields["age"]]
\nFingerprint: [medicalActive1.fields["fingerprint"]]
\nPhysical Status: [medicalActive1.fields["p_stat"]]
\nMental Status: [medicalActive1.fields["m_stat"]]
" else . += "
Requested medical record not found.

" if(medicalActive2 in GLOB.data_core.medical) @@ -460,7 +460,7 @@ if(1) . += "

Security Record

" if(securityActive1 in GLOB.data_core.general) - . += "Name: [securityActive1.fields["name"]] ID: [securityActive1.fields["id"]]
\nSex: [securityActive1.fields["sex"]]
\nAge: [securityActive1.fields["age"]]
\nRank: [securityActive1.fields["rank"]]
\nFingerprint: [securityActive1.fields["fingerprint"]]
\nPhysical Status: [securityActive1.fields["p_stat"]]
\nMental Status: [securityActive1.fields["m_stat"]]
" + . += "Name: [securityActive1.fields["name"]] ID: [securityActive1.fields["id"]]
\nGender: [securityActive1.fields["gender"]]
\nAge: [securityActive1.fields["age"]]
\nRank: [securityActive1.fields["rank"]]
\nFingerprint: [securityActive1.fields["fingerprint"]]
\nPhysical Status: [securityActive1.fields["p_stat"]]
\nMental Status: [securityActive1.fields["m_stat"]]
" else . += "
Requested security record not found,

" if(securityActive2 in GLOB.data_core.security) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 33c66079d5..e5881848d5 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -151,7 +151,7 @@ for(var/key in alarm_types_clear) alarm_types_clear[key] = 0 -/mob/living/silicon/can_inject(mob/user, error_msg) +/mob/living/silicon/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE) if(error_msg) to_chat(user, "[p_their(TRUE)] outer shell is too tough.") return FALSE diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 2371cfd7f1..554d03991a 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -207,7 +207,11 @@ switch(add_to) if("collar") - add_collar(usr.get_active_held_item(), usr) + var/obj/item/clothing/neck/petcollar/P = usr.get_active_held_item() + if(!istype(P)) + to_chat(usr,"That's not a collar.") + return + add_collar(P, usr) update_corgi_fluff() if(BODY_ZONE_HEAD) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 71465f23f9..65ee6a69f2 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -479,31 +479,33 @@ Difficulty: Very Hard NewTerrainTables = /obj/structure/table/abductor /obj/machinery/anomalous_crystal/theme_warp/ActivationReaction(mob/user, method) - if(..()) - var/area/A = get_area(src) - if(!A.outdoors && !(A in affected_targets)) - for(var/atom/Stuff in A) - if(isturf(Stuff)) - var/turf/T = Stuff - if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors) - var/turf/open/O = T.ChangeTurf(NewTerrainFloors, flags = CHANGETURF_INHERIT_AIR) - if(prob(florachance) && NewFlora.len && !is_blocked_turf(O, TRUE)) - var/atom/Picked = pick(NewFlora) - new Picked(O) - continue - if(iswallturf(T) && NewTerrainWalls) - T.ChangeTurf(NewTerrainWalls) - continue - if(istype(Stuff, /obj/structure/chair) && NewTerrainChairs) - var/obj/structure/chair/Original = Stuff - var/obj/structure/chair/C = new NewTerrainChairs(Original.loc) - C.setDir(Original.dir) - qdel(Stuff) - continue - if(istype(Stuff, /obj/structure/table) && NewTerrainTables) - new NewTerrainTables(Stuff.loc) - continue - affected_targets += A + . = ..() + if(!.) + return + for(var/i in get_sub_areas(src)) + var/area/A = i + if(A.outdoors || (A in affected_targets)) + continue + affected_targets += A + for(var/stuff in A) + var/atom/target = stuff + if(isturf(target)) + var/turf/T = target + if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors) + var/turf/open/O = T.ChangeTurf(NewTerrainFloors, flags = CHANGETURF_INHERIT_AIR) + if(NewFlora.len && prob(florachance) && !is_blocked_turf(O, TRUE)) + var/atom/Picked = pick(NewFlora) + new Picked(O) + else if(iswallturf(T) && NewTerrainWalls) + T.ChangeTurf(NewTerrainWalls) + else if(NewTerrainChairs && istype(target, /obj/structure/chair)) + var/obj/structure/chair/Original = target + var/obj/structure/chair/C = new NewTerrainChairs(Original.loc) + C.setDir(Original.dir) + qdel(target) + else if(NewTerrainTables && istype(target, /obj/structure/table)) + new NewTerrainTables(target.loc) + qdel(target) /obj/machinery/anomalous_crystal/emitter //Generates a projectile when interacted with observer_desc = "This crystal generates a projectile when activated." diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 49b56d0950..43ce940d57 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -170,7 +170,7 @@ Difficulty: Medium to_chat(user, "The staff is still recharging!") return - var/area/user_area = get_area(user) + var/area/user_area = get_base_area(user) var/turf/user_turf = get_turf(user) if(!user_area || !user_turf || (user_area.type in excluded_areas)) to_chat(user, "Something is preventing you from using the staff here.") diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 6082bdf705..8b2ef507d9 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -84,6 +84,7 @@ var/datum/personal_crafting/handcrafting var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever), AI_Z_OFF (Temporarily off due to nonpresence of players) + var/can_have_ai = TRUE //once we have become sentient, we can never go back var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check. @@ -425,6 +426,9 @@ canmove = FALSE else canmove = value_otherwise + if(!canmove) // !(mobility_flags & MOBILITY_MOVE) + walk(src, 0) //stop mid walk + update_transform() update_action_buttons_icon() return canmove @@ -443,6 +447,7 @@ /mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion toggle_ai(AI_OFF) // To prevent any weirdness. + can_have_ai = FALSE /mob/living/simple_animal/update_sight() if(!client) @@ -557,6 +562,8 @@ LoadComponent(/datum/component/riding) /mob/living/simple_animal/proc/toggle_ai(togglestatus) + if(!can_have_ai && (togglestatus != AI_OFF)) + return if (AIStatus != togglestatus) if (togglestatus > 0 && togglestatus < 5) if (togglestatus == AI_Z_OFF || AIStatus == AI_Z_OFF) diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 29b4689317..fd6cecf926 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -41,7 +41,7 @@ AIproc = 1 while(AIproc && stat != DEAD && (attacked || hungry || rabid || buckled)) - if(buckled) // can't eat AND have this little process at the same time + if(!canmove) // !(mobility_flags & MOBILITY_MOVE) //also covers buckling. Not sure why buckled is in the while condition if we're going to immediately break, honestly break if(!Target || client) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 630ce54261..33cc2c6e20 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -456,8 +456,10 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA return /mob/proc/transfer_ckey(mob/new_mob, send_signal = TRUE) - if(!ckey || !new_mob) - CRASH("transfer_ckey() called [ckey ? "" : "on a ckey-less mob[new_mob ? "" : " and "]"][new_mob ? "" : "without a valid mob target"]!") + if(!new_mob || (!ckey && new_mob.ckey)) + CRASH("transfer_ckey() called [new_mob ? "on ckey-less mob with a player mob as target" : "without a valid mob target"]!") + if(!ckey) + return SEND_SIGNAL(new_mob, COMSIG_MOB_PRE_PLAYER_CHANGE, new_mob, src) if (client && client.prefs && client.prefs.auto_ooc) if (client.prefs.chat_toggles & CHAT_OOC && isliving(new_mob)) @@ -964,4 +966,4 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) /mob/setMovetype(newval) . = ..() - update_movespeed(FALSE) \ No newline at end of file + update_movespeed(FALSE) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 8dae1f30f7..1402b78908 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -26,7 +26,7 @@ var/computer_id = null var/list/logging = list() - var/obj/machinery/machine = null + var/atom/machine = null var/next_move = null var/create_area_cooldown diff --git a/code/modules/modular_computers/computers/item/computer_damage.dm b/code/modules/modular_computers/computers/item/computer_damage.dm index 001cf3aa65..6664b449bd 100644 --- a/code/modules/modular_computers/computers/item/computer_damage.dm +++ b/code/modules/modular_computers/computers/item/computer_damage.dm @@ -23,6 +23,8 @@ new /obj/item/stack/sheet/metal(newloc, round(steel_sheet_cost/2)) for(var/C in all_components) var/obj/item/computer_hardware/H = all_components[C] + if(QDELETED(H)) + return uninstall_component(H) H.forceMove(newloc) if(prob(25)) diff --git a/code/modules/modular_computers/computers/item/laptop_presets.dm b/code/modules/modular_computers/computers/item/laptop_presets.dm index 102397037b..e50392e3b3 100644 --- a/code/modules/modular_computers/computers/item/laptop_presets.dm +++ b/code/modules/modular_computers/computers/item/laptop_presets.dm @@ -13,11 +13,11 @@ -/obj/item/modular_computer/laptop/preset/civillian +/obj/item/modular_computer/laptop/preset/civilian desc = "A low-end laptop often used for personal recreation." -/obj/item/modular_computer/laptop/preset/civillian/install_programs() +/obj/item/modular_computer/laptop/preset/civilian/install_programs() var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD] hard_drive.store_file(new/datum/computer_file/program/chatclient()) - hard_drive.store_file(new/datum/computer_file/program/nttransfer()) \ No newline at end of file + hard_drive.store_file(new/datum/computer_file/program/nttransfer()) diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index aa1fd7dbfb..4120c81a78 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -126,7 +126,7 @@ continue var/obj/item/paper/P = new /obj/item/paper(src) P.info = "
Security Record

" - P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]]
\nSex: [G.fields["sex"]]
\nAge: [G.fields["age"]]
\nFingerprint: [G.fields["fingerprint"]]
\nPhysical Status: [G.fields["p_stat"]]
\nMental Status: [G.fields["m_stat"]]
" + P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]]
\nGender: [G.fields["gender"]]
\nAge: [G.fields["age"]]
\nFingerprint: [G.fields["fingerprint"]]
\nPhysical Status: [G.fields["p_stat"]]
\nMental Status: [G.fields["m_stat"]]
" P.info += "
\n
Security Data

\nCriminal Status: [S.fields["criminal"]]
\n
\nMinor Crimes: [S.fields["mi_crim"]]
\nDetails: [S.fields["mi_crim_d"]]
\n
\nMajor Crimes: [S.fields["ma_crim"]]
\nDetails: [S.fields["ma_crim_d"]]
\n
\nImportant Notes:
\n\t[S.fields["notes"]]
\n
\n
Comments/Log

" var/counter = 1 while(S.fields["com_[counter]"]) @@ -159,7 +159,7 @@ continue var/obj/item/paper/P = new /obj/item/paper(src) P.info = "
Medical Record

" - P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]]
\nSex: [G.fields["sex"]]
\nAge: [G.fields["age"]]
\nFingerprint: [G.fields["fingerprint"]]
\nPhysical Status: [G.fields["p_stat"]]
\nMental Status: [G.fields["m_stat"]]
" + P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]]
\nGender: [G.fields["gender"]]
\nAge: [G.fields["age"]]
\nFingerprint: [G.fields["fingerprint"]]
\nPhysical Status: [G.fields["p_stat"]]
\nMental Status: [G.fields["m_stat"]]
" P.info += "
\n
Medical Data

\nBlood Type: [M.fields["blood_type"]]
\nDNA: [M.fields["b_dna"]]
\n
\nMinor Disabilities: [M.fields["mi_dis"]]
\nDetails: [M.fields["mi_dis_d"]]
\n
\nMajor Disabilities: [M.fields["ma_dis"]]
\nDetails: [M.fields["ma_dis_d"]]
\n
\nAllergies: [M.fields["alg"]]
\nDetails: [M.fields["alg_d"]]
\n
\nCurrent Diseases: [M.fields["cdi"]] (per disease info placed in log/comment section)
\nDetails: [M.fields["cdi_d"]]
\n
\nImportant Notes:
\n\t[M.fields["notes"]]
\n
\n
Comments/Log

" var/counter = 1 while(M.fields["com_[counter]"]) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index cfd028c4df..076d8b026a 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -34,7 +34,9 @@ /obj/item/paperplane/handle_atom_del(atom/A) if(A == internalPaper) + var/obj/item/paper/P = internalPaper internalPaper = null + P.moveToNullspace() //So we're not deleting it twice when deleting our contents. if(!QDELETED(src)) qdel(src) return ..() diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index 125219d809..140167c2f0 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -33,6 +33,8 @@ var/picture_size_y_min = 1 var/picture_size_x_max = 4 var/picture_size_y_max = 4 + var/can_customise = TRUE + var/default_picture_name /obj/item/camera/attack_self(mob/user) if(!disk) @@ -199,8 +201,10 @@ user.put_in_hands(p) pictures_left-- to_chat(user, "[pictures_left] photos left.") - var/customize = alert(user, "Do you want to customize the photo?", "Customization", "Yes", "No") - if(customize == "Yes") + var/customise = "No" + if(can_customise) + customise = alert(user, "Do you want to customize the photo?", "Customization", "Yes", "No") + if(customise == "Yes") var/name1 = stripped_input(user, "Set a name for this photo, or leave blank. 32 characters max.", "Name", max_length = 32) var/desc1 = stripped_input(user, "Set a description to add to photo, or leave blank. 128 characters max.", "Caption", max_length = 128) var/caption = stripped_input(user, "Set a caption for this photo, or leave blank. 256 characters max.", "Caption", max_length = 256) @@ -210,6 +214,10 @@ picture.picture_desc = "[desc1] - [picture.picture_desc]" if(caption) picture.caption = caption + else + if(default_picture_name) + picture.picture_name = default_picture_name + p.set_picture(picture, TRUE, TRUE) if(CONFIG_GET(flag/picture_logging_camera)) picture.log_to_file() \ No newline at end of file diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index b7cbcdb9d8..78294e988d 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -56,6 +56,8 @@ integrity_failure = 50 var/damage_deflection = 10 resistance_flags = FIRE_PROOF + armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 100, "bomb" = 30, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50) + req_access = list(ACCESS_ENGINE_EQUIP) interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON var/lon_range = 1.5 @@ -148,12 +150,40 @@ if(terminal) terminal.connect_to_network() -/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0) - if (!req_access) - req_access = list(ACCESS_ENGINE_EQUIP) - if (!armor) - armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 100, "bomb" = 30, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50) - ..() +/obj/machinery/power/apc/Initialize(mapload, ndir, building = FALSE) + . = ..() + var/area/A = get_base_area(src) + if(!building) + has_electronics = APC_ELECTRONICS_SECURED + // is starting with a power cell installed, create it and set its charge level + if(cell_type) + cell = new cell_type + cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value) + + //if area isn't specified use current + if(areastring) + area = get_area_instance_from_text(areastring) + if(!area) + area = A + stack_trace("Bad areastring path for [src], [src.areastring]") + else if(isarea(A) && !areastring) + area = A + if(auto_name) + name = "\improper [A.name] APC" + update_icon() + + make_terminal() + update_nightshift_auth_requirement() + + else + area = A + opened = APC_COVER_OPENED + operating = FALSE + name = "\improper [A.name] APC" + stat |= MAINT + update_icon() + addtimer(CALLBACK(src, .proc/update), 5) + GLOB.apcs_list += src wires = new /datum/wires/apc(src) @@ -164,9 +194,6 @@ src.tdir = dir // to fix Vars bug setDir(SOUTH) - if(auto_name) - name = "\improper [get_area(src)] APC" - switch(tdir) if(NORTH) pixel_y = 23 @@ -176,14 +203,6 @@ pixel_x = 24 if(WEST) pixel_x = -25 - if (building) - area = get_area(src) - opened = APC_COVER_OPENED - operating = FALSE - name = "[area.name] APC" - stat |= MAINT - src.update_icon() - addtimer(CALLBACK(src, .proc/update), 5) /obj/machinery/power/apc/Destroy() GLOB.apcs_list -= src @@ -217,33 +236,6 @@ terminal.setDir(tdir) terminal.master = src -/obj/machinery/power/apc/Initialize(mapload) - . = ..() - if(!mapload) - return - has_electronics = APC_ELECTRONICS_SECURED - // is starting with a power cell installed, create it and set its charge level - if(cell_type) - cell = new cell_type - cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value) - - var/area/A = src.loc.loc - - //if area isn't specified use current - if(areastring) - src.area = get_area_instance_from_text(areastring) - if(!src.area) - src.area = A - stack_trace("Bad areastring path for [src], [src.areastring]") - else if(isarea(A) && src.areastring == null) - src.area = A - update_icon() - - make_terminal() - update_nightshift_auth_requirement() - - addtimer(CALLBACK(src, .proc/update), 5) - /obj/machinery/power/apc/examine(mob/user) . = ..() if(stat & BROKEN) @@ -1432,7 +1424,7 @@ return for(var/A in GLOB.ai_list) var/mob/living/silicon/ai/I = A - if(get_area(I) == area) + if(get_base_area(I) == area) return failure_timer = max(failure_timer, round(duration)) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 903f63e22c..441eb27621 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -193,9 +193,9 @@ var/on = FALSE // 1 if on, 0 if off var/on_gs = FALSE var/static_power_used = 0 - var/brightness = 8 // luminosity when on, also used in power calculation + var/brightness = 11 // luminosity when on, also used in power calculation var/bulb_power = 0.75 // basically the alpha of the emitted light source - var/bulb_colour = "#FFEEDD" // befault colour of the light. + var/bulb_colour = "#FFF6ED" // befault colour of the light. var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN var/flickering = FALSE var/light_type = /obj/item/light/tube // the type of light item @@ -231,7 +231,7 @@ icon_state = "bulb" base_state = "bulb" fitting = "bulb" - brightness = 4 + brightness = 6 bulb_colour = "#FFDDBB" desc = "A small lighting fixture." light_type = /obj/item/light/bulb @@ -272,11 +272,11 @@ spawn(2) switch(fitting) if("tube") - brightness = 8 + brightness = 11 if(prob(2)) break_light_tube(1) if("bulb") - brightness = 4 + brightness = 6 if(prob(5)) break_light_tube(1) spawn(1) @@ -294,7 +294,7 @@ cut_overlays() switch(status) // set icon_states if(LIGHT_OK) - var/area/A = get_area(src) + var/area/A = get_base_area(src) if(emergency_mode || (A && A.fire)) icon_state = "[base_state]_emergency" else @@ -323,7 +323,7 @@ var/CO = bulb_colour if(color) CO = color - var/area/A = get_area(src) + var/area/A = get_base_area(src) if (A && A.fire) CO = bulb_emergency_colour else if (nightshift_enabled) @@ -351,11 +351,11 @@ set_light(0) update_icon() - active_power_usage = (brightness * 10) + active_power_usage = (brightness * 7.2) if(on != on_gs) on_gs = on if(on) - static_power_used = brightness * 20 //20W per unit luminosity + static_power_used = brightness * 14.4 //20W per unit luminosity addStaticPower(static_power_used, STATIC_LIGHT) else removeStaticPower(static_power_used, STATIC_LIGHT) @@ -738,7 +738,7 @@ icon_state = "ltube" base_state = "ltube" item_state = "c_tube" - brightness = 8 + brightness = 11 /obj/item/light/tube/broken status = LIGHT_BROKEN @@ -751,7 +751,7 @@ item_state = "contvapour" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' - brightness = 4 + brightness = 6 /obj/item/light/bulb/broken status = LIGHT_BROKEN @@ -820,7 +820,7 @@ icon = 'icons/obj/lighting.dmi' base_state = "floor" // base description and icon_state icon_state = "floor" - brightness = 4 + brightness = 6 layer = 2.5 light_type = /obj/item/light/bulb fitting = "bulb" diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index d2d3d60066..fba526edbd 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -382,6 +382,7 @@ return null /area/proc/get_apc() + var/target = base_area ? base_area : src for(var/obj/machinery/power/apc/APC in GLOB.apcs_list) - if(APC.area == src) + if(APC.area == target) return APC \ No newline at end of file diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index ab9dd6d6a6..611f8c57bd 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -96,15 +96,20 @@ "Gold Trim" = "detective_gold", "The Peacemaker" = "detective_peacemaker" ) + var/list/safe_calibers + +/obj/item/gun/ballistic/revolver/detective/Initialize() + . = ..() + safe_calibers = magazine.caliber /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(chambered && !(chambered.caliber in safe_calibers)) if(prob(70 - (magazine.ammo_count() * 10))) //minimum probability of 10, maximum of 60 playsound(user, fire_sound, 50, 1) to_chat(user, "[src] blows up in your face!") user.take_bodypart_damage(0,20) user.dropItemToGround(src) - return 0 + return FALSE ..() /obj/item/gun/ballistic/revolver/detective/screwdriver_act(mob/living/user, obj/item/I) diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index ecd906f2a9..1495ff61ba 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -374,14 +374,18 @@ desc = "Decreases the cooldown of a kinetic accelerator. Not rated for minebot use." modifier = 2.5 minebot_upgrade = FALSE + var/decreased /obj/item/borg/upgrade/modkit/cooldown/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user) . = ..() if(.) - KA.overheat_time -= modifier + var/old = KA.overheat_time + KA.overheat_time = max(0, KA.overheat_time - modifier) + decreased = old - KA.overheat_time + /obj/item/borg/upgrade/modkit/cooldown/uninstall(obj/item/gun/energy/kinetic_accelerator/KA) - KA.overheat_time += modifier + KA.overheat_time += decreased ..() /obj/item/borg/upgrade/modkit/cooldown/minebot diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index bf3c4220b4..95e104ba68 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -171,7 +171,7 @@ return master -/datum/reagents/proc/trans_to(obj/target, amount=1, multiplier=1, preserve_data=1, no_react = 0)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. +/datum/reagents/proc/trans_to(obj/target, amount = 1, multiplier = 1, preserve_data = 1, no_react = 0, log = FALSE)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. var/list/cached_reagents = reagent_list if(!target || !total_volume) return @@ -188,17 +188,23 @@ amount = min(min(amount, src.total_volume), R.maximum_volume-R.total_volume) var/part = amount / src.total_volume var/trans_data = null + var/list/transferred = list() for(var/reagent in cached_reagents) var/datum/reagent/T = reagent var/transfer_amount = T.volume * part if(preserve_data) trans_data = copy_data(T) - + transferred += "[T] - [transfer_amount]" R.add_reagent(T.type, transfer_amount * multiplier, trans_data, chem_temp, T.purity, pH, no_react = TRUE, ignore_pH = TRUE) //we only handle reaction after every reagent has been transfered. - remove_reagent(T.type, transfer_amount, ignore_pH = TRUE) + if(log && amount > 0) + var/atom/us = my_atom + var/atom/them = R.my_atom + var/location_string = "FROM [(us && "[us] ([REF(us)]) [COORD(us)]") || "NULL"] TO [(them && "[them] ([REF(them)]) [COORD(them)]") || "NULL"]" + log_reagent_transfer("[location_string] - [key_name(usr)][istext(log) ? " - [log]" : ""]: trans_to with arguments [target] [amount] [multiplier] [preserve_data] [no_react] and reagents [english_list(transferred)]") + update_total() R.update_total() if(!no_react) @@ -237,7 +243,7 @@ src.handle_reactions() return amount -/datum/reagents/proc/trans_id_to(obj/target, reagent, amount=1, preserve_data=1)//Not sure why this proc didn't exist before. It does now! /N +/datum/reagents/proc/trans_id_to(obj/target, reagent, amount = 1, preserve_data = TRUE, log = FALSE)//Not sure why this proc didn't exist before. It does now! /N var/list/cached_reagents = reagent_list if (!target) return @@ -257,8 +263,12 @@ if(preserve_data) trans_data = current_reagent.data R.add_reagent(current_reagent.type, amount, trans_data, chem_temp, current_reagent.purity, pH, no_react = TRUE) - remove_reagent(current_reagent.type, amount, 1) + if(log && amount > 0) + var/atom/us = my_atom + var/atom/them = R.my_atom + var/location_string = "FROM [(us && "[us] ([REF(us)]) [COORD(us)]") || "NULL"] TO [(them && "[them] ([REF(them)]) [COORD(them)]") || "NULL"]" + log_reagent_transfer("[location_string] - [key_name(usr)][istext(log) ? " - [log]" : ""]: trans_id_to with arguments [target] [reagent] [amount] [preserve_data]") break src.update_total() diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 9c877fc053..b779ad5d44 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -148,8 +148,8 @@ /obj/machinery/chem_master/on_deconstruction() var/atom/A = drop_location() - beaker.forceMove(A) - bottle.forceMove(A) + beaker?.forceMove(A) + bottle?.forceMove(A) return ..() /obj/machinery/chem_master/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 62a8d97b2d..103f7cb28f 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -887,7 +887,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/barefoot/on_mob_life(mob/living/carbon/M) if(ishuman(M)) //Barefoot causes the imbiber to quickly regenerate brute trauma if they're not wearing shoes. var/mob/living/carbon/human/H = M - if(!H.shoes) + if(!H.shoes || !(H.shoes.body_parts_covered & FEET)) H.adjustBruteLoss(-3, 0) . = 1 return ..() || . diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index ad3a2c90a4..a32cb94401 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -153,20 +153,37 @@ color = "#669900" // rgb: 102, 153, 0 toxpwr = 0.5 taste_description = "death" + var/fakedeath_active = FALSE pH = 13 /datum/reagent/toxin/zombiepowder/on_mob_metabolize(mob/living/L) ..() - L.fakedeath(type) + ADD_TRAIT(L, TRAIT_FAKEDEATH, type) /datum/reagent/toxin/zombiepowder/on_mob_end_metabolize(mob/living/L) L.cure_fakedeath(type) ..() -/datum/reagent/toxin/zombiepowder/on_mob_life(mob/living/carbon/M) - M.adjustOxyLoss(0.5*REM, 0) +/datum/reagent/toxin/zombiepowder/reaction_mob(mob/living/L, method=TOUCH, reac_volume) + L.adjustOxyLoss(0.5*REM, 0) + if(method == INGEST) + fakedeath_active = TRUE + L.fakedeath(type) + +/datum/reagent/toxin/zombiepowder/on_mob_life(mob/living/M) ..() - . = 1 + if(fakedeath_active) + return TRUE + switch(current_cycle) + if(1 to 5) + M.confused += 1 + M.drowsyness += 1 + M.slurring += 3 + if(5 to 8) + M.adjustStaminaLoss(40, 0) + if(9 to INFINITY) + fakedeath_active = TRUE + M.fakedeath(type) /datum/reagent/toxin/ghoulpowder name = "Ghoul Powder" diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index 2890d02d09..eb473950d5 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -70,6 +70,14 @@ required_other = TRUE required_container = /obj/item/slime_extract/green +/datum/chemical_reaction/slime/slimemammal + name = "Mammal Mutation Toxin" + id = /datum/reagent/mutationtoxin/mammal + results = list(/datum/reagent/mutationtoxin/mammal = 1) + required_reagents = list(/datum/reagent/water = 1) + required_other = TRUE + required_container = /obj/item/slime_extract/green + //Metal /datum/chemical_reaction/slime/slimemetal name = "Slime Metal" @@ -565,9 +573,16 @@ required_other = TRUE /datum/chemical_reaction/slime/slimestop/on_reaction(datum/reagents/holder) + sleep(50) + var/obj/item/slime_extract/sepia/extract = holder.my_atom var/turf/T = get_turf(holder.my_atom) - var/list/M = list(get_mob_by_key(holder.my_atom.fingerprintslast)) - new /obj/effect/timestop(T, null, null, M) + new /obj/effect/timestop(T, null, null, null) + if(istype(extract)) + if(extract.Uses > 0) + var/mob/lastheld = get_mob_by_key(holder.my_atom.fingerprintslast) + if(lastheld && !lastheld.equip_to_slot_if_possible(extract, SLOT_HANDS, disable_warning = TRUE)) + extract.forceMove(get_turf(lastheld)) + ..() /datum/chemical_reaction/slime/slimecamera diff --git a/code/modules/reagents/chemistry/recipes/special.dm b/code/modules/reagents/chemistry/recipes/special.dm index 5ad9728b22..cc63a8c692 100644 --- a/code/modules/reagents/chemistry/recipes/special.dm +++ b/code/modules/reagents/chemistry/recipes/special.dm @@ -186,6 +186,7 @@ GLOBAL_LIST_INIT(food_reagents, build_reagents_to_food()) //reagentid = related var/datum/chemical_reaction/recipe = get_chemical_reaction(recipe_id) if(!recipe) info = "This recipe is illegible." + return var/list/dat = list("