diff --git a/README.md b/README.md index 2a1ffe65ec..0ecf4c5b01 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,28 @@ ## 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) +[![Build Status](https://api.travis-ci.org/Citadel-Station-13/Citadel-Station-13.png)](https://travis-ci.org/Citadel-Station-13/Citadel-Station-13) +[![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") -[![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a) - -[![Build Status](https://api.travis-ci.org/Citadel-Station-13/Citadel-Station-13.png)](https://travis-ci.org/Citadel-Station-13/Citadel-Station-13) [![Krihelimeter](http://www.krihelinator.xyz/badge/Citadel-Station-13/Citadel-Station-13)](http://www.krihelinator.xyz) - -[![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") +[![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) [![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a) **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). - +* **Website:** +* **Code:** +* **Wiki:** +* **Codedocs:** +* **/tg/station Discord:** +* **Coderbus Discord:** +* ~~**IRC:** ~~ (dead) + **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) +* **Website:** +* **Code:** +* **Wiki:** +* **Forums:** +* **Ban Appeals:** +* **Discord:** ## DOWNLOADING @@ -162,13 +164,12 @@ All code before [commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 a See LICENSE and GPLv3.txt for more details. +The TGS3 API is licensed as a subproject under the MIT license. + +See the footers of code/\_\_DEFINES/server\_tools.dm, code/modules/server\_tools/st\_commands.dm, and code/modules/server\_tools/st\_inteface.dm for the MIT license. + tgui clientside is licensed as a subproject under the MIT license. Font Awesome font files, used by tgui, are licensed under the SIL Open Font License v1.1 tgui assets are licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). -The TGS3 API is licensed as a subproject under the MIT license. -See tgui/LICENSE.md for the MIT license. -See tgui/assets/fonts/SIL-OFL-1.1-LICENSE.md for the SIL Open Font License. -See the footers of code/\_\_DEFINES/server\_tools.dm, code/modules/server\_tools/st\_commands.dm, and code/modules/server\_tools/st\_inteface.dm for the MIT license. - -All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](http://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated. +All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](https://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated. diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm new file mode 100644 index 0000000000..f590af752b --- /dev/null +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm @@ -0,0 +1,1721 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aa" = ( +/turf/template_noop, +/area/template_noop) +"ab" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface) +"ac" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"ad" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/structure/closet/crate/grave/lead_researcher, +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/effect/mob_spawn/human/skeleton, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ae" = ( +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"af" = ( +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ag" = ( +/obj/effect/decal/cleanable/vomit, +/obj/item/shovel, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ah" = ( +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ai" = ( +/obj/effect/decal/cleanable/blood/tracks{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aj" = ( +/obj/effect/decal/cleanable/blood/tracks{ + dir = 4 + }, +/obj/item/paper/fluff/ruins/elephant_graveyard/final_message, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ak" = ( +/turf/open/floor/plating/asteroid/basalt/wasteland{ + icon_state = "wasteland_dug" + }, +/area/ruin/unpowered/elephant_graveyard) +"al" = ( +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"am" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"an" = ( +/obj/item/reagent_containers/food/snacks/deadmouse, +/obj/item/assembly/mousetrap, +/turf/open/floor/plating/asteroid/basalt/wasteland{ + icon_state = "wasteland_dug" + }, +/area/ruin/unpowered/elephant_graveyard) +"ao" = ( +/obj/structure/statue/bone/skull/half, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ap" = ( +/obj/structure/statue/bone/skull/half{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aq" = ( +/obj/item/reagent_containers/glass/bottle/frostoil{ + desc = "A small bottle. Contains cold sauce. There's a label on here: APPLY ON SEVERE BURNS."; + volume = 10 + }, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ar" = ( +/obj/structure/flora/rock, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"as" = ( +/obj/structure/flora/rock, +/obj/item/pickaxe{ + layer = 2.5; + pixel_x = -8; + pixel_y = 5 + }, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"at" = ( +/turf/closed/mineral/strong/wasteland, +/area/lavaland/surface) +"au" = ( +/obj/structure/table, +/obj/item/t_scanner/adv_mining_scanner/lesser, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"av" = ( +/obj/structure/barricade/wooden/crude, +/obj/structure/barricade/wooden, +/obj/effect/decal/cleanable/blood/splatter, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aw" = ( +/obj/structure/table, +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/rnd_notes, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ax" = ( +/obj/structure/statue/bone/rib{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ay" = ( +/obj/structure/statue/bone/rib, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"az" = ( +/obj/structure/table, +/obj/item/pen, +/obj/item/pen, +/obj/item/pen, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aA" = ( +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"aB" = ( +/obj/item/chair, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aC" = ( +/obj/effect/decal/remains/human, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aD" = ( +/obj/structure/table, +/obj/item/reagent_containers/glass/bottle/plasma{ + volume = 25 + }, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aE" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aF" = ( +/obj/structure/table, +/obj/machinery/power/floodlight, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aG" = ( +/obj/structure/table, +/obj/effect/spawner/lootdrop/glowstick, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aH" = ( +/turf/closed/wall/mineral/titanium, +/area/ruin/powered/graveyard_shuttle) +"aI" = ( +/obj/effect/spawner/structure/window/shuttle, +/obj/structure/grille, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/powered/graveyard_shuttle) +"aJ" = ( +/obj/structure/table, +/obj/item/clipboard, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aK" = ( +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aL" = ( +/obj/structure/table, +/obj/item/paper_bin, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aM" = ( +/obj/structure/table, +/obj/item/clothing/gloves/color/black, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aN" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/ruin/powered/graveyard_shuttle) +"aO" = ( +/obj/effect/decal/cleanable/glass, +/obj/machinery/computer, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"aP" = ( +/obj/structure/bed, +/obj/item/flashlight/lantern, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aQ" = ( +/obj/machinery/power/floodlight, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aR" = ( +/obj/structure/table, +/obj/item/taperecorder, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aS" = ( +/obj/structure/table, +/obj/item/tape/random, +/obj/item/tape/random, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aT" = ( +/obj/structure/closet/crate/bin, +/obj/item/trash/candle, +/obj/item/trash/can, +/obj/item/trash/can, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aU" = ( +/obj/structure/bed, +/obj/item/bedsheet/brown, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aV" = ( +/obj/structure/bed, +/obj/item/bedsheet/brown, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aW" = ( +/obj/structure/filingcabinet/chestdrawer, +/obj/item/clothing/mask/gas/explorer/folded, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"aX" = ( +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aY" = ( +/obj/structure/sign/warning/nosmoking/circle, +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"aZ" = ( +/obj/item/organ/brain, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ba" = ( +/obj/structure/headpike/bone, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bb" = ( +/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bc" = ( +/obj/structure/sign/poster/ripped, +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"bd" = ( +/obj/item/organ/heart, +/obj/item/organ/eyes, +/obj/item/organ/ears, +/obj/effect/decal/cleanable/blood/gibs/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"be" = ( +/obj/item/organ/lungs, +/obj/item/organ/liver, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bf" = ( +/turf/closed/mineral/strong/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bg" = ( +/obj/structure/sign/warning/securearea, +/turf/closed/wall/mineral/titanium, +/area/ruin/powered/graveyard_shuttle) +"bh" = ( +/obj/effect/decal/cleanable/oil, +/obj/structure/chair/office/light, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bi" = ( +/obj/effect/turf_decal/delivery/white, +/turf/open/floor/circuit/off, +/area/ruin/powered/graveyard_shuttle) +"bj" = ( +/obj/structure/barricade/wooden, +/obj/structure/mineral_door/wood, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bk" = ( +/obj/item/kitchen/knife/combat/bone, +/obj/item/organ/tongue, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bl" = ( +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bm" = ( +/obj/structure/closet/wardrobe/curator, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bn" = ( +/obj/structure/sink/oil_well, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bo" = ( +/obj/item/stack/medical/gauze/improvised, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bp" = ( +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bq" = ( +/obj/machinery/iv_drip, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"br" = ( +/obj/structure/sign/warning/nosmoking/circle, +/turf/closed/wall/mineral/titanium, +/area/ruin/powered/graveyard_shuttle) +"bs" = ( +/obj/structure/fence/door, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bt" = ( +/obj/structure/table, +/turf/closed/mineral/strong/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bu" = ( +/obj/structure/bed, +/obj/item/trash/pistachios, +/obj/item/trash/chips, +/obj/item/bedsheet/brown, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bv" = ( +/obj/effect/decal/remains/human, +/obj/item/clothing/under/misc/overalls, +/obj/item/clothing/mask/bandana/green, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bw" = ( +/obj/structure/rack, +/obj/item/shovel, +/obj/item/wrench, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bx" = ( +/obj/item/reagent_containers/food/snacks/deadmouse, +/obj/item/assembly/mousetrap, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"by" = ( +/obj/structure/closet/emcloset, +/obj/item/light/bulb, +/obj/effect/turf_decal/box/white, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"bz" = ( +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/mutiny, +/obj/item/cigbutt, +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bA" = ( +/obj/machinery/suit_storage_unit/mining/eva, +/obj/effect/turf_decal/box/white, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"bB" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bC" = ( +/obj/structure/barricade/sandbags, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bD" = ( +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"bE" = ( +/obj/structure/shuttle/engine/heater, +/obj/structure/window{ + dir = 1 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"bF" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"bG" = ( +/obj/effect/decal/remains/human, +/obj/item/tank/internals/emergency_oxygen/empty, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bH" = ( +/obj/item/paper/fluff/ruins/elephant_graveyard, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface) +"bI" = ( +/obj/structure/shuttle/engine/propulsion, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/powered/graveyard_shuttle) +"bJ" = ( +/obj/structure/sign/warning/xeno_mining, +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"bK" = ( +/obj/structure/sign/warning/explosives, +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"bL" = ( +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/effect/decal/cleanable/blood/splatter, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bM" = ( +/obj/item/storage/fancy/cigarettes/cigpack_mindbreaker, +/obj/structure/closet/crate/grave, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bN" = ( +/obj/structure/sign/warning/securearea, +/obj/structure/sign/warning/securearea, +/turf/closed/mineral/strong/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bO" = ( +/obj/item/paper/fluff/ruins/elephant_graveyard, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bP" = ( +/obj/structure/barricade/wooden/crude, +/obj/item/paper/fluff/ruins/elephant_graveyard, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"bQ" = ( +/obj/structure/filingcabinet/chestdrawer, +/obj/effect/decal/cleanable/cobweb, +/obj/item/paper/fluff/ruins/elephant_graveyard/hypothesis, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bR" = ( +/obj/effect/decal/cleanable/generic, +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bS" = ( +/obj/effect/decal/cleanable/oil/slippery, +/obj/machinery/rnd/destructive_analyzer, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bT" = ( +/obj/structure/barricade/wooden, +/obj/item/paper/fluff/ruins/elephant_graveyard, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bU" = ( +/obj/item/light/bulb/broken, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bV" = ( +/obj/effect/decal/cleanable/dirt, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"bW" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/door/airlock/shuttle{ + name = "archaeology shuttle airlock" + }, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"bX" = ( +/obj/effect/decal/remains/human, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/clothing/head/fedora/curator, +/obj/item/clothing/suit/curator, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bY" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bZ" = ( +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface) +"ca" = ( +/obj/structure/table, +/obj/item/storage/firstaid/o2, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cb" = ( +/obj/machinery/power/port_gen/pacman, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cc" = ( +/obj/effect/decal/remains/human, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cd" = ( +/obj/item/trash/can, +/obj/structure/bedsheetbin/empty, +/obj/structure/table, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ce" = ( +/obj/structure/stone_tile/slab/cracked, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cf" = ( +/obj/structure/bed, +/obj/item/wirecutters, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cg" = ( +/obj/structure/stone_tile/center/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ch" = ( +/obj/effect/decal/remains/human, +/obj/item/restraints/handcuffs/cable/zipties/used, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ci" = ( +/obj/structure/stone_tile/surrounding_tile, +/turf/open/floor/plating/asteroid/basalt/wasteland{ + icon_state = "wasteland_dug" + }, +/area/ruin/unpowered/elephant_graveyard) +"cj" = ( +/obj/structure/stone_tile/block/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ck" = ( +/obj/structure/reagent_dispensers/water_cooler, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cl" = ( +/obj/structure/closet/crate/grave, +/obj/effect/mob_spawn/human/skeleton, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cm" = ( +/obj/structure/table/optable, +/obj/item/storage/backpack/explorer, +/obj/item/reagent_containers/food/drinks/soda_cans/cola, +/obj/item/restraints/handcuffs/cable/zipties/used, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"cn" = ( +/obj/structure/stone_tile/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"co" = ( +/obj/effect/decal/cleanable/blood/drip, +/obj/structure/stone_tile/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cq" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cr" = ( +/obj/structure/bonfire/prelit, +/obj/effect/decal/cleanable/ash, +/obj/item/organ/tail/lizard, +/obj/effect/decal/cleanable/blood/old, +/obj/structure/stone_tile/slab/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cs" = ( +/obj/structure/ore_box, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ct" = ( +/obj/structure/stone_tile, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cu" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cv" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"cw" = ( +/obj/structure/closet/crate/grave, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/mob_spawn/human/skeleton, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cx" = ( +/obj/item/light/bulb/broken, +/obj/effect/turf_decal/caution/stand_clear/white, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"cz" = ( +/obj/structure/stone_tile, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) + +(1,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(2,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +at +ab +ab +ab +ac +ac +ac +ac +bf +ac +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(3,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +ab +ab +bf +bf +bf +bf +bf +ac +ac +ac +ac +bf +bf +bf +ac +ac +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +"} +(4,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +ab +ab +bf +bf +aT +bR +bf +bf +bf +ac +bf +bf +bf +bf +bf +bf +bf +ac +ac +ab +ab +aa +aa +aa +aa +aa +aa +aa +"} +(5,1,1) = {" +aa +aa +aa +aa +aa +ab +ab +ab +bf +bf +bf +bz +aK +bY +ae +bf +bf +bf +cs +aE +bJ +bf +bf +bf +ac +ac +ac +ab +ab +ab +aa +aa +aa +aa +aa +"} +(6,1,1) = {" +aa +aa +aa +aa +ab +ab +bf +bf +bf +bf +aA +bc +aA +aY +ae +bv +ae +cl +ae +ae +aC +bs +bO +ae +ae +ac +ac +ac +ac +ab +ab +ab +aa +aa +aa +"} +(7,1,1) = {" +aa +aa +aa +aa +ab +bf +bf +bf +aq +al +al +al +aQ +ae +ae +ak +ae +ae +ae +ae +bK +bf +bf +bf +ae +ac +ac +ac +ac +ac +ac +ab +ab +aa +aa +"} +(8,1,1) = {" +aa +aa +ab +ab +ab +bf +bf +al +al +ar +ae +ae +ae +ar +aZ +ae +ba +ae +ba +ae +ae +ae +ae +bf +ae +ac +ac +ac +ac +ac +ac +ac +ab +ab +aa +"} +(9,1,1) = {" +aa +ab +ab +bf +bf +bf +al +al +ak +ae +aE +ae +ae +ae +ba +ae +af +ae +ae +ae +ba +ae +ak +bf +ae +ae +ac +ac +ac +ac +ac +ac +ac +ac +aa +"} +(10,1,1) = {" +ab +ab +bf +bf +bf +al +am +ae +ae +ae +ae +cl +ae +ae +ae +co +bd +bk +ae +ae +ae +ae +aE +bf +bf +ae +ae +ac +ac +ac +ac +bG +bM +ac +ac +"} +(11,1,1) = {" +at +bf +bf +bf +bf +al +ae +ae +ao +ae +ax +ax +ax +ax +ae +ae +be +cr +ae +cz +ae +ae +bn +cw +bf +bf +bB +ac +ac +ac +ac +bL +ae +ae +ac +"} +(12,1,1) = {" +at +bf +bf +bf +bf +al +cl +ae +ae +ae +ae +ci +cj +ce +ae +cj +ae +cq +ae +ae +cu +ae +ae +ae +bf +bf +bC +ac +ac +ac +ac +ac +ac +bD +ac +"} +(13,1,1) = {" +bf +ad +ae +bf +cl +al +ae +ae +ae +ae +cg +ae +ak +ak +cn +ae +cq +ae +ct +ar +ae +cl +ae +ae +bf +bf +ae +ac +ac +ac +ac +ac +ac +ae +ac +"} +(14,1,1) = {" +bf +aj +ae +bf +ae +al +aE +ae +ap +ae +ay +ay +ay +ay +ae +ae +ak +ae +ae +bn +ae +ae +aE +aQ +bf +cl +bB +ae +ac +ac +ac +ac +ac +ae +ac +"} +(15,1,1) = {" +bf +ai +ag +bf +an +al +ae +ae +ae +ae +ae +ae +ae +ae +ae +ae +ae +cw +ae +ae +ae +ae +ae +al +bf +ac +ae +ae +bB +ac +ac +ac +ac +bD +ac +"} +(16,1,1) = {" +bf +ai +bf +bf +bf +al +al +al +ae +ae +aE +ae +ar +ae +ba +ae +ae +ae +ae +ae +ba +ae +ae +al +bf +ac +ac +ae +ae +bB +ac +ac +ac +bB +bP +"} +(17,1,1) = {" +bf +ae +af +bf +bf +aE +bf +al +as +au +az +aG +aM +aR +ae +ae +ba +ae +ba +ae +ae +aE +cl +al +bf +bf +ac +ac +ae +bD +ac +ac +ac +bF +bT +"} +(18,1,1) = {" +at +bf +ah +bf +bf +af +bf +ae +ae +aw +aB +ae +ae +aS +ae +ae +aE +ae +ae +ae +ae +ae +ae +al +cb +bf +ac +ac +ac +ae +bB +bB +bF +bB +bP +"} +(19,1,1) = {" +ab +bf +af +av +af +ae +bf +ae +bt +aD +ch +ae +ae +ca +ae +al +al +al +al +al +al +al +al +bx +bf +bf +ac +ac +ac +ac +bF +bB +bV +ac +ac +"} +(20,1,1) = {" +aa +at +bf +bf +bf +bf +bf +bj +bf +aF +aJ +aL +al +al +al +bw +bf +ac +bm +ae +bn +bf +bf +bf +bf +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +"} +(21,1,1) = {" +aa +aa +ab +ac +ac +bf +aU +aE +bf +bf +bf +bf +ck +aX +ae +bf +bf +bf +bf +bf +bf +bf +bf +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ab +ab +"} +(22,1,1) = {" +aa +aa +ab +ab +ac +bf +aU +ae +bl +cd +bf +bf +bf +bN +ae +bf +bf +bf +bf +ac +ac +ac +ac +ac +ac +ac +ac +ab +ab +ab +ab +ab +ab +bZ +bZ +"} +(23,1,1) = {" +aa +aa +aa +ab +ab +bf +aV +bl +aE +bu +bf +bf +bf +bf +bb +bf +bf +bf +bf +ab +ab +ab +ab +ab +ab +ab +ab +bZ +bZ +bZ +bH +bZ +bZ +bZ +ab +"} +(24,1,1) = {" +aa +aa +aa +aa +ab +at +aP +bo +cc +cf +bf +aH +aH +bg +bW +bg +aH +aH +aH +bH +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +ab +ab +ab +"} +(25,1,1) = {" +aa +aa +aa +aa +aa +at +bf +bf +bf +bf +aH +aN +bQ +bh +cv +bU +by +aH +aH +bI +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +ab +ab +ab +ab +ab +ab +"} +(26,1,1) = {" +aa +aa +aa +aa +aa +ab +ab +ab +ab +ab +aI +aO +bX +bi +bp +bi +cx +bE +aH +bI +bZ +bZ +bZ +bZ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(27,1,1) = {" +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +aH +aN +aW +cm +bq +bS +bA +aH +aH +bI +bZ +bZ +bZ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +"} +(28,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +aH +aH +aH +br +aH +aH +aH +aH +bZ +bZ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +"} +(29,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +"} diff --git a/_maps/RandomRuins/SpaceRuins/spacediner.dmm b/_maps/RandomRuins/SpaceRuins/spacediner.dmm new file mode 100644 index 0000000000..21670da9e4 --- /dev/null +++ b/_maps/RandomRuins/SpaceRuins/spacediner.dmm @@ -0,0 +1,2918 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aa" = ( +/turf/template_noop, +/area/template_noop) +"ab" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ac" = ( +/obj/machinery/door/airlock/external/glass{ + name = "Shuttle Dock" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ad" = ( +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ae" = ( +/obj/structure/lattice, +/turf/open/space/basic, +/area/space/nearstation) +"af" = ( +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"ag" = ( +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"ah" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/external/glass{ + name = "Shuttle Dock" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ai" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 1 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aj" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ak" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"al" = ( +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"am" = ( +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/power/solar, +/turf/open/floor/plasteel/solarpanel, +/area/ruin/space/diner/solars) +"an" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ao" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ap" = ( +/obj/structure/sign/poster/official/pda_ad600{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aq" = ( +/obj/structure/sign/poster/official/nanotrasen_logo{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ar" = ( +/obj/structure/sign/poster/official/cohiba_robusto_ad{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"as" = ( +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"at" = ( +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/power/solar, +/turf/open/floor/plasteel/solarpanel, +/area/ruin/space/diner/solars) +"au" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"av" = ( +/turf/open/floor/plating/airless, +/area/ruin/space/diner) +"aw" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 4 + }, +/turf/open/floor/plating/airless, +/area/ruin/space/diner) +"ax" = ( +/turf/closed/wall/r_wall, +/area/ruin/space/diner) +"ay" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/airalarm/all_access{ + dir = 4; + icon_state = "alarm0"; + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"az" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/vending/coffee, +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aA" = ( +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/ruin/space/diner/interior) +"aB" = ( +/obj/structure/reagent_dispensers/beerkeg, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aC" = ( +/obj/structure/table/reinforced, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aD" = ( +/obj/structure/kitchenspike, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aE" = ( +/obj/structure/closet/crate, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aF" = ( +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/structure/closet/crate/freezer, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aG" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aH" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aI" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aJ" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aK" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aL" = ( +/turf/open/floor/engine/airless, +/area/ruin/space/diner) +"aM" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"aN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aO" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/vending/cola/red, +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aP" = ( +/obj/machinery/atmospherics/components/unary/tank/air{ + dir = 1 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aQ" = ( +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 10 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aR" = ( +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/ruin/space/diner/interior) +"aS" = ( +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aT" = ( +/obj/structure/cable, +/obj/machinery/power/solar, +/turf/open/floor/plasteel/solarpanel, +/area/ruin/space/diner/solars) +"aU" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aV" = ( +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Fore Docking Area" + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aW" = ( +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Fore Docking Area" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aX" = ( +/obj/machinery/vending/boozeomat/pubby_maint, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"aY" = ( +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aZ" = ( +/obj/structure/closet/crate/bin, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ba" = ( +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bb" = ( +/obj/machinery/gibber, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bc" = ( +/turf/closed/wall/r_wall/rust, +/area/ruin/space/diner/interior) +"bd" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Fore Pod Bay" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/firedoor/closed, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"be" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel/stairs/old, +/area/ruin/space/diner/interior) +"bf" = ( +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"bg" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"bh" = ( +/obj/machinery/light/small/broken, +/turf/open/floor/engine/airless, +/area/ruin/space/diner) +"bi" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/button{ + pixel_y = -24 + }, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"bj" = ( +/obj/effect/spawner/structure/window/hollow/reinforced, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bk" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bl" = ( +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/chem_dispenser/drinks/beer, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bm" = ( +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/chem_dispenser/drinks, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bn" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/vending/dinnerware, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bo" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/secure_closet/freezer/kitchen{ + req_access = null; + req_access_txt = "200" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bp" = ( +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/item/reagent_containers/food/condiment/flour, +/obj/item/kitchen/rollingpin, +/obj/item/reagent_containers/food/condiment/rice{ + pixel_x = -8; + pixel_y = 8 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bq" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/processor, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"br" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/firealarm{ + pixel_y = 24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bs" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sink/kitchen{ + pixel_y = 28 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bt" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/grill, +/obj/machinery/light/small/broken{ + icon_state = "bulb-broken"; + dir = 1 + }, +/obj/machinery/power/apc/highcap/five_k{ + name = "Space Diner APC"; + pixel_y = 24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bu" = ( +/obj/machinery/deepfryer, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bv" = ( +/obj/effect/decal/cleanable/cobweb{ + icon_state = "cobweb2" + }, +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bw" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"bx" = ( +/obj/structure/toilet/secret/low_loot{ + icon_state = "toilet00"; + dir = 4 + }, +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/window/eastright, +/turf/open/floor/mineral/titanium/white, +/area/ruin/space/diner/interior) +"by" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/contraband/rebels_unite{ + pixel_y = 32 + }, +/obj/item/reagent_containers/food/urinalcake, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bz" = ( +/obj/structure/urinal{ + pixel_y = 28 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bA" = ( +/obj/effect/decal/cleanable/cobweb{ + icon_state = "cobweb2" + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/structure/closet/crate/bin, +/obj/machinery/airalarm/all_access{ + dir = 8; + icon_state = "alarm0"; + pixel_x = 24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bB" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 8 + }, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bC" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/middle, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bD" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 4 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bE" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bF" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/manifold/general/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bG" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bH" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bI" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/grunge/abandoned{ + name = "Staff Entrance" + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bJ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/manifold/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bK" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 10 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bL" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bM" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/secure_closet/freezer/meat{ + req_access_txt = "200" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bO" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"bP" = ( +/obj/structure/toilet/secret/low_loot{ + icon_state = "toilet00"; + dir = 4 + }, +/obj/structure/window/reinforced/spawner/north, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/window/eastright, +/turf/open/floor/mineral/titanium/white, +/area/ruin/space/diner/interior) +"bQ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 6 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bR" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bS" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/sign/poster/official/cleanliness{ + pixel_x = 32 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bT" = ( +/obj/structure/rack, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"bU" = ( +/obj/structure/table, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"bV" = ( +/obj/structure/table, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"bW" = ( +/obj/structure/table, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/item/storage/toolbox/electrical, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"bX" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 1 + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bY" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bZ" = ( +/obj/machinery/icecream_vat, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/airalarm/all_access{ + dir = 4; + icon_state = "alarm0"; + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ca" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/manifold/general/hidden{ + icon_state = "manifold-2"; + dir = 8 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cb" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cc" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 10 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cd" = ( +/obj/structure/table/reinforced, +/obj/machinery/microwave{ + pixel_y = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ce" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cf" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/mirror{ + icon_state = "mirror_broke"; + pixel_x = 24 + }, +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cg" = ( +/obj/structure/sign/warning/vacuum/external{ + pixel_x = -32 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"ch" = ( +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"ci" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cj" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ck" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/holopad, +/obj/effect/turf_decal/bot, +/obj/item/radio/intercom{ + pixel_x = 26 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cl" = ( +/obj/structure/grille/broken, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"cm" = ( +/obj/machinery/light{ + dir = 8; + light_color = "#e8eaff" + }, +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/snacks/stewedsoymeat, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cn" = ( +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"co" = ( +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/item/trash/plate, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cp" = ( +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/drinks/drinkingglass, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cq" = ( +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/condiment/saltshaker{ + pixel_x = 4; + pixel_y = 2 + }, +/obj/item/reagent_containers/food/condiment/peppermill{ + pixel_x = -4; + pixel_y = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cr" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/obj/structure/frame, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cs" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/table/wood/bar, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ct" = ( +/obj/machinery/light{ + dir = 4; + light_color = "#e8eaff" + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/table/wood/bar, +/obj/structure/window/reinforced/spawner, +/obj/structure/window/reinforced/spawner/west, +/obj/machinery/dish_drive, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cu" = ( +/obj/structure/sign/barsign, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"cv" = ( +/obj/machinery/door/airlock/grunge/abandoned{ + name = "Restrooms" + }, +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cw" = ( +/obj/machinery/airalarm/all_access{ + dir = 1; + icon_state = "alarm0"; + pixel_x = 0; + pixel_y = -24 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cx" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/machinery/airalarm/all_access{ + dir = 4; + icon_state = "alarm0"; + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cy" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cz" = ( +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/obj/item/beacon, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cA" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cB" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/public/glass{ + name = "Teleporter Room" + }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cC" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cD" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/machinery/atmospherics/pipe/manifold/general/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cE" = ( +/obj/structure/chair/stool/bar, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cF" = ( +/obj/structure/chair/stool/bar, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cG" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cH" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cI" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/computer/slot_machine, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cJ" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cK" = ( +/obj/structure/table/wood, +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/drinks/drinkingglass, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cL" = ( +/obj/structure/table/wood, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/trash/plate, +/obj/item/kitchen/fork, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cM" = ( +/obj/machinery/light/broken{ + icon_state = "tube-broken"; + dir = 1 + }, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/chair, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cN" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cO" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/sign/departments/restroom{ + pixel_y = 32 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cP" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cQ" = ( +/obj/structure/sign/warning/vacuum/external{ + pixel_x = 32; + pixel_y = 32 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"cS" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 1 + }, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"cT" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate/bin, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cU" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cV" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/official/report_crimes{ + pixel_y = 32 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cW" = ( +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Diner" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cX" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cY" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cZ" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"da" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"db" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/manifold/general/hidden, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dc" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dd" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 9 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"de" = ( +/obj/machinery/door/airlock/external{ + name = "Mining Shuttle Dock" + }, +/obj/machinery/door/firedoor, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"df" = ( +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dg" = ( +/obj/machinery/door/airlock/external/glass, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dh" = ( +/obj/machinery/teleport/hub, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"di" = ( +/obj/machinery/light/small/broken, +/obj/machinery/teleport/station, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"dj" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/computer/teleporter{ + icon_state = "computer"; + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"dk" = ( +/obj/structure/lattice/catwalk, +/turf/template_noop, +/area/space/nearstation) +"dm" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end, +/obj/structure/cable, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dn" = ( +/obj/machinery/light/small, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"do" = ( +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Diner" + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dp" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dq" = ( +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dr" = ( +/obj/structure/sign/mining{ + pixel_x = 32 + }, +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/rag, +/obj/item/kitchen/fork, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"ds" = ( +/obj/structure/cable, +/obj/machinery/power/solar_control{ + icon_state = "computer"; + dir = 4 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dt" = ( +/obj/structure/sign/poster/ripped{ + pixel_x = 32 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dv" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 4 + }, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dx" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/manifold/general/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dy" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/light/broken{ + icon_state = "tube-broken"; + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dz" = ( +/obj/structure/chair, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dA" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/chair, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dB" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dC" = ( +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/chair{ + icon_state = "chair_toppled"; + dir = 1 + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dD" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/snacks/sushi_rice, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dE" = ( +/obj/machinery/light/small/broken{ + icon_state = "bulb-broken"; + dir = 1 + }, +/turf/open/floor/engine/airless, +/area/ruin/space/diner) +"dF" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/button{ + pixel_y = 24 + }, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"dG" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/vending/cola/blue, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dH" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/trash/plate, +/obj/item/reagent_containers/food/condiment/pack/ketchup{ + pixel_x = -4 + }, +/obj/item/reagent_containers/food/condiment/pack/mustard{ + pixel_x = 4 + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dI" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/item/trash/plate, +/obj/item/reagent_containers/food/snacks/hotdog, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dJ" = ( +/obj/machinery/light, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dK" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/drinks/bottle/whiskey, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dL" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/trash/plate{ + pixel_y = -2 + }, +/obj/item/reagent_containers/food/snacks/burger/mcguffin, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dM" = ( +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/machinery/jukebox, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dN" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/kitchen/fork, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dO" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/trash/plate, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dP" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dQ" = ( +/obj/machinery/light, +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/drinks/bottle/vodka, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dR" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/drinks/coffee, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dS" = ( +/obj/item/storage/wallet/random, +/turf/open/floor/engine/airless, +/area/ruin/space/diner) +"dT" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"dU" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Aft Pod Bay" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/firedoor/closed, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dV" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/directional{ + icon_state = "hrwindow_spawner_directional"; + dir = 10 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dW" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/middle, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dX" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 4 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dY" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 8 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dZ" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/directional{ + icon_state = "hrwindow_spawner_directional"; + dir = 6 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ea" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/template_noop, +/area/space/nearstation) +"eb" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Aft Docking Area" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/firedoor/closed, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ec" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Aft Docking Area" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/firedoor/closed, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ed" = ( +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"ee" = ( +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"ef" = ( +/obj/machinery/light/small/broken{ + icon_state = "bulb-broken"; + dir = 1 + }, +/obj/machinery/vending/snack, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"eg" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 1 + }, +/turf/open/floor/plating/airless, +/area/ruin/space/diner) +"eh" = ( +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plating/airless, +/area/ruin/space/diner) +"ei" = ( +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"ej" = ( +/obj/structure/girder/reinforced, +/turf/open/floor/plating/airless, +/area/ruin/space/diner) + +(1,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(2,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(3,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(4,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(5,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +af +af +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(6,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +af +dk +dk +dk +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(7,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +af +av +ax +af +dk +dk +dk +af +ej +aa +aa +aa +aa +aa +aa +aa +aa +"} +(8,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +av +aL +aL +ag +ag +ag +dg +ag +ag +ag +af +aa +aa +aa +aa +aa +aa +aa +"} +(9,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +af +aL +aL +aL +aL +bB +bT +cg +ch +ch +dh +bB +av +af +aa +aa +aa +aa +aa +aa +"} +(10,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +av +aL +aL +aL +bh +bC +bU +ch +cy +ch +di +bC +dE +aL +af +aa +aa +aa +aa +aa +"} +(11,1,1) = {" +aa +aa +aa +aa +aa +af +aa +aw +aL +aL +aL +aL +bD +bV +ci +cz +ci +dj +dv +aL +dS +av +af +aa +aa +aa +aa +"} +(12,1,1) = {" +aa +aa +aa +aa +af +af +af +ax +aM +aM +aM +bi +ag +bW +ch +cA +ch +cw +ag +dF +dT +av +af +aa +aa +aa +aa +"} +(13,1,1) = {" +aa +aa +aa +ag +ai +an +ag +ag +ag +ag +bd +bj +ag +bX +cj +cB +cS +dm +ag +bj +dU +ag +ax +ax +ej +aa +aa +"} +(14,1,1) = {" +aa +aa +aa +ag +aj +aj +aj +ay +aj +aV +aj +aj +bE +aj +aj +cC +cT +aj +cx +aj +aj +eb +ed +ed +av +aa +aa +"} +(15,1,1) = {" +aa +aa +aa +ag +ak +ao +au +au +aN +aW +au +au +bF +bY +bY +cD +cU +au +dx +au +aN +ec +ee +eh +ed +af +aa +"} +(16,1,1) = {" +aa +ab +ab +ab +al +al +ag +az +aO +ag +ag +bc +bG +aj +ck +aj +bL +dn +ag +ag +ag +ag +ef +ei +af +aa +aa +"} +(17,1,1) = {" +aa +ac +ad +ah +al +ap +ag +ag +ag +ag +ae +ag +bH +ag +ag +ag +cV +aj +ag +af +af +ax +eg +av +aa +aa +aa +"} +(18,1,1) = {" +aa +ab +ab +ab +al +al +ag +aA +aP +aX +ag +ag +bI +ag +cl +ag +cW +do +ag +af +af +aa +aa +af +aa +aa +aa +"} +(19,1,1) = {" +aa +aa +af +ab +al +aq +ag +aB +aQ +aY +be +bk +bJ +ag +ag +ag +cX +cH +ag +ai +dV +aa +aa +af +aa +aa +aa +"} +(20,1,1) = {" +aa +ab +ab +ab +al +al +ag +aC +aR +aZ +ag +bl +bH +bZ +cm +cE +cX +cH +dy +dG +dW +aa +aa +af +aa +aa +aa +"} +(21,1,1) = {" +aa +ac +ad +ah +al +ar +ag +aD +aS +ba +ag +bm +bH +aj +cn +cF +cX +cH +dz +dH +dX +af +af +af +aa +aa +aa +"} +(22,1,1) = {" +aa +ab +ab +ab +al +as +ag +aE +aS +ba +bc +bn +bK +ca +co +cF +cY +dp +dA +dI +bw +ea +ea +ea +aa +aa +aa +"} +(23,1,1) = {" +aa +aa +aa +ag +ak +al +ag +aF +aS +bb +bc +bo +bL +cb +cp +cF +cX +cH +dq +dJ +ag +af +af +af +aa +aa +aa +"} +(24,1,1) = {" +aa +aa +aa +ag +ai +an +ag +ag +ag +bc +ag +bp +bL +cb +cq +cF +cX +cH +dz +dK +dY +aa +aa +af +aa +aa +aa +"} +(25,1,1) = {" +aa +aa +aa +aa +aa +aa +af +af +af +aa +ag +bq +bL +cc +cr +cG +cZ +cH +dz +dL +dW +aa +aa +aa +aa +aa +aa +"} +(26,1,1) = {" +aa +aa +aa +af +am +at +at +aG +aT +af +ag +br +bL +aj +cs +cH +da +cH +dq +dq +dW +aa +af +aa +aa +aa +aa +"} +(27,1,1) = {" +aa +aa +aa +aa +aa +aa +af +aH +af +aa +ag +bs +bL +aj +ct +cH +da +cH +dq +dM +dW +aa +aa +aa +aa +aa +aa +"} +(28,1,1) = {" +aa +aa +aa +af +am +at +at +aI +aT +af +ag +bt +bM +aj +cu +cI +da +cH +dz +dN +dW +aa +aa +aa +aa +aa +aa +"} +(29,1,1) = {" +aa +aa +aa +aa +aa +aa +af +aH +af +aa +bc +bu +bL +aj +ag +cJ +da +cH +dz +dO +dW +aa +aa +aa +af +aa +aa +"} +(30,1,1) = {" +aa +aa +aa +af +am +at +at +aI +aT +af +ag +bv +bN +cd +ag +cK +db +cH +dq +dq +dW +aa +aa +aa +aa +aa +aa +"} +(31,1,1) = {" +aa +aa +aa +aa +aa +aa +af +aH +af +af +bf +bw +bO +bw +bw +cL +dc +cH +dz +dP +dX +aa +aa +af +aa +aa +aa +"} +(32,1,1) = {" +aa +aa +aa +aa +af +am +at +aJ +aU +aU +bg +bx +bP +bP +bc +cM +da +cH +dz +dQ +ag +af +af +af +aa +aa +aa +"} +(33,1,1) = {" +aa +aa +aa +aa +aa +aa +af +aH +af +af +bc +by +bQ +ce +cv +cN +dd +dp +dB +dB +bw +ea +ea +aa +aa +aa +aa +"} +(34,1,1) = {" +aa +aa +aa +aa +aa +af +am +aK +aT +af +ag +bz +bR +bL +ag +cO +cX +dq +dC +dq +dY +af +af +aa +aa +aa +aa +"} +(35,1,1) = {" +aa +aa +aa +aa +aa +aa +af +af +af +aa +ag +bA +bS +cf +ag +cP +cX +dr +dD +dR +dW +aa +aa +aa +aa +aa +aa +"} +(36,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +ag +ag +ag +ag +ag +bc +de +ag +ag +ai +dZ +aa +aa +aa +aa +aa +aa +"} +(37,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +ag +aS +df +ds +ag +aa +aa +aa +aa +aa +aa +aa +aa +"} +(38,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +ag +cQ +aS +dt +ag +af +af +aa +aa +aa +aa +aa +aa +"} +(39,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +ag +dg +dg +ag +ag +aa +aa +aa +aa +aa +aa +aa +aa +"} +(40,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 879be286a3..776c3586c4 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -3993,8 +3993,6 @@ }, /obj/structure/closet/wardrobe/white, /obj/item/clothing/under/suit/waiter, -/obj/item/clothing/under/suit/waiter, -/obj/item/clothing/under/suit/waiter, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ahD" = ( @@ -4139,11 +4137,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/mixed, /obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/dress/skirt/purple, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, /obj/structure/sign/poster/official/fashion{ pixel_x = -32 }, @@ -4674,13 +4667,13 @@ /turf/open/floor/plating, /area/maintenance/fore/secondary) "aiB" = ( -/obj/machinery/vending/kink, /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/structure/sign/poster/official/fashion{ pixel_y = 32 }, +/obj/machinery/vending/autodrobe, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aiC" = ( @@ -10716,21 +10709,7 @@ /obj/structure/closet{ name = "Holodeck Outfits" }, -/obj/item/clothing/under/trek/Q, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/medsci/next, -/obj/item/clothing/under/trek/medsci/next, -/obj/item/clothing/under/trek/medsci/next, /obj/item/clothing/under/misc/blue_camo, -/obj/item/clothing/under/misc/blue_camo, -/obj/item/clothing/under/costume/gladiator, -/obj/item/clothing/under/costume/gladiator, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -18209,7 +18188,6 @@ /obj/structure/closet/wardrobe/white, /obj/item/clothing/suit/ghost_sheet, /obj/item/clothing/suit/ghost_sheet, -/obj/item/clothing/suit/ghost_sheet, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQP" = ( @@ -18237,10 +18215,10 @@ /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQV" = ( -/obj/machinery/vending/autodrobe, /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/vending/clothing, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQW" = ( @@ -18254,7 +18232,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/vending/games, +/obj/machinery/vending/kink, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQY" = ( @@ -18737,9 +18715,6 @@ name = "Station Intercom (General)"; pixel_x = -27 }, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/russobluecamohat, /obj/item/clothing/head/russobluecamohat, /turf/open/floor/plasteel, /area/crew_quarters/locker) @@ -19223,7 +19198,6 @@ dir = 8 }, /obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/costume/kilt, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aTy" = ( @@ -19741,11 +19715,6 @@ department = "Locker Room"; pixel_x = -32 }, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/color/grey, -/obj/item/clothing/under/color/grey, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aUW" = ( @@ -20356,13 +20325,6 @@ "aWn" = ( /obj/structure/closet/wardrobe/black, /obj/item/clothing/shoes/jackboots, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/head/beret/black, /obj/item/clothing/head/beret/black, /turf/open/floor/plasteel, /area/crew_quarters/locker) @@ -21711,12 +21673,10 @@ dir = 4; pixel_x = 11 }, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 - }, /obj/structure/mirror{ pixel_x = 28 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "aZp" = ( @@ -21789,6 +21749,7 @@ /area/crew_quarters/toilet/locker) "aZw" = ( /obj/effect/landmark/blobstart, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "aZx" = ( @@ -22147,6 +22108,7 @@ c_tag = "Locker Room Toilets"; dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "bax" = ( @@ -22281,13 +22243,6 @@ /area/maintenance/port) "baO" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/obj/structure/mirror{ - pixel_x = 28 - }, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "baP" = ( @@ -22473,9 +22428,7 @@ /obj/machinery/light{ dir = 8 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "bbs" = ( @@ -22842,9 +22795,8 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bct" = ( -/obj/structure/chair/wood/wings, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "bcu" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/door/airlock/maintenance{ @@ -23321,9 +23273,12 @@ /turf/open/floor/carpet, /area/bridge/meeting_room) "bdJ" = ( -/obj/structure/closet/secure_closet/personal/cabinet, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/door/airlock{ + id_tag = "LockerShitter3"; + name = "Unit 3" + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "bdK" = ( /obj/machinery/holopad, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -23340,6 +23295,7 @@ dir = 8 }, /obj/structure/bedsheetbin/color, +/obj/structure/table, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/locker) "bdN" = ( @@ -23889,13 +23845,6 @@ }, /turf/closed/wall, /area/maintenance/disposal) -"bfa" = ( -/obj/structure/closet/crate, -/obj/item/stack/sheet/mineral/wood/fifty{ - amount = 20 - }, -/turf/open/floor/plating, -/area/maintenance/port) "bfb" = ( /obj/structure/sign/warning/vacuum/external{ pixel_y = 32 @@ -24371,14 +24320,12 @@ /turf/open/floor/plating, /area/maintenance/port) "bgr" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/plating, -/area/maintenance/port) -"bgs" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/structure/table/wood/fancy/purple, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/door/airlock{ + id_tag = "LockerShitter4"; + name = "Unit 4" + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "bgt" = ( /obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plating, @@ -24993,7 +24940,7 @@ dir = 4 }, /turf/closed/wall, -/area/maintenance/port) +/area/crew_quarters/toilet/locker) "bhR" = ( /obj/structure/grille, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -29139,14 +29086,7 @@ /turf/open/floor/plating, /area/maintenance/starboard) "brz" = ( -/obj/structure/table, -/obj/item/pen, -/obj/machinery/camera{ - c_tag = "Experimentor Lab"; - network = list("ss13","rd") - }, -/obj/item/hand_labeler, -/obj/item/stack/packageWrap, +/obj/machinery/rnd/bepis, /turf/open/floor/plasteel/white/side, /area/science/explab) "brA" = ( @@ -29163,11 +29103,14 @@ "brC" = ( /obj/structure/table, /obj/item/folder/white, -/obj/item/folder/white, /obj/machinery/airalarm{ pixel_y = 23 }, /obj/item/radio/off, +/obj/machinery/camera{ + c_tag = "Experimentor Lab"; + network = list("ss13","rd") + }, /turf/open/floor/plasteel/white/side, /area/science/explab) "brD" = ( @@ -38100,7 +38043,7 @@ /obj/machinery/light/small{ dir = 8 }, -/obj/machinery/chem_dispenser, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bLV" = ( @@ -47819,8 +47762,6 @@ "clO" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/grey, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, /obj/machinery/camera{ c_tag = "Dorms East - Holodeck"; dir = 4 @@ -51882,24 +51823,15 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "cBn" = ( -/obj/structure/closet, -/obj/item/stack/tile/carpet/royalblue{ - amount = 24 +/obj/structure/sink{ + dir = 4; + pixel_x = 11 }, -/obj/item/stack/tile/carpet/green{ - amount = 24 +/obj/structure/mirror{ + pixel_x = 28 }, -/obj/item/stack/tile/carpet/purple{ - amount = 24 - }, -/obj/item/stack/tile/carpet/orange{ - amount = 24 - }, -/obj/item/stack/tile/wood{ - amount = 24 - }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "cBo" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/wood, @@ -52369,6 +52301,19 @@ /obj/structure/closet/boxinggloves, /turf/open/floor/plasteel, /area/crew_quarters/fitness) +"cFG" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/mirror{ + pixel_x = 28 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "cGz" = ( /obj/structure/table/wood, /obj/item/instrument/violin, @@ -52757,10 +52702,6 @@ }, /turf/open/floor/plasteel/airless/solarpanel, /area/solar/starboard/aft) -"cMS" = ( -/obj/item/chair/wood, -/turf/open/floor/plating, -/area/maintenance/port) "cNa" = ( /obj/structure/cable, /obj/machinery/power/solar{ @@ -53822,14 +53763,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/security/execution/transfer) -"epC" = ( -/obj/machinery/door/airlock{ - desc = "To keep the station within regulations, space IKEA requires one storage cupboard for their Nanotrasen partnership to continue."; - id_tag = "MaintDorm1"; - name = "Furniture Storage" - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) "epD" = ( /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /obj/machinery/light{ @@ -54553,10 +54486,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"gfr" = ( -/obj/structure/bed, -/turf/open/floor/plating, -/area/maintenance/port) "gfC" = ( /obj/effect/turf_decal/tile/red, /obj/structure/chair{ @@ -54810,17 +54739,28 @@ /area/crew_quarters/fitness) "gQX" = ( /obj/machinery/button/door{ - desc = "Alright, GAMER! Want to take your PWRGAME addiction to the MAX? Just smash this button with your chubby chetto encrusted hands an- oh, you broke the switch. Good job, idiot."; - id = "RIPFUN"; - name = "Powerful Gamer Toggle"; + id = "LockerShitter4"; + name = "Door Bolt Control"; normaldoorcontrol = 1; - pixel_x = -24; - pixel_y = 7; + pixel_x = 14; + pixel_y = 38; specialfunctions = 4 }, -/obj/structure/table_frame/wood, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/structure/toilet/secret/low_loot{ + dir = 4 + }, +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/sink{ + dir = 1; + pixel_y = 25 + }, +/obj/structure/mirror{ + pixel_y = 32 + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "gRZ" = ( /obj/structure/bookcase{ name = "Forbidden Knowledge" @@ -54898,16 +54838,6 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"hew" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/port) "hgG" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/structure/extinguisher_cabinet{ @@ -54945,10 +54875,6 @@ }, /turf/closed/wall, /area/crew_quarters/dorms) -"hnl" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, -/turf/closed/wall, -/area/maintenance/port) "hnU" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -55043,15 +54969,12 @@ /turf/open/floor/wood, /area/crew_quarters/bar) "hPs" = ( -/obj/structure/fireplace{ - pixel_y = -6 - }, /obj/machinery/airalarm{ dir = 8; pixel_x = 23 }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "hPP" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -55259,13 +55182,6 @@ /obj/effect/turf_decal/tile/green, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"iwB" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/closed/wall, -/area/maintenance/port) "izg" = ( /obj/item/cigbutt/cigarbutt, /turf/open/floor/plating, @@ -55507,9 +55423,7 @@ }, /area/maintenance/bar) "jrE" = ( -/obj/structure/sign/poster/official/random{ - pixel_x = 32 - }, +/obj/item/beacon, /turf/open/floor/plasteel/white, /area/science/circuit) "jtj" = ( @@ -56183,10 +56097,6 @@ }, /turf/open/floor/plasteel, /area/security/brig) -"kQO" = ( -/obj/structure/reagent_dispensers/keg/semen, -/turf/open/floor/plating, -/area/maintenance/bar) "kSb" = ( /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -56318,7 +56228,7 @@ }, /area/maintenance/bar) "lsk" = ( -/obj/machinery/vending/autodrobe, +/obj/machinery/vending/kink, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ltK" = ( @@ -57250,17 +57160,29 @@ /turf/open/floor/plasteel, /area/security/prison) "omY" = ( -/obj/item/flashlight/lamp/green{ - pixel_x = -2; - pixel_y = 15 +/obj/machinery/button/door{ + id = "LockerShitter3"; + name = "Door Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 14; + pixel_y = 38; + specialfunctions = 4 }, -/obj/structure/dresser{ - desc = "There's plenty of clothes here to change into! It has a surprising amount of variety, too."; - name = "Dresser"; - pixel_y = 7 +/obj/structure/toilet/secret/low_loot{ + dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/sink{ + dir = 1; + pixel_y = 25 + }, +/obj/structure/mirror{ + pixel_y = 32 + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "oqj" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -57480,12 +57402,7 @@ "oZl" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/pjs, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/under/costume/maid, /obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/accessory/maidapron, /obj/machinery/light{ dir = 8 }, @@ -57582,7 +57499,6 @@ /turf/open/floor/wood, /area/crew_quarters/bar) "pqs" = ( -/obj/machinery/vending/clothing, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -58078,11 +57994,11 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/vending/kink, /obj/machinery/light{ dir = 4; light_color = "#e8eaff" }, +/obj/machinery/vending/games, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "rgL" = ( @@ -58184,11 +58100,6 @@ dir = 4 }, /obj/structure/closet/wardrobe/black, -/obj/item/clothing/under/dress/skirt, -/obj/item/clothing/head/beret/black, -/obj/item/clothing/head/beret/black, -/obj/item/clothing/under/custom/trendy_fit, -/obj/item/clothing/under/custom/trendy_fit, /obj/item/clothing/under/dress/sundress, /turf/open/floor/plasteel, /area/crew_quarters/fitness) @@ -58887,11 +58798,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/crew_quarters/dorms) -"txm" = ( -/obj/structure/table/wood/fancy/royalblue, -/obj/item/crowbar/red, -/turf/open/floor/plating, -/area/maintenance/port) "tyX" = ( /obj/structure/cable{ icon_state = "4-8" @@ -60186,6 +60092,12 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"wTk" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "wUg" = ( /obj/effect/turf_decal/stripes/line{ dir = 10 @@ -77122,10 +77034,10 @@ aXQ aXQ aXQ aXQ -aPz -aPz -epC -aPz +aXQ +aXQ +aXQ +aXQ bhQ bjj bkF @@ -77379,9 +77291,9 @@ aXQ aZt aXQ ycd -aPz +aXQ omY -cMS +aXQ gQX bhQ bjj @@ -77636,12 +77548,12 @@ aXQ aZv aXQ bbL -aPz +aXQ bdJ -txm +aXQ bgr -iwB -hew +bhQ +bjj bkF aaa aaa @@ -77893,10 +77805,10 @@ aWy aYe bbq aZw -aPz +wTk +bct +bct bct -bfa -gfr bhQ bjk bkE @@ -78150,11 +78062,11 @@ aXp baO aZo baw -aPz +cFG hPs cBn -bgs -hnl +bct +bhQ bjk bkF aaa @@ -78407,10 +78319,10 @@ aXQ aXQ aXQ aXQ -aPz -aPz -aPz -aPz +aXQ +aXQ +aXQ +aXQ bhQ bjk aPz @@ -82564,7 +82476,7 @@ mrR dKP odx rBq -kQO +evR bCq bUs bLv diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm index b3aad634c5..d2443f076c 100644 --- a/_maps/map_files/CogStation/CogStation.dmm +++ b/_maps/map_files/CogStation/CogStation.dmm @@ -72017,6 +72017,10 @@ }, /turf/open/space/basic, /area/space/nearstation) +"mBP" = ( +/obj/machinery/rnd/bepis, +/turf/open/floor/plasteel/white, +/area/science/circuit) "mEa" = ( /obj/machinery/atmospherics/pipe/manifold/cyan/visible, /obj/machinery/meter, @@ -93372,7 +93376,7 @@ aTE bTG aVF cGs -aVF +mBP caw caA cHk diff --git a/_maps/map_files/CogStation/FOLDER.txt b/_maps/map_files/CogStation/FOLDER.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index e5f8c587ab..6a5c8ef5ee 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -97814,17 +97814,17 @@ /obj/structure/sign/poster/official/science{ pixel_x = -32 }, +/obj/item/clothing/mask/gas, /turf/open/floor/plasteel, /area/science/explab) "djC" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/effect/turf_decal/stripes/line{ dir = 10 }, +/obj/machinery/rnd/bepis, /turf/open/floor/plasteel, /area/science/explab) "djD" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/machinery/light{ dir = 1 }, @@ -97835,7 +97835,6 @@ /turf/open/floor/plasteel, /area/science/explab) "djE" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -98819,34 +98818,20 @@ /obj/machinery/newscaster{ pixel_x = -32 }, -/obj/item/crowbar, -/obj/item/wrench, -/obj/item/clothing/mask/gas, /obj/effect/turf_decal/bot, +/obj/item/storage/bag/money, /turf/open/floor/plasteel, /area/science/explab) "dlp" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 5 - }, /obj/effect/turf_decal/tile/purple{ dir = 1 }, +/obj/structure/chair/office/light{ + dir = 8 + }, /turf/open/floor/plasteel/white, /area/science/explab) "dlq" = ( -/obj/machinery/atmospherics/components/trinary/filter{ - dir = 8 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 1 - }, -/turf/open/floor/plasteel/white, -/area/science/explab) -"dlr" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 9 - }, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -124854,10 +124839,6 @@ }, /turf/open/floor/plasteel/airless/solarpanel, /area/solar/port/aft) -"egC" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/chapel/office) "egD" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 @@ -125091,7 +125072,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/chem_dispenser, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/dark, /area/medical/medbay/central) "eMD" = ( @@ -156734,7 +156715,7 @@ cOM dgs cMY djE -dlr +dlq dmE dow dqm @@ -162434,7 +162415,7 @@ edT eeC efp egd -egC +efg aaa aad aaa @@ -162691,7 +162672,7 @@ edU eeD efq ege -egC +efg aaa aad aaa @@ -162948,7 +162929,7 @@ edV eeE efr ege -egC +efg aad ajr aaa diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 4d9dc17dfa..201418eba1 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -3806,8 +3806,6 @@ }, /obj/structure/closet/wardrobe/white, /obj/item/clothing/under/suit/waiter, -/obj/item/clothing/under/suit/waiter, -/obj/item/clothing/under/suit/waiter, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ahD" = ( @@ -3952,11 +3950,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/mixed, /obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/dress/skirt/purple, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, /obj/structure/sign/poster/official/fashion{ pixel_x = -32 }, @@ -4487,13 +4480,13 @@ /turf/open/floor/plating, /area/maintenance/fore/secondary) "aiB" = ( -/obj/machinery/vending/kink, /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/structure/sign/poster/official/fashion{ pixel_y = 32 }, +/obj/machinery/vending/autodrobe, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aiC" = ( @@ -10746,21 +10739,7 @@ /obj/structure/closet{ name = "Holodeck Outfits" }, -/obj/item/clothing/under/trek/Q, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/medsci/next, -/obj/item/clothing/under/trek/medsci/next, -/obj/item/clothing/under/trek/medsci/next, /obj/item/clothing/under/misc/blue_camo, -/obj/item/clothing/under/misc/blue_camo, -/obj/item/clothing/under/costume/gladiator, -/obj/item/clothing/under/costume/gladiator, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -18449,7 +18428,6 @@ /obj/structure/closet/wardrobe/white, /obj/item/clothing/suit/ghost_sheet, /obj/item/clothing/suit/ghost_sheet, -/obj/item/clothing/suit/ghost_sheet, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQP" = ( @@ -18477,10 +18455,10 @@ /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQV" = ( -/obj/machinery/vending/autodrobe, /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/vending/clothing, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQW" = ( @@ -18494,7 +18472,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/vending/games, +/obj/machinery/vending/kink, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQY" = ( @@ -18977,9 +18955,6 @@ name = "Station Intercom (General)"; pixel_x = -27 }, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/russobluecamohat, /obj/item/clothing/head/russobluecamohat, /turf/open/floor/plasteel, /area/crew_quarters/locker) @@ -19463,7 +19438,6 @@ dir = 8 }, /obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/costume/kilt, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aTy" = ( @@ -19982,13 +19956,8 @@ department = "Locker Room"; pixel_x = -32 }, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/color/grey, -/obj/item/clothing/under/color/grey, /turf/open/floor/plasteel, -/area/crew_quarters/locker) +/area/space) "aUW" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp/green, @@ -20597,13 +20566,6 @@ "aWn" = ( /obj/structure/closet/wardrobe/black, /obj/item/clothing/shoes/jackboots, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/head/beret/black, /obj/item/clothing/head/beret/black, /turf/open/floor/plasteel, /area/crew_quarters/locker) @@ -21947,19 +21909,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/wood, /area/security/vacantoffice) -"aZo" = ( -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 - }, -/obj/structure/mirror{ - pixel_x = 28 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/toilet/locker) "aZp" = ( /obj/structure/rack, /obj/item/electronics/apc, @@ -22030,6 +21979,7 @@ /area/crew_quarters/toilet/locker) "aZw" = ( /obj/effect/landmark/blobstart, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "aZx" = ( @@ -22388,6 +22338,7 @@ c_tag = "Locker Room Toilets"; dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "bax" = ( @@ -22714,9 +22665,7 @@ /obj/machinery/light{ dir = 8 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "bbs" = ( @@ -23083,9 +23032,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bct" = ( -/obj/structure/chair/wood/wings, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "bcu" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/door/airlock/maintenance{ @@ -23562,9 +23513,12 @@ /turf/open/floor/carpet, /area/bridge/meeting_room) "bdJ" = ( -/obj/structure/closet/secure_closet/personal/cabinet, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/door/airlock{ + id_tag = "LockerShitter3"; + name = "Unit 3" + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "bdK" = ( /obj/machinery/holopad, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -24131,12 +24085,8 @@ /turf/closed/wall, /area/maintenance/disposal) "bfa" = ( -/obj/structure/closet/crate, -/obj/item/stack/sheet/mineral/wood/fifty{ - amount = 20 - }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "bfb" = ( /obj/structure/sign/warning/vacuum/external{ pixel_y = 32 @@ -24611,14 +24561,12 @@ /turf/open/floor/plating, /area/maintenance/port) "bgr" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/plating, -/area/maintenance/port) -"bgs" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/structure/table/wood/fancy/purple, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/door/airlock{ + id_tag = "LockerShitter4"; + name = "Unit 4" + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "bgt" = ( /obj/effect/spawner/lootdrop/maintenance, /obj/structure/reagent_dispensers/watertank, @@ -25235,7 +25183,7 @@ dir = 4 }, /turf/closed/wall, -/area/maintenance/port) +/area/crew_quarters/toilet/locker) "bhR" = ( /obj/structure/grille, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -29367,14 +29315,7 @@ /turf/open/floor/plating, /area/maintenance/starboard) "brz" = ( -/obj/structure/table, -/obj/item/pen, -/obj/machinery/camera{ - c_tag = "Experimentor Lab"; - network = list("ss13","rd") - }, -/obj/item/hand_labeler, -/obj/item/stack/packageWrap, +/obj/machinery/rnd/bepis, /turf/open/floor/plasteel/white/side, /area/science/explab) "brA" = ( @@ -29396,6 +29337,10 @@ pixel_y = 23 }, /obj/item/radio/off, +/obj/machinery/camera{ + c_tag = "Experimentor Lab"; + network = list("ss13","rd") + }, /turf/open/floor/plasteel/white/side, /area/science/explab) "brD" = ( @@ -38320,7 +38265,7 @@ /obj/machinery/light/small{ dir = 8 }, -/obj/machinery/chem_dispenser, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bLV" = ( @@ -41718,7 +41663,7 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/pipe/simple/dark/visible{ +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ dir = 4 }, /turf/open/floor/plasteel/white/corner, @@ -44852,7 +44797,7 @@ /area/engine/engineering) "ccy" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/machinery/atmospherics/pipe/simple/dark/visible{ +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ dir = 4 }, /turf/open/floor/plasteel, @@ -45205,7 +45150,7 @@ "cdB" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/dark/visible{ +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ dir = 4 }, /turf/open/floor/plating, @@ -48338,8 +48283,6 @@ "clO" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/grey, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, /obj/machinery/camera{ c_tag = "Dorms East - Holodeck"; dir = 4 @@ -52200,24 +52143,15 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "cBn" = ( -/obj/structure/closet, -/obj/item/stack/tile/carpet/royalblue{ - amount = 24 +/obj/structure/sink{ + dir = 4; + pixel_x = 11 }, -/obj/item/stack/tile/carpet/green{ - amount = 24 +/obj/structure/mirror{ + pixel_x = 28 }, -/obj/item/stack/tile/carpet/purple{ - amount = 24 - }, -/obj/item/stack/tile/carpet/orange{ - amount = 24 - }, -/obj/item/stack/tile/wood{ - amount = 24 - }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "cBo" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/wood, @@ -53005,10 +52939,6 @@ }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, /area/icemoon/surface/outdoors) -"cMS" = ( -/obj/item/chair/wood, -/turf/open/floor/plating, -/area/maintenance/port) "cNa" = ( /obj/structure/cable, /obj/machinery/power/solar{ @@ -54124,6 +54054,13 @@ }, /turf/open/floor/wood, /area/crew_quarters/bar) +"emX" = ( +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors) "ene" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -54141,14 +54078,6 @@ }, /turf/open/floor/engine, /area/engine/engineering) -"epC" = ( -/obj/machinery/door/airlock{ - desc = "To keep the station within regulations, space IKEA requires one storage cupboard for their Nanotrasen partnership to continue."; - id_tag = "MaintDorm1"; - name = "Furniture Storage" - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) "epD" = ( /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /obj/machinery/light{ @@ -55014,10 +54943,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"gfr" = ( -/obj/structure/bed, -/turf/open/floor/plating, -/area/maintenance/port) "gfC" = ( /obj/effect/turf_decal/tile/red, /obj/structure/chair{ @@ -55317,17 +55242,28 @@ /area/crew_quarters/fitness) "gQX" = ( /obj/machinery/button/door{ - desc = "Alright, GAMER! Want to take your PWRGAME addiction to the MAX? Just smash this button with your chubby chetto encrusted hands an- oh, you broke the switch. Good job, idiot."; - id = "RIPFUN"; - name = "Powerful Gamer Toggle"; + id = "LockerShitter4"; + name = "Door Bolt Control"; normaldoorcontrol = 1; - pixel_x = -24; - pixel_y = 7; + pixel_x = 14; + pixel_y = 38; specialfunctions = 4 }, -/obj/structure/table_frame/wood, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/structure/toilet/secret/low_loot{ + dir = 4 + }, +/obj/structure/sink{ + dir = 1; + pixel_y = 25 + }, +/obj/structure/mirror{ + pixel_y = 32 + }, +/obj/machinery/light/small{ + dir = 8 + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "gRZ" = ( /obj/structure/bookcase{ name = "Forbidden Knowledge" @@ -55397,16 +55333,6 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"hew" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/port) "hgO" = ( /obj/structure/table, /obj/item/storage/pill_bottle/dice{ @@ -55453,10 +55379,6 @@ }, /turf/closed/wall, /area/crew_quarters/dorms) -"hnl" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, -/turf/closed/wall, -/area/maintenance/port) "hnU" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -55604,15 +55526,15 @@ /turf/open/floor/engine, /area/engine/engineering) "hPs" = ( -/obj/structure/fireplace{ - pixel_y = -6 - }, /obj/machinery/airalarm{ dir = 8; pixel_x = 23 }, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "hPP" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -55830,13 +55752,6 @@ /obj/effect/turf_decal/tile/green, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"iwB" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/closed/wall, -/area/maintenance/port) "izg" = ( /obj/item/cigbutt/cigarbutt, /turf/open/floor/plating, @@ -55865,6 +55780,12 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness/pool) +"iBR" = ( +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 6 + }, +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors) "iEJ" = ( /obj/machinery/door/airlock/external{ name = "Escape Pod One" @@ -56609,6 +56530,12 @@ /obj/structure/window, /turf/open/floor/wood, /area/crew_quarters/bar) +"krn" = ( +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 9 + }, +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors) "ksp" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/closed/wall, @@ -56859,10 +56786,6 @@ }, /turf/open/floor/plasteel, /area/security/brig) -"kQO" = ( -/obj/structure/reagent_dispensers/keg/semen, -/turf/open/floor/plating, -/area/maintenance/bar) "kSb" = ( /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -56907,6 +56830,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"kYy" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "kZE" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -57041,7 +56968,7 @@ /turf/open/floor/engine, /area/engine/engineering) "lsk" = ( -/obj/machinery/vending/autodrobe, +/obj/machinery/vending/kink, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ltK" = ( @@ -57462,6 +57389,13 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) +"mAU" = ( +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/turf/open/floor/plating/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors) "mCy" = ( /obj/machinery/space_heater{ anchored = 1 @@ -58081,17 +58015,26 @@ /turf/open/floor/plasteel, /area/security/prison) "omY" = ( -/obj/item/flashlight/lamp/green{ - pixel_x = -2; - pixel_y = 15 +/obj/machinery/button/door{ + id = "LockerShitter4"; + name = "Door Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 14; + pixel_y = 38; + specialfunctions = 4 }, -/obj/structure/dresser{ - desc = "There's plenty of clothes here to change into! It has a surprising amount of variety, too."; - name = "Dresser"; - pixel_y = 7 +/obj/structure/toilet/secret/low_loot{ + dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/structure/sink{ + dir = 1; + pixel_y = 25 + }, +/obj/machinery/light/small{ + dir = 8 + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "oqj" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -58399,12 +58342,7 @@ "oZl" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/pjs, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/under/costume/maid, /obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/accessory/maidapron, /obj/machinery/light{ dir = 8 }, @@ -58525,7 +58463,6 @@ /turf/open/floor/wood, /area/crew_quarters/bar) "pqs" = ( -/obj/machinery/vending/clothing, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -59046,18 +58983,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel/dark, /area/engine/engineering) -"rca" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, -/obj/structure/closet/secure_closet/atmospherics, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/plasteel/dark/corner{ - dir = 1 - }, -/area/engine/atmos) "rcD" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -59101,11 +59026,11 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/vending/kink, /obj/machinery/light{ dir = 4; light_color = "#e8eaff" }, +/obj/machinery/vending/games, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "rfW" = ( @@ -59228,11 +59153,6 @@ dir = 4 }, /obj/structure/closet/wardrobe/black, -/obj/item/clothing/under/dress/skirt, -/obj/item/clothing/head/beret/black, -/obj/item/clothing/head/beret/black, -/obj/item/clothing/under/custom/trendy_fit, -/obj/item/clothing/under/custom/trendy_fit, /obj/item/clothing/under/dress/sundress, /turf/open/floor/plasteel, /area/crew_quarters/fitness) @@ -60176,11 +60096,6 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engineering) -"txm" = ( -/obj/structure/table/wood/fancy/royalblue, -/obj/item/crowbar/red, -/turf/open/floor/plating, -/area/maintenance/port) "tyX" = ( /obj/structure/cable{ icon_state = "4-8" @@ -61008,6 +60923,10 @@ }, /turf/open/floor/wood, /area/maintenance/bar) +"vke" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "vmQ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 10 @@ -78702,10 +78621,10 @@ aXQ aXQ aXQ aXQ -aPz -aPz -epC -aPz +aXQ +aXQ +aXQ +aXQ bhQ bjj bkF @@ -78959,9 +78878,9 @@ aXQ aZt aXQ ycd -aPz +aXQ omY -cMS +aXQ gQX bhQ bjj @@ -79216,12 +79135,12 @@ aXQ aZv aXQ bbL -aPz +aXQ bdJ -txm +aXQ bgr -iwB -hew +bhQ +bjj bkF ayF ayF @@ -79473,10 +79392,10 @@ aWy aYe bbq aZw -aPz +kYy bct bfa -gfr +bfa bhQ bjk bkE @@ -79727,14 +79646,14 @@ aSV aUo aUX aXp +vke baO -aZo baw -aPz +baO hPs cBn -bgs -hnl +bfa +bhQ bjk bkF ayF @@ -79987,10 +79906,10 @@ aXQ aXQ aXQ aXQ -aPz -aPz -aPz -aPz +aXQ +aXQ +aXQ +aXQ bhQ bjk aPz @@ -84144,7 +84063,7 @@ mrR dKP odx rBq -kQO +evR bCq bUs bLv @@ -93127,7 +93046,7 @@ bOX bQm bRv bRs -rca +glY bTP bVX bWQ @@ -93384,7 +93303,7 @@ bOW bQl bRu bRs -rca +glY bUI bVR bWQ @@ -97747,14 +97666,14 @@ bFJ bvd bKH bzs -avm -ayF -avm -ayF -avB -ayF -avm -ayF +iBR +avx +mAU +avx +emX +avx +mAU +krn avB awd awe diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index 45876d0267..e867e3bc9e 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -30490,9 +30490,8 @@ dir = 4 }, /obj/machinery/light{ - dir = 4 + dir = 1 }, -/obj/machinery/computer/nanite_cloud_controller, /turf/open/floor/plasteel/dark, /area/science/research) "aXx" = ( @@ -30604,7 +30603,8 @@ name = "science camera"; network = list("ss13","rd") }, -/obj/machinery/computer/nanite_chamber_control, +/obj/structure/table/reinforced, +/obj/item/storage/bag/money, /turf/open/floor/plasteel/dark, /area/science/research) "aXG" = ( @@ -31272,8 +31272,6 @@ dir = 1 }, /obj/structure/table/reinforced, -/obj/item/nanite_scanner, -/obj/item/nanite_remote, /turf/open/floor/plasteel/dark, /area/science/research) "aYO" = ( @@ -35133,7 +35131,6 @@ dir = 4 }, /obj/effect/landmark/event_spawn, -/obj/machinery/nanite_program_hub, /turf/open/floor/plasteel/dark, /area/science/research) "beE" = ( @@ -85138,7 +85135,7 @@ dir = 8 }, /obj/effect/turf_decal/bot, -/obj/machinery/nanite_chamber, +/obj/machinery/rnd/bepis, /turf/open/floor/plasteel/dark, /area/science/research) "kSc" = ( @@ -85405,14 +85402,6 @@ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, /area/hallway/secondary/entry) -"sfp" = ( -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/machinery/nanite_programmer, -/turf/open/floor/plasteel/dark, -/area/science/research) "swG" = ( /obj/item/reagent_containers/food/drinks/drinkingglass{ pixel_x = 4; @@ -123517,7 +123506,7 @@ aZv aXw kRh aXI -sfp +aXI beD bbj aNF diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm index a24d5d666d..901824a5de 100644 --- a/_maps/map_files/LambdaStation/lambda.dmm +++ b/_maps/map_files/LambdaStation/lambda.dmm @@ -23470,9 +23470,7 @@ dir = 8 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, -/obj/structure/closet/l3closet/scientist{ - pixel_x = -2 - }, +/obj/structure/closet/l3closet/scientist, /turf/open/floor/plasteel/white, /area/science/explab) "aQI" = ( @@ -38260,12 +38258,10 @@ /turf/open/floor/plasteel/white, /area/medical/chemistry) "btD" = ( -/obj/machinery/chem_dispenser{ - layer = 2.7 - }, /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 }, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/white, /area/medical/chemistry) "btE" = ( @@ -81493,6 +81489,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"sZf" = ( +/obj/machinery/rnd/bepis, +/turf/open/floor/engine, +/area/science/explab) "tbT" = ( /obj/machinery/power/emitter/anchored{ dir = 1; @@ -113779,7 +113779,7 @@ aFb aFO aGD aHo -aGD +aHp aDr aaA aaA @@ -114035,7 +114035,7 @@ aEj aFc aFO aGD -aHp +aGD aGD aDr apk @@ -114548,9 +114548,9 @@ aJP aKA aFe aDr -aGD aHq aGD +sZf aDr aJI aKB diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 88487dc650..7807680289 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -56879,21 +56879,12 @@ }, /area/science/research) "ciS" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 - }, -/mob/living/simple_animal/pet/dog/pug{ - desc = "It's Pugley IV, the research department's lovable pug clone. Hopefully nothing happens to this one - fourth time lucky!"; - name = "Pugley IV"; - real_name = "Pugley IV" - }, +/obj/machinery/rnd/bepis, /turf/open/floor/engine, /area/science/explab) "ciT" = ( /obj/item/beacon, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 - }, +/obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/engine, /area/science/explab) "ciU" = ( @@ -59492,6 +59483,11 @@ /obj/structure/chair/office/light{ dir = 4 }, +/mob/living/simple_animal/pet/dog/pug{ + desc = "It's Pugley IV, the research department's lovable pug clone. Hopefully nothing happens to this one - fourth time lucky!"; + name = "Pugley IV"; + real_name = "Pugley IV" + }, /turf/open/floor/plasteel/white, /area/science/explab) "com" = ( @@ -63863,9 +63859,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, -/obj/machinery/chem_dispenser{ - layer = 2.7 - }, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/white, /area/medical/medbay/aft) "cwp" = ( diff --git a/_maps/shuttles/emergency_gorilla.dmm b/_maps/shuttles/emergency_gorilla.dmm index 0c75cd8b7e..cc2e67ee3e 100644 --- a/_maps/shuttles/emergency_gorilla.dmm +++ b/_maps/shuttles/emergency_gorilla.dmm @@ -326,10 +326,6 @@ /mob/living/simple_animal/hostile/gorilla, /turf/open/floor/plasteel/shuttle, /area/shuttle/escape) -"bn" = ( -/obj/structure/reagent_dispensers/keg/semen, -/turf/open/floor/plating, -/area/shuttle/escape) "bo" = ( /obj/structure/closet/crate/freezer/surplus_limbs, /turf/open/floor/plasteel/shuttle, @@ -539,7 +535,7 @@ aD fV Pi bm -bn +ax bs bu "} @@ -610,7 +606,7 @@ aX aD fV bi -bn +ax bl fV ab diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 82dc87e465..07f24fd8a3 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -101,8 +101,5 @@ #define TOGGLES_CITADEL 0 -//component stuff -#define COMSIG_VORE_TOGGLED "voremode_toggled" // totally not copypasta - //belly sound pref things #define NORMIE_HEARCHECK 4 diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 6ef8b07ddd..6e9383326e 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -29,38 +29,27 @@ #define EFFECT_DROWSY "drowsy" #define EFFECT_JITTER "jitter" -// /mob/living/combat_flags -#define CAN_TOGGLE_COMBAT_MODE(mob) FORCE_BOOLEAN((mob.stat == CONSCIOUS) && !(mob.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)) - -/// Default combat flags for those affected by ((stamina combat)) +/// Default combat flags for those affected by sprinting (combat mode has been made into its own component) #define COMBAT_FLAGS_DEFAULT NONE -/// Default combat flags for everyone else (so literally everyone but humans) -#define COMBAT_FLAGS_STAMSYSTEM_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_COMBAT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_COMBAT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED | COMBAT_FLAG_COMBAT_FORCED) -/// Default combat flags for those only affected by sprint (so just silicons) -#define COMBAT_FLAGS_STAMEXEMPT_YESSPRINT (COMBAT_FLAG_COMBAT_ACTIVE | COMBAT_FLAG_COMBAT_TOGGLED | COMBAT_FLAG_COMBAT_FORCED) +/// Default combat flags for everyone else (so literally everyone but humans). +#define COMBAT_FLAGS_SPRINT_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED) -/// The user wants combat mode on -#define COMBAT_FLAG_COMBAT_TOGGLED (1<<0) /// The user wants sprint mode on -#define COMBAT_FLAG_SPRINT_TOGGLED (1<<1) -/// Combat mode is currently active -#define COMBAT_FLAG_COMBAT_ACTIVE (1<<2) +#define COMBAT_FLAG_SPRINT_TOGGLED (1<<0) /// Sprint is currently active -#define COMBAT_FLAG_SPRINT_ACTIVE (1<<3) +#define COMBAT_FLAG_SPRINT_ACTIVE (1<<1) /// Currently attempting to crawl under someone -#define COMBAT_FLAG_ATTEMPTING_CRAWL (1<<4) +#define COMBAT_FLAG_ATTEMPTING_CRAWL (1<<2) /// Currently stamcritted -#define COMBAT_FLAG_HARD_STAMCRIT (1<<5) +#define COMBAT_FLAG_HARD_STAMCRIT (1<<3) /// Currently attempting to resist up from the ground -#define COMBAT_FLAG_RESISTING_REST (1<<6) +#define COMBAT_FLAG_RESISTING_REST (1<<4) /// Intentionally resting -#define COMBAT_FLAG_INTENTIONALLY_RESTING (1<<7) +#define COMBAT_FLAG_INTENTIONALLY_RESTING (1<<5) /// Currently stamcritted but not as violently -#define COMBAT_FLAG_SOFT_STAMCRIT (1<<8) -/// Force combat mode on at all times, overrides everything including combat disable traits. -#define COMBAT_FLAG_COMBAT_FORCED (1<<9) +#define COMBAT_FLAG_SOFT_STAMCRIT (1<<6) /// Force sprint mode on at all times, overrides everything including sprint disable traits. -#define COMBAT_FLAG_SPRINT_FORCED (1<<10) +#define COMBAT_FLAG_SPRINT_FORCED (1<<7) // Helpers for getting someone's stamcrit state. Cast to living. #define NOT_STAMCRIT 0 diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm index 65e1d0e980..f1548bbe0f 100644 --- a/code/__DEFINES/construction.dm +++ b/code/__DEFINES/construction.dm @@ -69,6 +69,7 @@ #define CAT_WEAPONRY "Weaponry" #define CAT_WEAPON "Weapons" #define CAT_AMMO "Ammunition" +#define CAT_PARTS "Weapon Parts" #define CAT_ROBOT "Robots" #define CAT_MISC "Misc" #define CAT_MISCELLANEOUS "Miscellaneous" diff --git a/code/__DEFINES/dcs/flags.dm b/code/__DEFINES/dcs/flags.dm index 59c0c58b8d..2dbd4874d9 100644 --- a/code/__DEFINES/dcs/flags.dm +++ b/code/__DEFINES/dcs/flags.dm @@ -75,3 +75,11 @@ #define ID_COMPONENT_KNOWLEDGE_NONE 0 /// Has full knowledge #define ID_COMPONENT_KNOWLEDGE_FULL 1 + +// Combat mode flags. +/// The user wants combat mode on +#define COMBAT_MODE_TOGGLED (1<<0) +/// combat mode is active. +#define COMBAT_MODE_ACTIVE (1<<1) +/// combat mode is not active +#define COMBAT_MODE_INACTIVE (1<<2) \ No newline at end of file diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index d78cecf9b1..ea9ebbec02 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -149,7 +149,8 @@ // /mob signals #define COMSIG_MOB_CLICKED_SHIFT_ON "mob_shift_click_on" //from base of /atom/ShiftClick(): (atom/A), for return values, see COMSIG_CLICK_SHIFT -#define COMSIG_MOB_FOV_VIEW "mob_visible_atoms" //from base of mob/fov_view(): (list/visible_atoms) +#define COMSIG_MOB_FOV_VIEW "mob_visible_atoms" //from base of /mob/fov_view(): (list/visible_atoms) +#define COMSIG_MOB_POINTED "mob_pointed" //from base of /mob/verb/pointed(): (atom/A) #define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A), for return values, see COMSIG_CLICK_SHIFT #define COMPONENT_EXAMINATE_BLIND 3 //outputs the "something is there but you can't see it" message. #define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed) @@ -192,7 +193,12 @@ #define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //from base of /obj/effect/proc_holder/spell/can_cast(): (spell) -#define COMSIG_ROBOT_UPDATE_ICONS "robot_update_icons" //from base of robot/update_icons(): () +// /client signals +#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) +#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client) +#define COMSIG_MOB_CLIENT_MOVE "mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc) +#define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view" //from base of /client/change_view(): (client, old_view, view) +#define COMSIG_MOB_CLIENT_MOUSEMOVE "mob_client_mousemove" //from base of /client/MouseMove(): (object, location, control, params) // /mob/living signals #define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs) @@ -200,20 +206,14 @@ #define COMSIG_LIVING_IGNITED "living_ignite" //from base of mob/living/IgniteMob() (/mob/living) #define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living) #define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage, source, siemens_coeff, flags) +#define COMSIG_LIVING_SHOCK_PREVENTED "living_shock_prevented" //sent when items with siemen coeff. of 0 block a shock: (power_source, source, siemens_coeff, dist_check) #define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: () #define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive) -#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) -#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client) -#define COMSIG_MOB_CLIENT_MOVE "mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc) -#define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view" //from base of /client/change_view(): (client, old_view, view) - #define COMSIG_MOB_RESET_PERSPECTIVE "mob_reset_perspective" //from base of /mob/reset_perspective(): (atom/target) #define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override) // This returns flags as defined for block in __DEFINES/combat.dm! #define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone) -#define COMSIG_LIVING_COMBAT_ENABLED "combatmode_enabled" //from base of mob/living/enable_combat_mode() (was_forced) -#define COMSIG_LIVING_COMBAT_DISABLED "combatmode_disabled" //from base of mob/living/disable_combat_mode() (was_forced) #define COMSIG_LIVING_GET_BLOCKING_ITEMS "get_blocking_items" //from base of mob/living/get_blocking_items(): (list/items) //ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! @@ -231,6 +231,10 @@ #define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) #define COMSIG_CARBON_IDENTITY_TRANSFERRED_TO "carbon_id_transferred_to" //from datum/dna/transfer_identity(): (datum/dna, transfer_SE) #define COMSIG_CARBON_TACKLED "carbon_tackled" //sends from tackle.dm on tackle completion + +// /mob/living/silicon signals +#define COMSIG_ROBOT_UPDATE_ICONS "robot_update_icons" //from base of robot/update_icons(): () + // /mob/living/simple_animal/hostile signals #define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" #define COMPONENT_HOSTILE_NO_ATTACK 1 @@ -341,6 +345,14 @@ //NTnet #define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive" //called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata)) +//Combat mode +#define COMSIG_TOGGLE_COMBAT_MODE "toggle_combat_mode" //safely toggles combat mode. +#define COMSIG_DISABLE_COMBAT_MODE "disable_combat_mode" //safely disables combat mode. +#define COMSIG_ENABLE_COMBAT_MODE "enable_combat_mode" //safely enables combat mode. +#define COMSIG_LIVING_COMBAT_ENABLED "combatmode_enabled" //from base of datum/component/combat_mode/enable_combat_mode() (was_forced) +#define COMSIG_LIVING_COMBAT_DISABLED "combatmode_disabled" //from base of datum/component/combat_mode/disable_combat_mode() (was_forced) +#define COMSIG_COMBAT_MODE_CHECK "combatmode_check" //called when checking the combat mode flags (enabled/disabled/forced) + //Nanites #define COMSIG_HAS_NANITES "has_nanites" //() returns TRUE if nanites are found #define COMSIG_NANITE_IS_STEALTHY "nanite_is_stealthy" //() returns TRUE if nanites have stealth diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 9facaf5d70..abc0507bf4 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -74,8 +74,10 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define FLYING (1<<1) #define VENTCRAWLING (1<<2) #define FLOATING (1<<3) -#define UNSTOPPABLE (1<<4) //When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped. -#define CRAWLING (1<<5) //Applied if you're crawling around on the ground/resting. +///When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped. +#define UNSTOPPABLE (1<<4) +///Applied if you're crawling around on the ground/resting. +#define CRAWLING (1<<5) //Fire and Acid stuff, for resistance_flags #define LAVA_PROOF (1<<0) diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index e418b8b4c6..24726b8058 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -209,3 +209,5 @@ /// Make sure something is a boolean TRUE/FALSE 1/0 value, since things like bitfield & bitflag doesn't always give 1s and 0s. #define FORCE_BOOLEAN(x) ((x)? TRUE : FALSE) + +#define TILES_TO_PIXELS(tiles) (tiles * PIXELS) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 12828191ae..1714bd597f 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -9,6 +9,9 @@ #define TEXT_EAST "[EAST]" #define TEXT_WEST "[WEST]" +/// world.icon_size +#define PIXELS 32 + //These get to go at the top, because they're special //You can use these defines to get the typepath of the currently running proc/verb (yes procs + verbs are objects) /* eg: @@ -27,31 +30,32 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s //Human Overlays Indexes///////// //LOTS OF CIT CHANGES HERE. BE CAREFUL WHEN UPSTREAM ADDS MORE LAYERS -#define MUTATIONS_LAYER 32 //mutations. Tk headglows, cold resistance glow, etc -#define GENITALS_BEHIND_LAYER 31 //Some genitalia needs to be behind everything, such as with taurs (Taurs use body_behind_layer -#define BODY_BEHIND_LAYER 30 //certain mutantrace features (tail when looking south) that must appear behind the body parts -#define BODYPARTS_LAYER 29 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag -#define MARKING_LAYER 28 //Matrixed body markings because clashing with snouts? -#define BODY_ADJ_LAYER 27 //certain mutantrace features (snout, body markings) that must appear above the body parts -#define GENITALS_FRONT_LAYER 26 //Draws some genitalia above clothes and the TAUR body if need be. -#define BODY_LAYER 25 //underwear, undershirts, socks, eyes, lips(makeup) -#define BODY_ADJ_UPPER_LAYER 24 -#define FRONT_MUTATIONS_LAYER 23 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes) -#define DAMAGE_LAYER 22 //damage indicators (cuts and burns) -#define UNIFORM_LAYER 21 -#define ID_LAYER 20 -#define HANDS_PART_LAYER 19 -#define SHOES_LAYER 18 -#define GLOVES_LAYER 17 -#define EARS_LAYER 16 -#define SUIT_LAYER 15 -#define GENITALS_EXPOSED_LAYER 14 -#define GLASSES_LAYER 13 -#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt? -#define SUIT_STORE_LAYER 11 -#define NECK_LAYER 10 -#define BACK_LAYER 9 -#define HAIR_LAYER 8 //TODO: make part of head layer? +#define MUTATIONS_LAYER 33 //mutations. Tk headglows, cold resistance glow, etc +#define GENITALS_BEHIND_LAYER 32 //Some genitalia needs to be behind everything, such as with taurs (Taurs use body_behind_layer +#define BODY_BEHIND_LAYER 31 //certain mutantrace features (tail when looking south) that must appear behind the body parts +#define BODYPARTS_LAYER 30 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag +#define MARKING_LAYER 29 //Matrixed body markings because clashing with snouts? +#define BODY_ADJ_LAYER 28 //certain mutantrace features (snout, body markings) that must appear above the body parts +#define GENITALS_FRONT_LAYER 27 //Draws some genitalia above clothes and the TAUR body if need be. +#define BODY_LAYER 26 //underwear, undershirts, socks, eyes, lips(makeup) +#define BODY_ADJ_UPPER_LAYER 25 +#define FRONT_MUTATIONS_LAYER 24 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes) +#define DAMAGE_LAYER 23 //damage indicators (cuts and burns) +#define UNIFORM_LAYER 22 +#define ID_LAYER 21 +#define HANDS_PART_LAYER 20 +#define SHOES_LAYER 19 +#define GLOVES_LAYER 18 +#define EARS_LAYER 17 +#define SUIT_LAYER 16 +#define GENITALS_EXPOSED_LAYER 15 +#define GLASSES_LAYER 14 +#define BELT_LAYER 13 //Possible make this an overlay of somethign required to wear a belt? +#define SUIT_STORE_LAYER 12 +#define NECK_LAYER 11 +#define BACK_LAYER 10 +#define HAIR_LAYER 9 //TODO: make part of head layer? +#define HORNS_LAYER 8 #define FACEMASK_LAYER 7 #define HEAD_LAYER 6 #define HANDCUFF_LAYER 5 @@ -59,7 +63,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s #define HANDS_LAYER 3 #define BODY_FRONT_LAYER 2 #define FIRE_LAYER 1 //If you're on fire -#define TOTAL_LAYERS 32 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; +#define TOTAL_LAYERS 33 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; //Human Overlay Index Shortcuts for alternate_worn_layer, layers //Because I *KNOW* somebody will think layer+1 means "above" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 29ab67271c..8d8b9f47ae 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -126,6 +126,13 @@ #define SCREWYHUD_DEAD 2 #define SCREWYHUD_HEALTHY 3 +//Threshold levels for beauty for humans +#define BEAUTY_LEVEL_HORRID -66 +#define BEAUTY_LEVEL_BAD -33 +#define BEAUTY_LEVEL_DECENT 33 +#define BEAUTY_LEVEL_GOOD 66 +#define BEAUTY_LEVEL_GREAT 100 + //Moods levels for humans #define MOOD_LEVEL_HAPPY4 15 #define MOOD_LEVEL_HAPPY3 10 diff --git a/code/__DEFINES/profile.dm b/code/__DEFINES/profile.dm index 8929e0f05e..5fc8478901 100644 --- a/code/__DEFINES/profile.dm +++ b/code/__DEFINES/profile.dm @@ -26,4 +26,4 @@ #define PROFILE_ITEM_LEN 2 #define PROFILE_ITEM_TIME 1 -#define PROFILE_ITEM_COUNT 2 \ No newline at end of file +#define PROFILE_ITEM_COUNT 2 diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 6eb38fce81..8c423ad09c 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -117,6 +117,7 @@ #define FIRE_PRIORITY_NPC 80 #define FIRE_PRIORITY_MOBS 100 #define FIRE_PRIORITY_TGUI 110 +#define FIRE_PRIORITY_PROJECTILES 200 #define FIRE_PRIORITY_TICKER 200 #define FIRE_PRIORITY_ATMOS_ADJACENCY 300 #define FIRE_PRIORITY_CHAT 400 diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index e164a4ec96..7c0811ec59 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -1,253 +1,343 @@ -//tgstation-server DMAPI +// tgstation-server DMAPI -#define TGS_DMAPI_VERSION "5.1.1" +#define TGS_DMAPI_VERSION "5.2.1" -//All functions and datums outside this document are subject to change with any version and should not be relied on +// All functions and datums outside this document are subject to change with any version and should not be relied on. -//CONFIGURATION +// CONFIGURATION -//create this define if you want to do configuration outside of this file +/// Create this define if you want to do TGS configuration outside of this file. #ifndef TGS_EXTERNAL_CONFIGURATION -//Comment this out once you've filled in the below +// Comment this out once you've filled in the below. #error TGS API unconfigured -//Uncomment this if you wish to allow the game to interact with TGS 3 -//This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()() +// Uncomment this if you wish to allow the game to interact with TGS 3. +// This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()() //#define TGS_V3_API -//Required interfaces (fill in with your codebase equivalent): +// Required interfaces (fill in with your codebase equivalent): -//create a global variable named `Name` and set it to `Value` +/// Create a global variable named `Name` and set it to `Value`. #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) -//Read the value in the global variable `Name` +/// Read the value in the global variable `Name`. #define TGS_READ_GLOBAL(Name) -//Set the value in the global variable `Name` to `Value` +/// Set the value in the global variable `Name` to `Value`. #define TGS_WRITE_GLOBAL(Name, Value) -//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities +/// Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities. #define TGS_PROTECT_DATUM(Path) -//Display an announcement `message` from the server to all players +/// Display an announcement `message` from the server to all players. #define TGS_WORLD_ANNOUNCE(message) -//Notify current in-game administrators of a string `event` +/// Notify current in-game administrators of a string `event`. #define TGS_NOTIFY_ADMINS(event) -//Write an info `message` to a server log +/// Write an info `message` to a server log. #define TGS_INFO_LOG(message) -//Write an warning `message` to a server log +/// Write an warning `message` to a server log. #define TGS_WARNING_LOG(message) -//Write an error `message` to a server log +/// Write an error `message` to a server log. #define TGS_ERROR_LOG(message) -//Get the number of connected /clients +/// Get the number of connected /clients. #define TGS_CLIENT_COUNT #endif -//EVENT CODES +// EVENT CODES -#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //Before a reboot mode change, extras parameters are the current and new reboot mode enums -#define TGS_EVENT_PORT_SWAP -2 //Before a port change is about to happen, extra parameters is new port -#define TGS_EVENT_INSTANCE_RENAMED -3 //Before the instance is renamed, extra parameter is the new name -#define TGS_EVENT_WATCHDOG_REATTACH -4 //After the watchdog reattaches to DD, extra parameter is the new /datum/tgs_version of the server +/// Before a reboot mode change, extras parameters are the current and new reboot mode enums +#define TGS_EVENT_REBOOT_MODE_CHANGE -1 +/// Before a port change is about to happen, extra parameters is new port +#define TGS_EVENT_PORT_SWAP -2 +/// Before the instance is renamed, extra parameter is the new name +#define TGS_EVENT_INSTANCE_RENAMED -3 +/// After the watchdog reattaches to DD, extra parameter is the new [/datum/tgs_version] of the server +#define TGS_EVENT_WATCHDOG_REATTACH -4 -//See the descriptions for the parameters of these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs +/// When the repository is reset to its origin reference. Parameters: Reference name, Commit SHA #define TGS_EVENT_REPO_RESET_ORIGIN 0 +/// When the repository performs a checkout. Parameters: Checkout git object #define TGS_EVENT_REPO_CHECKOUT 1 +/// When the repository performs a fetch operation. No parameters #define TGS_EVENT_REPO_FETCH 2 +/// When the repository merges a pull request. Parameters: PR Number, PR Sha, (Nullable) Comment made by TGS user #define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3 +/// Before the repository makes a sychronize operation. Parameters: Absolute repostiory path #define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4 +/// Before a BYOND install operation begins. Parameters: [/datum/tgs_version] of the installing BYOND #define TGS_EVENT_BYOND_INSTALL_START 5 +/// When a BYOND install operation fails. Parameters: Error message #define TGS_EVENT_BYOND_INSTALL_FAIL 6 +/// When the active BYOND version changes. Parameters: (Nullable) [/datum/tgs_version] of the current BYOND, [/datum/tgs_version] of the new BYOND #define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7 +/// When the compiler starts running. Parameters: Game directory path, origin commit SHA #define TGS_EVENT_COMPILE_START 8 +/// When a compile is cancelled. No parameters #define TGS_EVENT_COMPILE_CANCELLED 9 +/// When a compile fails. Parameters: Game directory path, [TRUE]/[FALSE] based on if the cause for failure was DMAPI validation #define TGS_EVENT_COMPILE_FAILURE 10 -#define TGS_EVENT_COMPILE_COMPLETE 11 // Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the TGS_EVENT_DEPLOYMENT_COMPLETE instead +/// When a compile operation completes. Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the [TGS_EVENT_DEPLOYMENT_COMPLETE] instead. Parameters: Game directory path +#define TGS_EVENT_COMPILE_COMPLETE 11 +/// When an automatic update for the current instance begins. No parameters #define TGS_EVENT_INSTANCE_AUTO_UPDATE_START 12 +/// When the repository encounters a merge conflict: Parameters: Base SHA, target SHA, base reference, target reference #define TGS_EVENT_REPO_MERGE_CONFLICT 13 +/// When a deployment completes. No Parameters #define TGS_EVENT_DEPLOYMENT_COMPLETE 14 +/// Before the watchdog shuts down. Not sent for graceful shutdowns. No parameters. #define TGS_EVENT_WATCHDOG_SHUTDOWN 15 +/// Before the watchdog detaches for a TGS update/restart. No parameters. #define TGS_EVENT_WATCHDOG_DETACH 16 -//OTHER ENUMS +// OTHER ENUMS +/// The server will reboot normally. #define TGS_REBOOT_MODE_NORMAL 0 +/// The server will stop running on reboot. #define TGS_REBOOT_MODE_SHUTDOWN 1 +/// The watchdog will restart on reboot. #define TGS_REBOOT_MODE_RESTART 2 +/// DreamDaemon Trusted security level. #define TGS_SECURITY_TRUSTED 0 +/// DreamDaemon Safe security level. #define TGS_SECURITY_SAFE 1 +/// DreamDaemon Ultrasafe security level. #define TGS_SECURITY_ULTRASAFE 2 //REQUIRED HOOKS -//Call this somewhere in /world/New() that is always run -//IMPORTANT: This function may sleep! -//event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels -//minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated +/** + * Call this somewhere in [/world/proc/New] that is always run. This function may sleep! + * + * * event_handler - Optional user defined [/datum/tgs_event_handler]. + * * minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated. Can be one of [TGS_SECURITY_ULTRASAFE], [TGS_SECURITY_SAFE], or [TGS_SECURITY_TRUSTED]. + */ /world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE) return -//Call this when your initializations are complete and your game is ready to play before any player interactions happen -//This may use world.sleep_offline to make this happen so ensure no changes are made to it while this call is running -//Most importantly, before this point, note that any static files or directories may be in use by another server. Your code should account for this -//This function should not be called before ..() in /world/New() +/** + * Call this when your initializations are complete and your game is ready to play before any player interactions happen. + * + * This may use [/world/var/sleep_offline] to make this happen so ensure no changes are made to it while this call is running. + * Before this point, note that any static files or directories may be in use by another server. Your code should account for this. + * This function should not be called before ..() in [/world/proc/New]. + */ /world/proc/TgsInitializationComplete() return -//Put this at the start of /world/Topic() +/// Put this at the start of [/world/proc/Topic]. #define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return -//Call this at the beginning of world/Reboot(reason) +/** + * Call this at the beginning of [world/proc/Reboot]. + */ /world/proc/TgsReboot() return -//DATUM DEFINITIONS -//unless otherwise specified all datums defined here should be considered read-only, warranty void if written +// DATUM DEFINITIONS +// All datums defined here should be considered read-only -//represents git revision information about the current world build +/// Represents git revision information. /datum/tgs_revision_information - var/commit //full sha of compiled commit - var/origin_commit //full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch + /// Full SHA of the commit. + var/commit + /// Full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch. + var/origin_commit -//represents a version of tgstation-server +/// Represents a version. /datum/tgs_version - var/suite //The suite/major version, can be >=3 + /// The suite/major version number + var/suite - //this group of variables can be null to represent a wild card - var/minor //The minor version - var/patch //The patch version - var/deprecated_patch //The legacy version + // This group of variables can be null to represent a wild card + /// The minor version number. null for wildcards + var/minor + /// The patch version number. null for wildcards + var/patch - var/raw_parameter //The unparsed parameter - var/deprefixed_parameter //The version only bit of raw_parameter + /// Legacy version number. Generally null + var/deprecated_patch -//if the tgs_version is a wildcard version + /// Unparsed string value + var/raw_parameter + /// String value minus prefix + var/deprefixed_parameter + +/** + * Returns [TRUE]/[FALSE] based on if the [/datum/tgs_version] contains wildcards. + */ /datum/tgs_version/proc/Wildcard() return -//if the tgs_version equals some other_version +/** + * Returns [TRUE]/[FALSE] based on if the [/datum/tgs_version] equals some other version. + * + * other_version - The [/datum/tgs_version] to compare against. + */ /datum/tgs_version/proc/Equals(datum/tgs_version/other_version) return -//represents a merge of a GitHub pull request +/// Represents a merge of a GitHub pull request. /datum/tgs_revision_information/test_merge - var/number //pull request number - var/title //pull request title - var/body //pull request body - var/author //pull request github author - var/url //link to pull request html - var/pull_request_commit //commit of the pull request when it was merged - var/time_merged //timestamp of when the merge commit for the pull request was created - var/comment //optional comment left by the one who initiated the test merge + /// The pull request number. + var/number + /// The pull request title when it was merged. + var/title + /// The pull request body when it was merged. + var/body + /// The GitHub username of the pull request's author. + var/author + /// An http URL to the pull request. + var/url + /// The SHA of the pull request when that was merged. + var/pull_request_commit + /// ISO 8601 timestamp of when the pull request was merged. + var/time_merged + /// (Nullable) Comment left by the TGS user who initiated the merge.. + var/comment -//represents a connected chat channel +/// Represents a connected chat channel. /datum/tgs_chat_channel - var/id //internal channel representation - var/friendly_name //user friendly channel name - var/connection_name //the name of the configured chat connection - var/is_admin_channel //if the server operator has marked this channel for game admins only - var/is_private_channel //if this is a private chat channel - var/custom_tag //user defined string associated with channel + /// TGS internal channel ID. + var/id + /// User friendly name of the channel. + var/friendly_name + /// Name of the chat connection. This is the IRC server address or the Discord guild. + var/connection_name + /// [TRUE]/[FALSE] based on if the server operator has marked this channel for game admins only. + var/is_admin_channel + /// [TRUE]/[FALSE] if the channel is a private message channel for a [/datum/tgs_chat_user]. + var/is_private_channel + /// Tag string associated with the channel in TGS + var/custom_tag -//represents a chat user +// Represents a chat user /datum/tgs_chat_user - var/id //Internal user representation, requires channel to be unique - var/friendly_name //The user's public name - var/mention //The text to use to ping this user in a message - var/datum/tgs_chat_channel/channel //The /datum/tgs_chat_channel this user was from + /// TGS internal user ID. + var/id + // The user's display name. + var/friendly_name + // The string to use to ping this user in a message. + var/mention + /// The [/datum/tgs_chat_channel] the user was from + var/datum/tgs_chat_channel/channel -//user definable callback for handling events -//extra parameters may be specified depending on the event +/** + * User definable callback for handling TGS events. + * + * event_code - One of the TGS_EVENT_ defines. Extra parameters will be documented in each + */ /datum/tgs_event_handler/proc/HandleEvent(event_code, ...) set waitfor = FALSE return -//user definable chat command +/// User definable chat command /datum/tgs_chat_command - var/name = "" //the string to trigger this command on a chat bot. e.g. TGS3_BOT: do_this_command - var/help_text = "" //help text for this command - var/admin_only = FALSE //set to TRUE if this command should only be usable by registered chat admins + /// The string to trigger this command on a chat bot. e.g `@bot name ...` or `!tgs name ...` + var/name = "" + /// The help text displayed for this command + var/help_text = "" + /// If this command should be available to game administrators only + var/admin_only = FALSE -//override to implement command -//sender: The tgs_chat_user who send to command -//params: The trimmed string following the command name -//The return value will be stringified and sent to the appropriate chat +/** + * Process command activation. Should return a string to respond to the issuer with. + * + * sender - The [/datum/tgs_chat_user] who issued the command. + * params - The trimmed string following the command `/datum/tgs_chat_command/var/name]. + */ /datum/tgs_chat_command/proc/Run(datum/tgs_chat_user/sender, params) CRASH("[type] has no implementation for Run()") -//FUNCTIONS +// API FUNCTIONS -//Returns the respective supported /datum/tgs_version of the API +/// Returns the maximum supported [/datum/tgs_version] of the DMAPI. /world/proc/TgsMaximumAPIVersion() return +/// Returns the minimum supported [/datum/tgs_version] of the DMAPI. /world/proc/TgsMinimumAPIVersion() return -//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise -//No function below this succeeds if it returns FALSE or if TgsNew() has yet to be called +/** + * Returns [TRUE] if DreamDaemon was launched under TGS, the API matches, and was properly initialized. [FALSE] will be returned otherwise. + */ /world/proc/TgsAvailable() return -//Forces a hard reboot of BYOND by ending the process -//unlike del(world) clients will try to reconnect -//If the service has not requested a shutdown, the next server will take over +// No function below this succeeds if it TgsAvailable() returns FALSE or if TgsNew() has yet to be called. + +/** + * Forces a hard reboot of DreamDaemon by ending the process. + * + * Unlike del(world) clients will try to reconnect. + * If TGS has not requested a [TGS_REBOOT_MODE_SHUTDOWN] DreamDaemon will be launched again + */ /world/proc/TgsEndProcess() return -//Send a message to non-admin connected chats -//message: The message to send -//admin_only: If TRUE, message will instead be sent to only admin connected chats -/world/proc/TgsTargetedChatBroadcast(message, admin_only) +/** + * Send a message to connected chats. + * + * message - The string to send. + * admin_only: If [TRUE], message will be sent to admin connected chats. Vice-versa applies. + */ +/world/proc/TgsTargetedChatBroadcast(message, admin_only = FALSE) return -//Send a private message to a specific user -//message: The message to send -//user: The /datum/tgs_chat_user to send to +/** + * Send a private message to a specific user. + * + * message - The string to send. + * user: The [/datum/tgs_chat_user] to PM. + */ /world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user) return -//The following functions will sleep if a call to TgsNew() is sleeping +// The following functions will sleep if a call to TgsNew() is sleeping -//Sends a message to connected game chats -//message: The message to send -//channels: optional channels to limit the broadcast to -/world/proc/TgsChatBroadcast(message, list/channels) +/** + * Send a message to connected chats that are flagged as game-related in TGS. + * + * message - The string to send. + * channels - Optional list of [/datum/tgs_chat_channel]s to restrict the message to. + */ +/world/proc/TgsChatBroadcast(message, list/channels = null) return -//Gets the current /datum/tgs_version of the server tools running the server +/// Returns the current [/datum/tgs_version] of TGS if it is running the server, null otherwise. /world/proc/TgsVersion() return -//Gets the current /datum/tgs_version of the DMAPI being used +/// Returns the current [/datum/tgs_version] of the DMAPI being used if it was activated, null otherwise. /world/proc/TgsApiVersion() return -//Gets the name of the TGS instance running the game +/// Returns the name of the TGS instance running the game if TGS is present, null otherwise. /world/proc/TgsInstanceName() return -//Get the current `/datum/tgs_revision_information` +/// Return the current [/datum/tgs_revision_information] of the running server if TGS is present, null otherwise. /world/proc/TgsRevision() return -//Get the current BYOND security level +/// Returns the current BYOND security level as a TGS_SECURITY_ define if TGS is present, null otherwise. /world/proc/TgsSecurityLevel() return -//Gets a list of active `/datum/tgs_revision_information/test_merge`s +/// Returns a list of active [/datum/tgs_revision_information/test_merge]s if TGS is present, null otherwise. /world/proc/TgsTestMerges() return -//Gets a list of connected tgs_chat_channel +/// Returns a list of connected [/datum/tgs_chat_channel]s if TGS is present, null otherwise. /world/proc/TgsChatChannelInfo() return diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index a63a59c75f..74470cf72e 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -135,6 +135,7 @@ #define TRAIT_LAW_ENFORCEMENT_METABOLISM "law-enforcement-metabolism" #define TRAIT_QUICK_CARRY "quick-carry" #define TRAIT_QUICKER_CARRY "quicker-carry" +#define TRAIT_QUICK_BUILD "quick-build" #define TRAIT_STRONG_GRABBER "strong_grabber" #define TRAIT_CALCIUM_HEALER "calcium_healer" #define TRAIT_MAGIC_CHOKE "magic_choke" @@ -147,6 +148,8 @@ #define TRAIT_NORUNNING "norunning" // You walk! #define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites. #define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat. +#define TRAIT_NOGUT "nogutting" //Your chest cant be gutted of organs +#define TRAIT_NODECAP "nodecapping" //Your head cant be cut off in combat #define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events" #define TRAIT_NO_MIDROUND_ANTAG "no-midround-antag" //can't be turned into an antag by random events #define TRAIT_PUGILIST "pugilist" //This guy punches people for a living @@ -179,6 +182,7 @@ #define TRAIT_PARA "paraplegic" #define TRAIT_EMPATH "empath" #define TRAIT_FRIENDLY "friendly" +#define TRAIT_SNOB "snob" #define TRAIT_CULT_EYES "cult_eyes" #define TRAIT_AUTO_CATCH_ITEM "auto_catch_item" #define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman. diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 7b304f968d..49d49a694f 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -161,6 +161,9 @@ /proc/log_subsystem(subsystem, text) WRITE_LOG(GLOB.subsystem_log, "[subsystem]: [text]") +/proc/log_click(atom/object, atom/location, control, params, client/C, event = "clicked", unexpected) + WRITE_LOG(GLOB.click_log, "[unexpected? "ERROR" :"CLICK"]: [C.ckey] - [event] : [istype(object)? "[object] ([COORD(object)])" : object] | [istype(location)? "[location] ([COORD(location)])" : location] | [control] | [params]") + /* Log to both DD and the logfile. */ /proc/log_world(text) #ifdef USE_CUSTOM_ERROR_HANDLER @@ -190,7 +193,7 @@ /proc/start_log(log) WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------") -/* ui logging */ +/* ui logging */ /proc/log_tgui(text) WRITE_LOG(GLOB.tgui_log, text) diff --git a/code/__HELPERS/angles.dm b/code/__HELPERS/angles.dm new file mode 100644 index 0000000000..a3fc2404bd --- /dev/null +++ b/code/__HELPERS/angles.dm @@ -0,0 +1,39 @@ +/proc/get_projectile_angle(atom/source, atom/target) + var/sx = source.x * world.icon_size + var/sy = source.y * world.icon_size + var/tx = target.x * world.icon_size + var/ty = target.y * world.icon_size + var/atom/movable/AM + if(ismovable(source)) + AM = source + sx += AM.step_x + sy += AM.step_y + if(ismovable(target)) + AM = target + tx += AM.step_x + ty += AM.step_y + return SIMPLIFY_DEGREES(arctan(ty - sy, tx - sx)) + +/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. + if(!start || !end) + return 0 + var/dy + var/dx + dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y) + dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x) + if(!dy) + return (dx>=0)?90:270 + .=arctan(dx/dy) + if(dy<0) + .+=180 + else if(dx<0) + .+=360 + +/proc/Get_Pixel_Angle(var/y, var/x)//for getting the angle when animating something's pixel_x and pixel_y + if(!y) + return (x>=0)?90:270 + .=arctan(x/y) + if(y<0) + .+=180 + else if(x<0) + .+=360 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 1f6c9c13a9..944e17b33b 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -15,30 +15,8 @@ var/textb = copytext(HTMLstring, 6, 8) return rgb(255 - hex2num(textr), 255 - hex2num(textg), 255 - hex2num(textb)) -/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. - if(!start || !end) - return 0 - var/dy - var/dx - dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y) - dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x) - if(!dy) - return (dx>=0)?90:270 - .=arctan(dx/dy) - if(dy<0) - .+=180 - else if(dx<0) - .+=360 - -/proc/Get_Pixel_Angle(var/y, var/x)//for getting the angle when animating something's pixel_x and pixel_y - if(!y) - return (x>=0)?90:270 - .=arctan(x/y) - if(y<0) - .+=180 - else if(x<0) - .+=360 - +//Better performant than an artisanal proc and more reliable than Turn(). From TGMC. +#define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) ) //Returns location. Returns null if no location was found. /proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) /* diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 1aab96f85e..e038596151 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -242,15 +242,14 @@ GLOBAL_LIST_INIT(bitfields, list( "MOBILITY_RESIST" = MOBILITY_RESIST ), "combat_flags" = list( - "COMBAT_FLAG_COMBAT_TOGGLED" = COMBAT_FLAG_COMBAT_TOGGLED, "COMBAT_FLAG_SPRINT_TOGGLED" = COMBAT_FLAG_SPRINT_TOGGLED, - "COMBAT_FLAG_COMBAT_ACTIVE" = COMBAT_FLAG_COMBAT_ACTIVE, "COMBAT_FLAG_SPRINT_ACTIVE" = COMBAT_FLAG_SPRINT_ACTIVE, "COMBAT_FLAG_ATTEMPTING_CRAWL" = COMBAT_FLAG_ATTEMPTING_CRAWL, "COMBAT_FLAG_HARD_STAMCRIT" = COMBAT_FLAG_HARD_STAMCRIT, "COMBAT_FLAG_SOFT_STAMCRIT" = COMBAT_FLAG_SOFT_STAMCRIT, "COMBAT_FLAG_INTENTIONALLY_RESTING" = COMBAT_FLAG_INTENTIONALLY_RESTING, - "COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST + "COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST, + "COMBAT_FLAG_SPRINT_FORCED" = COMBAT_FLAG_SPRINT_FORCED ), "shield_flags" = list( "SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT, diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index 632904202d..30321f5546 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -89,7 +89,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list( /obj/effect/spawner/lootdrop/welder_tools = 3, /obj/effect/spawner/lootdrop/low_tools = 5, /obj/item/relic = 3, - /obj/item/weaponcrafting/receiver = 2, + /obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 2, /obj/item/clothing/head/cone = 2, /obj/item/grenade/smokebomb = 2, /obj/item/geiger_counter = 3, diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 3c9b4ea1c6..b0a22f1d54 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -38,6 +38,8 @@ GLOBAL_VAR(reagent_log) GLOBAL_PROTECT(reagent_log) GLOBAL_VAR(world_crafting_log) GLOBAL_PROTECT(world_crafting_log) +GLOBAL_VAR(click_log) +GLOBAL_PROTECT(click_log) GLOBAL_LIST_EMPTY(bombers) GLOBAL_PROTECT(bombers) diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index 9638b040f9..8e2e0c3fb5 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -24,16 +24,6 @@ return -/client - var/list/atom/selected_target[2] - var/obj/item/active_mousedown_item = null - var/mouseParams = "" - var/mouseLocation = null - var/mouseObject = null - var/mouseControlObject = null - var/middragtime = 0 - var/atom/middragatom - /client/MouseDown(object, location, control, params) if (mouse_down_icon) mouse_pointer_icon = mouse_down_icon @@ -84,12 +74,6 @@ /obj/item/proc/onMouseUp(object, location, params, mob) return -/obj/item - var/canMouseDown = FALSE - -/obj/item/gun - var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds - /obj/item/gun/CanItemAutoclick(object, location, params) . = automatic @@ -108,16 +92,10 @@ mouseLocation = location mouseObject = object mouseControlObject = control - if(mob && LAZYLEN(mob.mousemove_intercept_objects)) - for(var/datum/D in mob.mousemove_intercept_objects) - D.onMouseMove(object, location, control, params) - if(!show_popup_menus && mob) //CIT CHANGE - passes onmousemove() to mobs - mob.onMouseMove(object, location, control, params) //CIT CHANGE - ditto + if(mob) + SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOUSEMOVE, object, location, control, params) ..() -/datum/proc/onMouseMove(object, location, control, params) - return - /client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params) var/list/L = params2list(params) if (L["middle"]) diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 7c116cc606..3cedd92255 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -642,9 +642,6 @@ so as to remain in compliance with the most up-to-date laws." mymob.client.screen |= alert return 1 -/mob - var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly - /obj/screen/alert/Click(location, control, params) if(!usr || !usr.client) return diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 3cfa71e19d..d82f3e7cf5 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -1,7 +1,3 @@ - -/mob - var/list/screens = list() - /mob/proc/overlay_fullscreen(category, type, severity) var/obj/screen/fullscreen/screen = screens[category] if (!screen || screen.type != type) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index f054cb0c8e..57335a966e 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -114,8 +114,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list( return ..() -/mob - var/hud_type = /datum/hud /mob/proc/create_mob_hud() if(!client || hud_used) diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 328e008f10..9380cf98aa 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -241,18 +241,11 @@ using.hud = src hotkeybuttons += using - //CIT CHANGES - rest and combat mode buttons - using = new /obj/screen/restbutton() - using.icon = tg_ui_icon_to_cit_ui(ui_style) + using = new /obj/screen/rest() + using.icon = ui_style using.screen_loc = ui_pull_resist using.hud = src static_inventory += using - - using = new /obj/screen/combattoggle() - using.icon = tg_ui_icon_to_cit_ui(ui_style) - using.screen_loc = ui_combat_toggle - using.hud = src - static_inventory += using //END OF CIT CHANGES using = new /obj/screen/human/toggle() diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm index 25a49c8d6b..d8ef1c525a 100755 --- a/code/_onclick/hud/parallax.dm +++ b/code/_onclick/hud/parallax.dm @@ -1,16 +1,4 @@ -/client - var/list/parallax_layers - var/list/parallax_layers_cached - var/atom/movable/movingmob - var/turf/previous_turf - var/dont_animate_parallax //world.time of when we can state animate()ing parallax again - var/last_parallax_shift //world.time of last update - var/parallax_throttle = 0 //ds between updates - var/parallax_movedir = 0 - var/parallax_layers_max = 3 - var/parallax_animate_timer - /datum/hud/proc/create_parallax(mob/viewmob) var/mob/screenmob = viewmob || mymob var/client/C = screenmob.client diff --git a/code/_onclick/hud/screen_objects/storage.dm b/code/_onclick/hud/screen_objects/storage.dm index d7d711917d..7e8bfe12ab 100644 --- a/code/_onclick/hud/screen_objects/storage.dm +++ b/code/_onclick/hud/screen_objects/storage.dm @@ -65,6 +65,7 @@ return ..() /obj/screen/storage/volumetric_box/Destroy() + makeItemInactive() our_item = null return ..() @@ -87,10 +88,14 @@ makeItemInactive() /obj/screen/storage/volumetric_box/proc/makeItemInactive() + if(!our_item) + return our_item.layer = VOLUMETRIC_STORAGE_ITEM_LAYER our_item.plane = VOLUMETRIC_STORAGE_ITEM_PLANE /obj/screen/storage/volumetric_box/proc/makeItemActive() + if(!our_item) + return our_item.layer = VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER //make sure we display infront of the others! our_item.plane = VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 3ad0219391..e2c160503c 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -113,7 +113,7 @@ /obj/attacked_by(obj/item/I, mob/living/user) var/totitemdamage = I.force var/bad_trait - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user)) + if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) totitemdamage *= 0.5 bad_trait = SKILL_COMBAT_MODE //blacklist combat skills. if(I.used_skills && user.mind) @@ -155,9 +155,11 @@ /mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user) . = I.force var/bad_trait - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user)) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) . *= 0.5 bad_trait = SKILL_COMBAT_MODE //blacklist combat skills. + if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) + . *= 1.5 if(!CHECK_MOBILITY(user, MOBILITY_STAND)) . *= 0.5 if(!user.mind || !I.used_skills) @@ -169,10 +171,6 @@ continue user.mind.auto_gain_experience(skill, I.skill_gain) -/mob/living/carbon/pre_attacked_by(obj/item/I, mob/living/user) - . = ..() - if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - . *= 1.5 // Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person. // Click parameters is the params string from byond Click() code, see that documentation. @@ -212,7 +210,7 @@ if(!user) return var/bad_trait - if(iscarbon(user) && !(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) . *= STAM_COST_NO_COMBAT_MULT bad_trait = SKILL_COMBAT_MODE if(used_skills && user.mind) diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 166f930e33..8a1c08bc35 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -451,3 +451,18 @@ SUBSYSTEM_DEF(garbage) #endif #endif + +#ifdef TESTING +/proc/writeDatumCount() + var/list/datums = list() + for(var/datum/D in world) + datums[D.type] += 1 + for(var/datum/D) + datums[D.type] += 1 + datums = sortTim(datums, /proc/cmp_numeric_dsc, associative = TRUE) + if(fexists("data/DATUMCOUNT.txt")) + fdel("data/DATUMCOUNT.txt") + var/outfile = file("data/DATUMCOUNT.txt") + for(var/path in datums) + outfile << "[datums[path]]\t\t\t\t\t[path]" +#endif diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index 812c0a00ca..7c51ba4506 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -43,7 +43,7 @@ SUBSYSTEM_DEF(input) // LET'S PLAY THE BIND EVERY KEY GAME! // oh except for Backspace and Enter; if you want to use those you shouldn't have used oldmode! var/list/classic_ctrl_override_keys = list( - "\[", "\]", "\\", ";", "'", ",", ".", "/", "-", "\\=", "`" + "\[", "\]", "\\\\", ";", "'", ",", ".", "/", "-", "=", "`" ) // i'm lazy let's play the list iteration game of numbers for(var/i in 0 to 9) @@ -58,8 +58,9 @@ SUBSYSTEM_DEF(input) macroset_classic_input["Ctrl+L"] = "looc" // let's play the list iteration game x2 for(var/key in classic_ctrl_override_keys) - macroset_classic_input["Ctrl+[key]"] = "\"KeyDown [key]\"" - macroset_classic_input["Ctrl+[key]+UP"] = "\"KeyUp [key]\"" + // make sure to double double quote to ensure things are treated as a key combo instead of addition/semicolon logic. + macroset_classic_input["\"Ctrl+[key]\""] = "\"KeyDown [istext(classic_ctrl_override_keys[key])? classic_ctrl_override_keys[key] : key]\"" + macroset_classic_input["\"Ctrl+[key]+UP\""] = "\"KeyUp [istext(classic_ctrl_override_keys[key])? classic_ctrl_override_keys[key] : key]\"" // Misc macroset_classic_input["Tab"] = "\".winset \\\"mainwindow.macro=[SKIN_MACROSET_CLASSIC_HOTKEYS] map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\"" macroset_classic_input["Escape"] = "\".winset \\\"input.text=\\\"\\\"\\\"\"" diff --git a/code/controllers/subsystem/materials.dm b/code/controllers/subsystem/materials.dm index cc07f8e963..96d733e8da 100644 --- a/code/controllers/subsystem/materials.dm +++ b/code/controllers/subsystem/materials.dm @@ -11,7 +11,11 @@ SUBSYSTEM_DEF(materials) ///Dictionary of category || list of material refs var/list/materials_by_category ///List of stackcrafting recipes for materials using rigid materials - var/list/rigid_stack_recipes = list(new/datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE)) + var/list/rigid_stack_recipes = list( + new /datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), + new /datum/stack_recipe("toilet", /obj/structure/toilet/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), + new /datum/stack_recipe("sink", /obj/structure/sink/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), + ) ///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info) /datum/controller/subsystem/materials/proc/InitializeMaterials() diff --git a/code/controllers/subsystem/processing/projectiles.dm b/code/controllers/subsystem/processing/projectiles.dm index 8cd63c6949..b8d904c727 100644 --- a/code/controllers/subsystem/processing/projectiles.dm +++ b/code/controllers/subsystem/processing/projectiles.dm @@ -1,21 +1,22 @@ PROCESSING_SUBSYSTEM_DEF(projectiles) name = "Projectiles" + priority = FIRE_PRIORITY_PROJECTILES wait = 1 stat_tag = "PP" flags = SS_NO_INIT|SS_TICKER - var/global_pixel_speed = 2 - var/global_iterations_per_move = 16 + var/global_pixel_increment_amount = 4 + var/global_projectile_speed_multiplier = 1 /datum/controller/subsystem/processing/projectiles/proc/set_pixel_speed(new_speed) - global_pixel_speed = new_speed + global_pixel_increment_amount = new_speed for(var/i in processing) var/obj/item/projectile/P = i if(istype(P)) //there's non projectiles on this too. - P.set_pixel_speed(new_speed) + P.set_pixel_increment_amount(new_speed) /datum/controller/subsystem/processing/projectiles/vv_edit_var(var_name, var_value) switch(var_name) - if(NAMEOF(src, global_pixel_speed)) + if(NAMEOF(src, global_pixel_increment_amount)) set_pixel_speed(var_value) return TRUE else diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm index f158574763..d816e37ddf 100644 --- a/code/controllers/subsystem/research.dm +++ b/code/controllers/subsystem/research.dm @@ -24,6 +24,7 @@ SUBSYSTEM_DEF(research) var/list/techweb_categories = list() //category name = list(node.id = TRUE) var/list/techweb_boost_items = list() //associative double-layer path = list(id = list(point_type = point_discount)) var/list/techweb_nodes_hidden = list() //Node ids that should be hidden by default. + var/list/techweb_nodes_experimental = list() //Node ids that are exclusive to the BEPIS. var/list/techweb_point_items = list( //path = list(point type = value) /obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000), @@ -508,6 +509,8 @@ SUBSYSTEM_DEF(research) D.unlocked_by += node.id if(node.hidden) techweb_nodes_hidden[node.id] = TRUE + if(node.experimental) + techweb_nodes_experimental[node.id] = TRUE CHECK_TICK generate_techweb_unlock_linking() diff --git a/code/datums/action.dm b/code/datums/action.dm index 00e7e0ad5d..0033df09d7 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -731,14 +731,6 @@ if(next_use_time > world.time) START_PROCESSING(SSfastprocess, src) - -//Stickmemes -/datum/action/item_action/stickmen - name = "Summon Stick Minions" - desc = "Allows you to summon faithful stickmen allies to aide you in battle." - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "art_summon" - //surf_ss13 /datum/action/item_action/bhop name = "Activate Jump Boots" diff --git a/code/datums/brain_damage/hypnosis.dm b/code/datums/brain_damage/hypnosis.dm index 37aee6df7e..f4c4541db9 100644 --- a/code/datums/brain_damage/hypnosis.dm +++ b/code/datums/brain_damage/hypnosis.dm @@ -63,7 +63,7 @@ if(prob(2)) switch(rand(1,2)) if(1) - to_chat(owner, "...[lowertext(hypnotic_phrase)]...") + to_chat(owner, "...[lowertext(hypnotic_phrase)]...") if(2) new /datum/hallucination/chat(owner, TRUE, FALSE, "[hypnotic_phrase]") diff --git a/code/datums/brain_damage/magic.dm b/code/datums/brain_damage/magic.dm new file mode 100644 index 0000000000..249907a1b8 --- /dev/null +++ b/code/datums/brain_damage/magic.dm @@ -0,0 +1,60 @@ +//Magical traumas, caused by spells and curses. +//Blurs the line between the victim's imagination and reality +//Unlike regular traumas this can affect the victim's body and surroundings + +/datum/brain_trauma/magic + resilience = TRAUMA_RESILIENCE_LOBOTOMY + +/datum/brain_trauma/magic/stalker + name = "Stalking Phantom" + desc = "Patient is stalked by a phantom only they can see." + scan_desc = "extra-sensory paranoia" + gain_text = "You feel like something wants to kill you..." + lose_text = "You no longer feel eyes on your back." + var/obj/effect/hallucination/simple/stalker_phantom/stalker + var/close_stalker = FALSE //For heartbeat + +/datum/brain_trauma/magic/stalker/on_gain() + create_stalker() + ..() + +/datum/brain_trauma/magic/stalker/proc/create_stalker() + var/turf/stalker_source = locate(owner.x + pick(-12, 12), owner.y + pick(-12, 12), owner.z) //random corner + stalker = new(stalker_source, owner) + +/datum/brain_trauma/magic/stalker/on_lose() + QDEL_NULL(stalker) + ..() + +/datum/brain_trauma/magic/stalker/on_life() + // Dead and unconscious people are not interesting to the psychic stalker. + if(owner.stat != CONSCIOUS) + return + + // Not even nullspace will keep it at bay. + if(!stalker || !stalker.loc || stalker.z != owner.z) + qdel(stalker) + create_stalker() + + if(get_dist(owner, stalker) <= 1) + playsound(owner, 'sound/magic/demon_attack1.ogg', 50) + owner.visible_message("[owner] is torn apart by invisible claws!", "Ghostly claws tear your body apart!") + owner.take_bodypart_damage(rand(20, 45)) + else if(prob(50)) + stalker.forceMove(get_step_towards(stalker, owner)) + if(get_dist(owner, stalker) <= 8) + if(!close_stalker) + var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE) + owner.playsound_local(owner, slowbeat, 40, 0, channel = CHANNEL_HEARTBEAT) + close_stalker = TRUE + else + if(close_stalker) + owner.stop_sound_channel(CHANNEL_HEARTBEAT) + close_stalker = FALSE + ..() + +/obj/effect/hallucination/simple/stalker_phantom + name = "???" + desc = "It's coming closer..." + image_icon = 'icons/mob/lavaland/lavaland_monsters.dmi' + image_state = "curseblob" diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm index e076c30ae1..bb37129b95 100644 --- a/code/datums/brain_damage/severe.dm +++ b/code/datums/brain_damage/severe.dm @@ -265,3 +265,37 @@ ..() if(prob(1) && !owner.has_status_effect(/datum/status_effect/trance)) owner.apply_status_effect(/datum/status_effect/trance, rand(100,300), FALSE) + +/datum/brain_trauma/severe/hypnotic_trigger + name = "Hypnotic Trigger" + desc = "Patient has a trigger phrase set in their subconscious that will trigger a suggestible trance-like state." + scan_desc = "oneiric feedback loop" + gain_text = "You feel odd, like you just forgot something important." + lose_text = "You feel like a weight was lifted from your mind." + random_gain = FALSE + var/trigger_phrase = "Nanotrasen" + +/datum/brain_trauma/severe/hypnotic_trigger/New(phrase) + ..() + if(phrase) + trigger_phrase = phrase + +/datum/brain_trauma/severe/hypnotic_trigger/on_lose() //hypnosis must be cleared separately, but brain surgery should get rid of both anyway + ..() + owner.remove_status_effect(/datum/status_effect/trance) + +/datum/brain_trauma/severe/hypnotic_trigger/handle_hearing(datum/source, list/hearing_args) + if(!owner.can_hear()) + return + if(owner == hearing_args[HEARING_SPEAKER]) + return + + var/regex/reg = new("(\\b[REGEX_QUOTE(trigger_phrase)]\\b)","ig") + + if(findtext(hearing_args[HEARING_RAW_MESSAGE], reg)) + addtimer(CALLBACK(src, .proc/hypnotrigger), 10) //to react AFTER the chat message + hearing_args[HEARING_RAW_MESSAGE] = reg.Replace(hearing_args[HEARING_RAW_MESSAGE], "*********") + +/datum/brain_trauma/severe/hypnotic_trigger/proc/hypnotrigger() + to_chat(owner, "The words trigger something deep within you, and you feel your consciousness slipping away...") + owner.apply_status_effect(/datum/status_effect/trance, rand(100,300), FALSE) diff --git a/code/datums/components/art.dm b/code/datums/components/art.dm deleted file mode 100644 index f6d3cb6c61..0000000000 --- a/code/datums/components/art.dm +++ /dev/null @@ -1,56 +0,0 @@ - -#define BAD_ART 12.5 -#define GOOD_ART 25 -#define GREAT_ART 50 - -/datum/component/art - var/impressiveness = 0 - -/datum/component/art/Initialize(impress) - impressiveness = impress - if(isobj(parent)) - RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_obj_examine) - else - RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_other_examine) - if(isstructure(parent)) - RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) - if(isitem(parent)) - RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/apply_moodlet) - -/datum/component/art/proc/apply_moodlet(mob/M, impress) - M.visible_message("[M] stops and looks intently at [parent].", \ - "You stop to take in [parent].") - switch(impress) - if (0 to BAD_ART) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) - if (BAD_ART to GOOD_ART) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) - if (GOOD_ART to GREAT_ART) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) - if(GREAT_ART to INFINITY) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) - - -/datum/component/art/proc/on_other_examine(datum/source, mob/M) - apply_moodlet(M, impressiveness) - -/datum/component/art/proc/on_obj_examine(datum/source, mob/M) - var/obj/O = parent - apply_moodlet(M, impressiveness *(O.obj_integrity/O.max_integrity)) - -/datum/component/art/proc/on_attack_hand(datum/source, mob/M) - to_chat(M, "You start examining [parent]...") - if(!do_after(M, 20, target = parent)) - return - on_obj_examine(source, M) - -/datum/component/art/rev - -/datum/component/art/rev/apply_moodlet(mob/M, impress) - M.visible_message("[M] stops to inspect [parent].", \ - "You take in [parent], inspecting the fine craftsmanship of the proletariat.") - - if(M.mind && M.mind.has_antag_datum(/datum/antagonist/rev)) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) - else - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) diff --git a/code/datums/components/combat_mode.dm b/code/datums/components/combat_mode.dm new file mode 100644 index 0000000000..b53d407162 --- /dev/null +++ b/code/datums/components/combat_mode.dm @@ -0,0 +1,217 @@ +/** + * Combat mode component. It makes the user face whichever atom the mouse pointer is hovering, + * amongst other things designed outside of this file, namely PvP and PvE stuff, hence the name. + * Can be toggled on and off by clicking the screen hud object or by pressing the assigned hotkey (default 'C') + */ +/datum/component/combat_mode + var/mode_flags = COMBAT_MODE_INACTIVE + var/combatmessagecooldown + var/lastmousedir + var/obj/screen/combattoggle/hud_icon + var/hud_loc + +/datum/component/combat_mode/Initialize(hud_loc = ui_combat_toggle) + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + var/mob/living/L = parent + + src.hud_loc = hud_loc + + RegisterSignal(L, SIGNAL_TRAIT(TRAIT_COMBAT_MODE_LOCKED), .proc/update_combat_lock) + RegisterSignal(L, COMSIG_TOGGLE_COMBAT_MODE, .proc/user_toggle_intentional_combat_mode) + RegisterSignal(L, COMSIG_DISABLE_COMBAT_MODE, .proc/safe_disable_combat_mode) + RegisterSignal(L, COMSIG_ENABLE_COMBAT_MODE, .proc/safe_enable_combat_mode) + RegisterSignal(L, COMSIG_MOB_DEATH, .proc/on_death) + RegisterSignal(L, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_logout) + RegisterSignal(L, COMSIG_MOB_HUD_CREATED, .proc/on_mob_hud_created) + RegisterSignal(L, COMSIG_COMBAT_MODE_CHECK, .proc/check_flags) + + update_combat_lock() + + if(L.client) + on_mob_hud_created(L) + +/datum/component/combat_mode/Destroy() + if(parent) + safe_disable_combat_mode(parent) + if(hud_icon) + QDEL_NULL(hud_icon) + return ..() + +/// Creates the hud screen object. +/datum/component/combat_mode/proc/on_mob_hud_created(mob/source) + hud_icon = new + hud_icon.hud = source.hud_used + hud_icon.icon = tg_ui_icon_to_cit_ui(source.hud_used.ui_style) + hud_icon.screen_loc = hud_loc + source.hud_used.static_inventory += hud_icon + hud_icon.update_icon() + +/// Combat mode can be locked out, forcibly disabled by a status trait. +/datum/component/combat_mode/proc/update_combat_lock() + var/locked = HAS_TRAIT(parent, TRAIT_COMBAT_MODE_LOCKED) + var/desired = (mode_flags & COMBAT_MODE_TOGGLED) + var/actual = (mode_flags & COMBAT_MODE_ACTIVE) + if(actual) + if(locked) + disable_combat_mode(parent, FALSE, TRUE) + else if(!desired) + disable_combat_mode(parent, TRUE, TRUE) + else + if(desired && !locked) + enable_combat_mode(parent, FALSE, TRUE) + +/// Enables combat mode. Please use 'safe_enable_combat_mode' instead, if you wish to also enable the toggle flag. +/datum/component/combat_mode/proc/enable_combat_mode(mob/living/source, silent = TRUE, forced = TRUE, visible = FALSE, locked = FALSE, playsound = FALSE) + if(locked) + if(hud_icon) + hud_icon.combat_on = TRUE + hud_icon.update_icon() + return + if(mode_flags & COMBAT_MODE_ACTIVE) + return + mode_flags |= COMBAT_MODE_ACTIVE + mode_flags &= ~COMBAT_MODE_INACTIVE + SEND_SIGNAL(source, COMSIG_LIVING_COMBAT_ENABLED, forced) + if(!silent) + var/self_message = forced? "Your muscles reflexively tighten!" : "You drop into a combative stance!" + if(visible && (forced || world.time >= combatmessagecooldown)) + combatmessagecooldown = world.time + 10 SECONDS + if(!forced) + if(source.a_intent != INTENT_HELP) + source.visible_message("[source] [source.resting ? "tenses up" : "drops into a combative stance"].", self_message) + else + source.visible_message("[source] [pick("looks","seems","goes")] [pick("alert","attentive","vigilant")].") + else + source.visible_message("[source] drops into a combative stance!", self_message) + else + to_chat(source, self_message) + if(playsound) + source.playsound_local(source, 'sound/misc/ui_toggle.ogg', 50, FALSE, pressure_affected = FALSE) //Sound from interbay! + RegisterSignal(source, COMSIG_MOB_CLIENT_MOUSEMOVE, .proc/onMouseMove) + RegisterSignal(source, COMSIG_MOVABLE_MOVED, .proc/on_move) + RegisterSignal(source, COMSIG_MOB_CLIENT_MOVE, .proc/on_client_move) + if(hud_icon) + hud_icon.combat_on = TRUE + hud_icon.update_icon() + +/// Disables combat mode. Please use 'safe_disable_combat_mode' instead, if you wish to also disable the toggle flag. +/datum/component/combat_mode/proc/disable_combat_mode(mob/living/source, silent = TRUE, forced = TRUE, visible = FALSE, locked = FALSE, playsound = FALSE) + if(locked) + if(hud_icon) + hud_icon.combat_on = FALSE + hud_icon.update_icon() + return + if(!(mode_flags & COMBAT_MODE_ACTIVE)) + return + mode_flags &= ~COMBAT_MODE_ACTIVE + mode_flags |= COMBAT_MODE_INACTIVE + SEND_SIGNAL(source, COMSIG_LIVING_COMBAT_DISABLED, forced) + if(!silent) + var/self_message = forced? "Your muscles are forcibly relaxed!" : "You relax your stance." + if(visible) + source.visible_message("[source] relaxes [source.p_their()] stance.", self_message) + else + to_chat(source, self_message) + if(playsound) + source.playsound_local(source, 'sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the toggleon sound! + UnregisterSignal(source, list(COMSIG_MOB_CLIENT_MOUSEMOVE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_CLIENT_MOVE)) + if(hud_icon) + hud_icon.combat_on = FALSE + hud_icon.update_icon() + +///Changes the user direction to (try) keep match the pointer. +/datum/component/combat_mode/proc/on_move(atom/movable/source, dir, atom/oldloc, forced) + var/mob/living/L = source + if(mode_flags & COMBAT_MODE_ACTIVE && L.client && lastmousedir && lastmousedir != dir) + L.setDir(lastmousedir, ismousemovement = TRUE) + +/// Added movement delay if moving backward. +/datum/component/combat_mode/proc/on_client_move(mob/source, client/client, direction, n, oldloc, added_delay) + if(oldloc != n && direction == REVERSE_DIR(source.dir)) + client.move_delay += added_delay*0.5 + +///Changes the user direction to (try) match the pointer. +/datum/component/combat_mode/proc/onMouseMove(mob/source, object, location, control, params) + if(source.client.show_popup_menus) + return + source.face_atom(object, TRUE) + lastmousedir = source.dir + +/// Toggles whether the user is intentionally in combat mode. THIS should be the proc you generally use! Has built in visual/to other player feedback, as well as an audible cue to ourselves. +/datum/component/combat_mode/proc/user_toggle_intentional_combat_mode(mob/living/source) + if(mode_flags & COMBAT_MODE_TOGGLED) + safe_disable_combat_mode(source) + else if(source.stat == CONSCIOUS && !(source.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)) + safe_enable_combat_mode(source) + +/// Enables intentionally being in combat mode. Please try to use the COMSIG_COMBAT_MODE_CHECK signal for feedback when possible. +/datum/component/combat_mode/proc/safe_enable_combat_mode(mob/living/source, silent = FALSE, visible = TRUE) + if((mode_flags & COMBAT_MODE_TOGGLED) && (mode_flags & COMBAT_MODE_ACTIVE)) + return TRUE + mode_flags |= COMBAT_MODE_TOGGLED + enable_combat_mode(source, silent, FALSE, visible, HAS_TRAIT(source, TRAIT_COMBAT_MODE_LOCKED), TRUE) + if(source.client) + source.client.show_popup_menus = FALSE + if(iscarbon(source)) //I dislike this typecheck. It probably should be removed once that spoiled apple is componentized too. + var/mob/living/carbon/C = source + if(C.voremode) + C.disable_vore_mode() + return TRUE + +/// Disables intentionally being in combat mode. Please try to use the COMSIG_COMBAT_MODE_CHECK signal for feedback when possible. +/datum/component/combat_mode/proc/safe_disable_combat_mode(mob/living/source, silent = FALSE, visible = FALSE) + if(!(mode_flags & COMBAT_MODE_TOGGLED) && !(mode_flags & COMBAT_MODE_ACTIVE)) + return TRUE + mode_flags &= ~COMBAT_MODE_TOGGLED + disable_combat_mode(source, silent, FALSE, visible, !(mode_flags & COMBAT_MODE_ACTIVE), TRUE) + if(source.client) + source.client.show_popup_menus = TRUE + return TRUE + +/// Returns a field of flags that are contained in both the second arg and our bitfield variable. +/datum/component/combat_mode/proc/check_flags(mob/living/source, flags) + return mode_flags & (flags) + +/// Disables combat mode upon death. +/datum/component/combat_mode/proc/on_death(mob/living/source) + safe_disable_combat_mode(source) + +/// Disables combat mode upon logout +/datum/component/combat_mode/proc/on_logout(mob/living/source) + safe_disable_combat_mode(source) + +/// The screen button. +/obj/screen/combattoggle + name = "toggle combat mode" + icon = 'modular_citadel/icons/ui/screen_midnight.dmi' + icon_state = "combat_off" + var/mutable_appearance/flashy + var/combat_on = FALSE ///Wheter combat mode is enabled or not, so we don't have to store a reference. + +/obj/screen/combattoggle/Click() + if(hud && usr == hud.mymob) + SEND_SIGNAL(hud.mymob, COMSIG_TOGGLE_COMBAT_MODE) + +/obj/screen/combattoggle/update_icon_state() + var/mob/living/user = hud?.mymob + if(!user) + return + if(combat_on) + icon_state = "combat" + else if(HAS_TRAIT(user, TRAIT_COMBAT_MODE_LOCKED)) + icon_state = "combat_locked" + else + icon_state = "combat_off" + +/obj/screen/combattoggle/update_overlays() + . = ..() + var/mob/living/carbon/user = hud?.mymob + if(!(user?.client)) + return + + if(combat_on) + if(!flashy) + flashy = mutable_appearance('icons/mob/screen_gen.dmi', "togglefull_flash") + flashy.color = user.client.prefs.hud_toggle_color + . += flashy //TODO - beg lummox jr for the ability to force mutable appearances or images to be created rendering from their first frame of animation rather than being based entirely around the client's frame count diff --git a/code/datums/components/crafting/guncrafting.dm b/code/datums/components/crafting/guncrafting.dm index e06583ab61..f332d53fc8 100644 --- a/code/datums/components/crafting/guncrafting.dm +++ b/code/datums/components/crafting/guncrafting.dm @@ -1,20 +1,64 @@ -//Gun crafting parts til they can be moved elsewhere - -// PARTS // +k// PARTS // /obj/item/weaponcrafting icon = 'icons/obj/improvised.dmi' -/obj/item/weaponcrafting/receiver - name = "modular receiver" - desc = "A prototype modular receiver and trigger assembly for a firearm." - icon_state = "receiver" - /obj/item/weaponcrafting/stock name = "rifle stock" desc = "A classic rifle stock that doubles as a grip, roughly carved out of wood." + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 6) icon_state = "riflestock" /obj/item/weaponcrafting/durathread_string name = "durathread string" desc = "A long piece of durathread with some resemblance to cable coil." icon_state = "durastring" + +//////////////////////////////// +// KAT IMPROVISED WEAPON PARTS// +//////////////////////////////// + +/obj/item/weaponcrafting/improvised_parts + name = "Eerie bunch of coloured dots." + desc = "You feel the urge to report to Central that the parent type of guncrafting, which should never appear in this reality, has appeared. Whatever that means." + icon = 'icons/obj/guns/gun_parts.dmi' + icon_state = "palette" + +// BARRELS + +/obj/item/weaponcrafting/improvised_parts/barrel_rifle + name = "rifle barrel" + desc = "A pipe with a diameter just the right size to fire 7.62 rounds out of." + icon_state = "barrel_rifle" + +/obj/item/weaponcrafting/improvised_parts/barrel_shotgun + name = "shotgun barrel" + desc = "A twenty bore shotgun barrel." + icon_state = "barrel_shotgun" + +// RECEIVERS + +/obj/item/weaponcrafting/improvised_parts/rifle_receiver + name = "bolt action receiver" + desc = "A crudely constructed receiver to create an improvised bolt-action breechloaded rifle." + icon_state = "receiver_rifle" + w_class = WEIGHT_CLASS_SMALL + +/obj/item/weaponcrafting/improvised_parts/shotgun_receiver + name = "break-action assembly" + desc = "An improvised receiver to create a break-action breechloaded shotgun." + icon_state = "receiver_shotgun" + w_class = WEIGHT_CLASS_SMALL + +// MISC + +/obj/item/weaponcrafting/improvised_parts/trigger_assembly + name = "firearm trigger assembly" + desc = "A modular trigger assembly with a firing pin, this can be used to make a whole bunch of improvised firearss." + icon_state = "trigger_assembly" + w_class = WEIGHT_CLASS_SMALL + +/obj/item/weaponcrafting/improvised_parts/wooden_body + name = "wooden firearm body" + desc = "A crudely fashioned wooden body to help keep higher calibre improvised weapons from blowing themselves apart." + icon_state = "wooden_body" + diff --git a/code/datums/components/crafting/recipes/recipes_primal.dm b/code/datums/components/crafting/recipes/recipes_primal.dm index ae611e5855..bb4f4ce6d5 100644 --- a/code/datums/components/crafting/recipes/recipes_primal.dm +++ b/code/datums/components/crafting/recipes/recipes_primal.dm @@ -116,4 +116,41 @@ always_availible = FALSE reqs = list(/obj/item/stack/rods = 1, /obj/item/stack/sheet/mineral/sandstone = 4) - category = CAT_PRIMAL \ No newline at end of file + category = CAT_PRIMAL + +/datum/crafting_recipe/rib + name = "Collosal Rib" + always_availible = FALSE + reqs = list( + /obj/item/stack/sheet/bone = 10, + /datum/reagent/oil = 5) + result = /obj/structure/statue/bone/rib + subcategory = CAT_PRIMAL + +/datum/crafting_recipe/skull + name = "Skull Carving" + always_availible = FALSE + reqs = list( + /obj/item/stack/sheet/bone = 6, + /datum/reagent/oil = 5) + result = /obj/structure/statue/bone/skull + category = CAT_PRIMAL + +/datum/crafting_recipe/halfskull + name = "Cracked Skull Carving" + always_availible = FALSE + reqs = list( + /obj/item/stack/sheet/bone = 3, + /datum/reagent/oil = 5) + result = /obj/structure/statue/bone/skull/half + category = CAT_PRIMAL + +/datum/crafting_recipe/boneshovel + name = "Serrated Bone Shovel" + always_availible = FALSE + reqs = list( + /obj/item/stack/sheet/bone = 4, + /datum/reagent/oil = 5, + /obj/item/shovel/spade = 1) + result = /obj/item/shovel/serrated + category = CAT_PRIMAL diff --git a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm index 21a160264a..7d608a55b2 100644 --- a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm +++ b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm @@ -251,8 +251,10 @@ /datum/crafting_recipe/ishotgun name = "Improvised Shotgun" result = /obj/item/gun/ballistic/revolver/doublebarrel/improvised - reqs = list(/obj/item/weaponcrafting/receiver = 1, - /obj/item/pipe = 1, + reqs = list(/obj/item/weaponcrafting/improvised_parts/barrel_shotgun = 1, + /obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 1, + /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 1, + /obj/item/weaponcrafting/improvised_parts/wooden_body = 1, /obj/item/weaponcrafting/stock = 1, /obj/item/stack/packageWrap = 5) tools = list(TOOL_SCREWDRIVER) @@ -261,10 +263,12 @@ subcategory = CAT_WEAPON /datum/crafting_recipe/irifle - name = "Improvised Rifle(7.62mm)" + name = "Improvised Rifle (7.62mm)" result = /obj/item/gun/ballistic/shotgun/boltaction/improvised - reqs = list(/obj/item/weaponcrafting/receiver = 1, - /obj/item/pipe = 2, + reqs = list(/obj/item/weaponcrafting/improvised_parts/barrel_rifle = 1, + /obj/item/weaponcrafting/improvised_parts/rifle_receiver = 1, + /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 1, + /obj/item/weaponcrafting/improvised_parts/wooden_body = 1, /obj/item/weaponcrafting/stock = 1, /obj/item/stack/packageWrap = 5) tools = list(TOOL_SCREWDRIVER) @@ -394,3 +398,60 @@ time = 5 category = CAT_WEAPONRY subcategory = CAT_AMMO + +//////////////////// +// PARTS CRAFTING // +//////////////////// + +// BARRELS + +/datum/crafting_recipe/rifle_barrel + name = "Improvised Rifle Barrel" + result = /obj/item/weaponcrafting/improvised_parts/barrel_rifle + reqs = list(/obj/item/pipe = 2) + tools = list(TOOL_WELDER,TOOL_SAW) + time = 150 + category = CAT_WEAPONRY + subcategory = CAT_PARTS + +/datum/crafting_recipe/shotgun_barrel + name = "Improvised Shotgun Barrel" + result = /obj/item/weaponcrafting/improvised_parts/barrel_shotgun + reqs = list(/obj/item/pipe = 2) + tools = list(TOOL_WELDER,TOOL_SAW) + time = 150 + category = CAT_WEAPONRY + subcategory = CAT_PARTS + +// RECEIVERS + +/datum/crafting_recipe/rifle_receiver + name = "Improvised Rifle Receiver" + result = /obj/item/weaponcrafting/improvised_parts/rifle_receiver + reqs = list(/obj/item/stack/sheet/metal = 20) + tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) // Rifle is the easiest to craft and can be made at an autolathe, this is a very light kick in the shin for dual-wielding ishotguns. + time = 50 + category = CAT_WEAPONRY + subcategory = CAT_PARTS + +/datum/crafting_recipe/shotgun_receiver + name = "Improvised Shotgun Receiver" + result = /obj/item/weaponcrafting/improvised_parts/shotgun_receiver + reqs = list(/obj/item/stack/sheet/metal = 10, + /obj/item/stack/sheet/plasteel = 1) + tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) // Increased cost is to stop dual-wield alpha striking. ishotgun is a rvolver and can be duel-wielded + time = 50 + category = CAT_WEAPONRY + subcategory = CAT_PARTS + +// MISC + +/datum/crafting_recipe/trigger_assembly + name = "Trigger Assembly" + result = /obj/item/weaponcrafting/improvised_parts/trigger_assembly + reqs = list(/obj/item/stack/sheet/metal = 3, + /obj/item/assembly/igniter = 1) + tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) + time = 150 + category = CAT_WEAPONRY + subcategory = CAT_PARTS diff --git a/code/datums/components/empprotection.dm b/code/datums/components/empprotection.dm deleted file mode 100644 index c85cdf31c7..0000000000 --- a/code/datums/components/empprotection.dm +++ /dev/null @@ -1,11 +0,0 @@ -/datum/component/empprotection - var/flags = NONE - -/datum/component/empprotection/Initialize(_flags) - if(!istype(parent, /atom)) - return COMPONENT_INCOMPATIBLE - flags = _flags - RegisterSignal(parent, list(COMSIG_ATOM_EMP_ACT), .proc/getEmpFlags) - -/datum/component/empprotection/proc/getEmpFlags(datum/source, severity) - return flags diff --git a/code/datums/components/fantasy/_fantasy.dm b/code/datums/components/fantasy/_fantasy.dm index a203264fae..8441f962f9 100644 --- a/code/datums/components/fantasy/_fantasy.dm +++ b/code/datums/components/fantasy/_fantasy.dm @@ -9,6 +9,7 @@ var/originalName var/list/affixes var/list/appliedComponents + var/list/appliedElements var/static/list/affixListing @@ -22,6 +23,7 @@ src.affixes = affixes appliedComponents = list() + appliedElements = list() randomAffixes() /datum/component/fantasy/Destroy() @@ -118,6 +120,8 @@ affix.remove(src) for(var/i in appliedComponents) qdel(i) + for(var/i in appliedElements) + master._RemoveElement(i) master.force = max(0, master.force - quality) master.throwforce = max(0, master.throwforce - quality) diff --git a/code/datums/components/fantasy/prefixes.dm b/code/datums/components/fantasy/prefixes.dm index 5ef2ac2baf..b6de85cab0 100644 --- a/code/datums/components/fantasy/prefixes.dm +++ b/code/datums/components/fantasy/prefixes.dm @@ -45,7 +45,8 @@ /datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName) var/obj/item/master = comp.parent - comp.appliedComponents += master.AddComponent(/datum/component/tactical) + master.AddElement(/datum/element/tactical) + comp.appliedElements += list(/datum/element/tactical) return "tactical [newName]" /datum/fantasy_affix/pyromantic diff --git a/code/datums/components/forced_gravity.dm b/code/datums/components/forced_gravity.dm deleted file mode 100644 index 100bcf781c..0000000000 --- a/code/datums/components/forced_gravity.dm +++ /dev/null @@ -1,20 +0,0 @@ -/datum/component/forced_gravity - var/gravity - var/ignore_space = FALSE //If forced gravity should also work on space turfs - -/datum/component/forced_gravity/Initialize(forced_value = 1) - if(!isatom(parent)) - return COMPONENT_INCOMPATIBLE - RegisterSignal(COMSIG_ATOM_HAS_GRAVITY, .proc/gravity_check) - if(isturf(parent)) - RegisterSignal(COMSIG_TURF_HAS_GRAVITY, .proc/turf_gravity_check) - - gravity = forced_value - -/datum/component/forced_gravity/proc/gravity_check(datum/source, turf/location, list/gravs) - if(!ignore_space && isspaceturf(location)) - return - gravs += gravity - -/datum/component/forced_gravity/proc/turf_gravity_check(datum/source, atom/checker, list/gravs) - return gravity_check(parent, gravs) \ No newline at end of file diff --git a/code/datums/components/lockon_aiming.dm b/code/datums/components/lockon_aiming.dm index 045611ab9d..2f4401862d 100644 --- a/code/datums/components/lockon_aiming.dm +++ b/code/datums/components/lockon_aiming.dm @@ -47,14 +47,11 @@ if(icon_state) lock_icon_state = icon_state generate_lock_visuals() - var/mob/M = parent - LAZYOR(M.mousemove_intercept_objects, src) + RegisterSignal(parent, COMSIG_MOB_CLIENT_MOUSEMOVE, .proc/onMouseMove) START_PROCESSING(SSfastprocess, src) /datum/component/lockon_aiming/Destroy() - var/mob/M = parent clear_visuals() - LAZYREMOVE(M.mousemove_intercept_objects, src) STOP_PROCESSING(SSfastprocess, src) return ..() @@ -120,7 +117,7 @@ return LAZYREMOVE(immune_weakrefs, A.weak_reference) -/datum/component/lockon_aiming/onMouseMove(object,location,control,params) +/datum/component/lockon_aiming/proc/onMouseMove(object,location,control,params) var/mob/M = parent if(!istype(M) || !M.client) return diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index 37d77a45bc..88ad75f345 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -321,6 +321,28 @@ if(0 to NUTRITION_LEVEL_STARVING) add_event(null, "nutrition", /datum/mood_event/starving) +/datum/component/mood/proc/update_beauty(area/A) + if(A.outdoors) //if we're outside, we don't care. + clear_event(null, "area_beauty") + return FALSE + if(HAS_TRAIT(parent, TRAIT_SNOB)) + switch(A.beauty) + if(-INFINITY to BEAUTY_LEVEL_HORRID) + add_event(null, "area_beauty", /datum/mood_event/horridroom) + return + if(BEAUTY_LEVEL_HORRID to BEAUTY_LEVEL_BAD) + add_event(null, "area_beauty", /datum/mood_event/badroom) + return + switch(A.beauty) + if(-INFINITY to BEAUTY_LEVEL_DECENT) + clear_event(null, "area_beauty") + if(BEAUTY_LEVEL_DECENT to BEAUTY_LEVEL_GOOD) + add_event(null, "area_beauty", /datum/mood_event/decentroom) + if(BEAUTY_LEVEL_GOOD to BEAUTY_LEVEL_GREAT) + add_event(null, "area_beauty", /datum/mood_event/goodroom) + if(BEAUTY_LEVEL_GREAT to INFINITY) + add_event(null, "area_beauty", /datum/mood_event/greatroom) + ///Called when parent is revived. /datum/component/mood/proc/on_revive(datum/source, full_heal) START_PROCESSING(SSdcs, src) diff --git a/code/datums/components/phantomthief.dm b/code/datums/components/phantomthief.dm index 57ab75f7a3..6b7e7221c3 100644 --- a/code/datums/components/phantomthief.dm +++ b/code/datums/components/phantomthief.dm @@ -20,7 +20,7 @@ valid_slots = _valid_slots /datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(mob/living/user, was_forced = FALSE) - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) user.remove_filter("phantomthief") else user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color)) diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm index 6a32a46aef..f5da669c3a 100644 --- a/code/datums/components/rotation.dm +++ b/code/datums/components/rotation.dm @@ -23,18 +23,12 @@ if(can_user_rotate) src.can_user_rotate = can_user_rotate - else - src.can_user_rotate = CALLBACK(src,.proc/default_can_user_rotate) if(can_be_rotated) src.can_be_rotated = can_be_rotated - else - src.can_be_rotated = CALLBACK(src,.proc/default_can_be_rotated) if(after_rotation) src.after_rotation = after_rotation - else - src.after_rotation = CALLBACK(src,.proc/default_after_rotation) //Try Clockwise,counter,flip in order if(src.rotation_flags & ROTATION_FLIP) @@ -103,14 +97,34 @@ examine_list += "Alt-click to rotate it clockwise." /datum/component/simple_rotation/proc/HandRot(datum/source, mob/user, rotation = default_rotation_direction) - if(!can_be_rotated.Invoke(user, rotation) || !can_user_rotate.Invoke(user, rotation)) - return + if(can_be_rotated) + if(!can_be_rotated.Invoke(user, default_rotation_direction)) + return + else + if(!default_can_be_rotated(user, default_rotation_direction)) + return + if(can_user_rotate) + if(!can_user_rotate.Invoke(user, default_rotation_direction)) + return + else + if(!default_can_user_rotate(user, default_rotation_direction)) + return BaseRot(user, rotation) return TRUE /datum/component/simple_rotation/proc/WrenchRot(datum/source, obj/item/I, mob/living/user) - if(!can_be_rotated.Invoke(user,default_rotation_direction) || !can_user_rotate.Invoke(user,default_rotation_direction)) - return + if(can_be_rotated) + if(!can_be_rotated.Invoke(user, default_rotation_direction)) + return + else + if(!default_can_be_rotated(user, default_rotation_direction)) + return + if(can_user_rotate) + if(!can_user_rotate.Invoke(user, default_rotation_direction)) + return + else + if(!default_can_user_rotate(user, default_rotation_direction)) + return if(istype(I,/obj/item/wrench)) BaseRot(user,default_rotation_direction) return COMPONENT_NO_AFTERATTACK @@ -126,7 +140,10 @@ if(ROTATION_FLIP) rot_degree = 180 AM.setDir(turn(AM.dir,rot_degree)) - after_rotation.Invoke(user,rotation_type) + if(after_rotation) + after_rotation.Invoke(user, rotation_type) + else + default_after_rotation(user, rotation_type) /datum/component/simple_rotation/proc/default_can_user_rotate(mob/living/user, rotation_type) if(!istype(user) || !user.canUseTopic(parent, BE_CLOSE, NO_DEXTERY)) diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm index e044a59668..55c3e1d083 100644 --- a/code/datums/components/storage/concrete/_concrete.dm +++ b/code/datums/components/storage/concrete/_concrete.dm @@ -136,9 +136,7 @@ var/mob/M = parent.loc I.dropped(M) if(new_location) - //Reset the items values - _removal_reset(AM) - AM.forceMove(new_location) + AM.forceMove(new_location) // exited comsig will handle removal reset. //We don't want to call this if the item is being destroyed AM.on_exit_storage(src) else diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 44ac865aa2..f93d40bb04 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -351,7 +351,6 @@ return master._removal_reset(thing) /datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing) - _removal_reset(thing) if(LAZYACCESS(ui_item_blocks, thing)) var/obj/screen/storage/volumetric_box/center/C = ui_item_blocks[thing] for(var/i in can_see_contents()) //runtimes result if mobs can access post deletion. @@ -359,6 +358,7 @@ M.client?.screen -= C.on_screen_objects() ui_item_blocks -= thing qdel(C) + _removal_reset(thing) // THIS NEEDS TO HAPPEN AFTER SO LAYERING DOESN'T BREAK! refresh_mob_views() //Call this proc to handle the removal of an item from the storage item. The item will be moved to the new_location target, if that is null it's being deleted diff --git a/code/datums/components/summoning.dm b/code/datums/components/summoning.dm index 61718301b3..1d66cf9307 100644 --- a/code/datums/components/summoning.dm +++ b/code/datums/components/summoning.dm @@ -59,7 +59,7 @@ var/mob/living/simple_animal/L = new chosen_mob_type(spawn_location) if(ishostile(L)) var/mob/living/simple_animal/hostile/H = L - H.friends += summoner // do not attack our summon boy + H.friends[summoner]++ // do not attack our summon boy spawned_mobs += L if(faction != null) L.faction = faction diff --git a/code/datums/components/tactical.dm b/code/datums/components/tactical.dm deleted file mode 100644 index b73c58604a..0000000000 --- a/code/datums/components/tactical.dm +++ /dev/null @@ -1,44 +0,0 @@ - -/datum/component/tactical - var/allowed_slot - -/datum/component/tactical/Initialize(allowed_slot) - if(!isitem(parent)) - return COMPONENT_INCOMPATIBLE - - src.allowed_slot = allowed_slot - -/datum/component/tactical/RegisterWithParent() - . = ..() - RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/modify) - RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/unmodify) - -/datum/component/tactical/UnregisterFromParent() - . = ..() - UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) - unmodify() - -/datum/component/tactical/Destroy() - unmodify() - return ..() - -/datum/component/tactical/proc/modify(obj/item/source, mob/user, slot) - if(allowed_slot && slot != allowed_slot) - unmodify() - return - - var/obj/item/master = parent - var/image/I = image(icon = master.icon, icon_state = master.icon_state, loc = user) - I.copy_overlays(master) - I.override = TRUE - source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I) - I.layer = ABOVE_MOB_LAYER - -/datum/component/tactical/proc/unmodify(obj/item/source, mob/user) - var/obj/item/master = source || parent - if(!user) - if(!ismob(master.loc)) - return - user = master.loc - - user.remove_alt_appearance("sneaking_mission") diff --git a/code/datums/dna.dm b/code/datums/dna.dm index ae0c540ef0..f569305211 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -395,17 +395,7 @@ return dna -/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, list/default_mutation_genes, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/mutations, force_transfer_mutations) -//Do not use force_transfer_mutations for stuff like cloners without some precautions, otherwise some conditional mutations could break (timers, drill hat etc) - if(newfeatures) - var/old_size = dna.features["body_size"] - dna.features = newfeatures - dna.update_body_size(old_size) - - if(mrace) - var/datum/species/newrace = new mrace.type - newrace.copy_properties_from(mrace) - set_species(newrace, icon_update=0) +/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures) if(newreal_name) real_name = newreal_name @@ -416,7 +406,17 @@ if(ui) dna.uni_identity = ui - updateappearance(icon_update=0) + updateappearance(icon_update=FALSE) + + if(newfeatures) + var/old_size = dna.features["body_size"] + dna.features = newfeatures + dna.update_body_size(old_size) + + if(mrace) + var/datum/species/newrace = new mrace.type + newrace.copy_properties_from(mrace) + set_species(newrace, icon_update=FALSE) if(LAZYLEN(mutation_index)) dna.mutation_index = mutation_index.Copy() diff --git a/code/datums/elements/art.dm b/code/datums/elements/art.dm new file mode 100644 index 0000000000..960d22af56 --- /dev/null +++ b/code/datums/elements/art.dm @@ -0,0 +1,64 @@ + +#define BAD_ART 12.5 +#define GOOD_ART 25 +#define GREAT_ART 50 + +/datum/element/art + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 2 + var/impressiveness = 0 + +/datum/element/art/Attach(datum/target, impress) + . = ..() + if(. == ELEMENT_INCOMPATIBLE || !isatom(target) || isarea(target)) + return ELEMENT_INCOMPATIBLE + impressiveness = impress + if(isobj(target)) + RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_obj_examine) + if(isstructure(target)) + RegisterSignal(target, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) + if(isitem(target)) + RegisterSignal(target, COMSIG_ITEM_ATTACK_SELF, .proc/apply_moodlet) + else + RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_other_examine) + +/datum/element/art/Detach(datum/target) + UnregisterSignal(target, list(COMSIG_PARENT_EXAMINE, COMSIG_ATOM_ATTACK_HAND, COMSIG_ITEM_ATTACK_SELF)) + return ..() + +/datum/element/art/proc/apply_moodlet(atom/source, mob/M, impress) + M.visible_message("[M] stops and looks intently at [source].", \ + "You stop to take in [source].") + switch(impress) + if (0 to BAD_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) + if (BAD_ART to GOOD_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) + if (GOOD_ART to GREAT_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) + if(GREAT_ART to INFINITY) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) + +/datum/element/art/proc/on_other_examine(atom/source, mob/M) + apply_moodlet(source, M, impressiveness) + +/datum/element/art/proc/on_obj_examine(atom/source, mob/M) + var/obj/O = source + apply_moodlet(source, M, impressiveness *(O.obj_integrity/O.max_integrity)) + +/datum/element/art/proc/on_attack_hand(atom/source, mob/M) + to_chat(M, "You start examining [source]...") + if(!do_after(M, 20, target = source)) + return + on_obj_examine(source, M) + +/datum/element/art/rev + +/datum/element/art/rev/apply_moodlet(atom/source, mob/M, impress) + M.visible_message("[M] stops to inspect [source].", \ + "You take in [source], inspecting the fine craftsmanship of the proletariat.") + + if(M.mind && M.mind.has_antag_datum(/datum/antagonist/rev)) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) + else + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) diff --git a/code/datums/elements/beauty.dm b/code/datums/elements/beauty.dm new file mode 100644 index 0000000000..8acfda73e1 --- /dev/null +++ b/code/datums/elements/beauty.dm @@ -0,0 +1,34 @@ +/datum/element/beauty + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 2 + var/beauty = 0 + +/datum/element/beauty/Attach(datum/target, beautyamount) + . = ..() + if(. == ELEMENT_INCOMPATIBLE || !isatom(target) || isarea(target)) + return ELEMENT_INCOMPATIBLE + beauty = beautyamount + RegisterSignal(target, COMSIG_ENTER_AREA, .proc/enter_area) + RegisterSignal(target, COMSIG_EXIT_AREA, .proc/exit_area) + var/area/A = get_area(target) + if(A) + enter_area(null, A) + +/datum/element/beauty/Detach(datum/target) + UnregisterSignal(target, list(COMSIG_ENTER_AREA, COMSIG_EXIT_AREA)) + var/area/A = get_area(target) + if(A) + exit_area(null, A) + return ..() + +/datum/element/beauty/proc/enter_area(datum/source, area/A) + if(A.outdoors) + return + A.totalbeauty += beauty + A.update_beauty() + +/datum/element/beauty/proc/exit_area(datum/source, area/A) + if(A.outdoors) + return + A.totalbeauty -= beauty + A.update_beauty() diff --git a/code/datums/elements/empprotection.dm b/code/datums/elements/empprotection.dm new file mode 100644 index 0000000000..c24914decb --- /dev/null +++ b/code/datums/elements/empprotection.dm @@ -0,0 +1,18 @@ +/datum/element/empprotection + element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE + id_arg_index = 2 + var/flags = NONE + +/datum/element/empprotection/Attach(datum/target, _flags) + . = ..() + if(. == ELEMENT_INCOMPATIBLE || !isatom(target)) + return ELEMENT_INCOMPATIBLE + flags = _flags + RegisterSignal(target, COMSIG_ATOM_EMP_ACT, .proc/getEmpFlags) + +/datum/element/empprotection/Detach(atom/target) + UnregisterSignal(target, COMSIG_ATOM_EMP_ACT) + return ..() + +/datum/element/empprotection/proc/getEmpFlags(datum/source, severity) + return flags diff --git a/code/datums/elements/forced_gravity.dm b/code/datums/elements/forced_gravity.dm new file mode 100644 index 0000000000..0b50df5b21 --- /dev/null +++ b/code/datums/elements/forced_gravity.dm @@ -0,0 +1,30 @@ +/datum/element/forced_gravity + element_flags = ELEMENT_BESPOKE + id_arg_index = 2 + var/gravity + var/ignore_space + +/datum/element/forced_gravity/Attach(datum/target, gravity=1, ignore_space=FALSE) + . = ..() + if(!isatom(target)) + return ELEMENT_INCOMPATIBLE + + src.gravity = gravity + src.ignore_space = ignore_space + + RegisterSignal(target, COMSIG_ATOM_HAS_GRAVITY, .proc/gravity_check) + if(isturf(target)) + RegisterSignal(target, COMSIG_TURF_HAS_GRAVITY, .proc/turf_gravity_check) + +/datum/element/forced_gravity/Detach(datum/source, force) + . = ..() + var/static/list/signals_b_gone = list(COMSIG_ATOM_HAS_GRAVITY, COMSIG_TURF_HAS_GRAVITY) + UnregisterSignal(source, signals_b_gone) + +/datum/element/forced_gravity/proc/gravity_check(datum/source, turf/location, list/gravs) + if(!ignore_space && isspaceturf(location)) + return + gravs += gravity + +/datum/element/forced_gravity/proc/turf_gravity_check(datum/source, atom/checker, list/gravs) + return gravity_check(null, source, gravs) diff --git a/code/datums/elements/tactical.dm b/code/datums/elements/tactical.dm new file mode 100644 index 0000000000..4b49552fbe --- /dev/null +++ b/code/datums/elements/tactical.dm @@ -0,0 +1,37 @@ +/datum/element/tactical + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 2 + var/allowed_slot + +/datum/element/tactical/Attach(datum/target, allowed_slot) + . = ..() + if(. == ELEMENT_INCOMPATIBLE || !isitem(target)) + return ELEMENT_INCOMPATIBLE + + src.allowed_slot = allowed_slot + RegisterSignal(target, COMSIG_ITEM_EQUIPPED, .proc/modify) + RegisterSignal(target, COMSIG_ITEM_DROPPED, .proc/unmodify) + +/datum/element/tactical/Detach(datum/target) + UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) + unmodify(target) + return ..() + +/datum/element/tactical/proc/modify(obj/item/source, mob/user, slot) + if(allowed_slot && slot != allowed_slot) + unmodify(source, user) + return + + var/image/I = image(icon = source.icon, icon_state = source.icon_state, loc = user) + I.copy_overlays(source) + I.override = TRUE + source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I) + I.layer = ABOVE_MOB_LAYER + +/datum/element/tactical/proc/unmodify(obj/item/source, mob/user) + if(!user) + if(!ismob(source.loc)) + return + user = source.loc + + user.remove_alt_appearance("sneaking_mission") diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm index e54a80bd81..0877e4021a 100644 --- a/code/datums/martial/_martial.dm +++ b/code/datums/martial/_martial.dm @@ -39,11 +39,11 @@ /datum/martial_art/proc/damage_roll(mob/living/carbon/human/A, mob/living/carbon/human/D) //Here we roll for our damage to be added into the damage var in the various attack procs. This is changed depending on whether we are in combat mode, lying down, or if our target is in combat mode. var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh) - if(!(D.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(D, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) damage *= 1.5 if(!CHECK_MOBILITY(A, MOBILITY_STAND)) damage *= 0.5 - if(!(A.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(A, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) damage *= 0.25 return damage @@ -83,7 +83,7 @@ var/datum/martial_art/X = H.mind.default_martial_art X.teach(H) REMOVE_TRAIT(H, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT) - + /datum/martial_art/proc/on_remove(mob/living/carbon/human/H) if(help_verb) H.verbs -= help_verb diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index c658ac215d..1a8ce755e1 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -24,6 +24,8 @@ Simple datum which is instanced once per type and is used for every object of sa var/value_per_unit = 0 ///Armor modifiers, multiplies an items normal armor vars by these amounts. var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1) + ///How beautiful is this material per unit? + var/beauty_modifier = 0 ///This proc is called when the material is added to an object. /datum/material/proc/on_applied(atom/source, amount, material_flags) @@ -39,6 +41,9 @@ Simple datum which is instanced once per type and is used for every object of sa if(istype(source, /obj)) //objs on_applied_obj(source, amount, material_flags) + if(beauty_modifier) + addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0) + ///This proc is called when the material is added to an object specifically. /datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags) if(material_flags & MATERIAL_AFFECT_STATISTICS) diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index f189a91353..d4921a04d2 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -19,6 +19,7 @@ integrity_modifier = 0.1 sheet_type = /obj/item/stack/sheet/glass value_per_unit = 0.0025 + beauty_modifier = 0.05 armor_modifiers = list("melee" = 0.2, "bullet" = 0.2, "laser" = 0, "energy" = 1, "bomb" = 0, "bio" = 0.2, "rad" = 0.2, "fire" = 1, "acid" = 0.2) // yeah ok /* @@ -35,6 +36,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/silver value_per_unit = 0.025 + beauty_modifier = 0.075 ///Slight force increase /datum/material/gold @@ -46,6 +48,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/gold value_per_unit = 0.0625 + beauty_modifier = 0.15 armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 1.15, "energy" = 1.15, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1.1) ///Has no special properties @@ -58,6 +61,8 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/diamond value_per_unit = 0.25 + beauty_modifier = 0.3 + armor_modifiers = list("melee" = 1.3, "bullet" = 1.3, "laser" = 0.6, "energy" = 1, "bomb" = 1.2, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1) ///Is slightly radioactive /datum/material/uranium @@ -68,6 +73,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/uranium value_per_unit = 0.05 + beauty_modifier = 0.3 //It shines so beautiful armor_modifiers = list("melee" = 1.5, "bullet" = 1.4, "laser" = 0.5, "energy" = 0.5, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 1, "acid" = 1) /datum/material/uranium/on_applied(atom/source, amount, material_flags) @@ -88,6 +94,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/plasma value_per_unit = 0.1 + beauty_modifier = 0.15 armor_modifiers = list("melee" = 1.4, "bullet" = 0.7, "laser" = 0, "energy" = 1.2, "bomb" = 0, "bio" = 1.2, "rad" = 1, "fire" = 0, "acid" = 0.5) /datum/material/plasma/on_applied(atom/source, amount, material_flags) @@ -109,6 +116,7 @@ Unless you know what you're doing, only use the first three numbers. They're in color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) alpha = 200 categories = list(MAT_CATEGORY_ORE = TRUE) + beauty_modifier = 0.5 sheet_type = /obj/item/stack/sheet/bluespace_crystal value_per_unit = 0.15 @@ -121,6 +129,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/bananium value_per_unit = 0.5 + beauty_modifier = 0.5 armor_modifiers = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 10, "acid" = 0) //Clowns cant be blown away /datum/material/bananium/on_applied(atom/source, amount, material_flags) @@ -144,6 +153,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/titanium value_per_unit = 0.0625 + beauty_modifier = 0.05 armor_modifiers = list("melee" = 1.35, "bullet" = 1.3, "laser" = 1.3, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1) /datum/material/runite @@ -154,6 +164,7 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 1.3 categories = list(MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/runite + beauty_modifier = 0.5 armor_modifiers = list("melee" = 1.35, "bullet" = 2, "laser" = 0.5, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 1.4, "acid" = 1) //rune is weak against magic lasers but strong against bullets. This is the combat triangle. ///Force decrease @@ -165,6 +176,7 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 0.85 sheet_type = /obj/item/stack/sheet/plastic value_per_unit = 0.0125 + beauty_modifier = -0.01 armor_modifiers = list("melee" = 1.5, "bullet" = 1.1, "laser" = 0.3, "energy" = 0.5, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1.1, "acid" = 1) ///Force decrease and mushy sound effect. (Not yet implemented) @@ -176,6 +188,30 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 0.8 value_per_unit = 0.025 +/datum/material/wood + name = "wood" + id = "wood" + desc = "Flexible, durable, but flamable. Hard to come across in space." + color = "#bb8e53" + strength_modifier = 0.5 + sheet_type = /obj/item/stack/sheet/mineral/wood + categories = list(MAT_CATEGORY_RIGID = TRUE) + value_per_unit = 0.06 + beauty_modifier = 0.1 + armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 0.4, "energy" = 0.4, "bomb" = 1, "bio" = 0.2, "rad" = 0, "fire" = 0, "acid" = 0.3) + +/datum/material/wood/on_applied_obj(obj/source, amount, material_flags) + . = ..() + if(material_flags & MATERIAL_AFFECT_STATISTICS) + var/obj/wooden = source + wooden.resistance_flags |= FLAMMABLE + +/datum/material/wood/on_removed_obj(obj/source, material_flags) + . = ..() + if(material_flags & MATERIAL_AFFECT_STATISTICS) + var/obj/wooden = source + wooden.resistance_flags &= ~FLAMMABLE + ///Stronk force increase /datum/material/adamantine name = "adamantine" @@ -186,6 +222,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/adamantine value_per_unit = 0.25 + beauty_modifier = 0.4 armor_modifiers = list("melee" = 1.5, "bullet" = 1.5, "laser" = 1.3, "energy" = 1.3, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 2.5, "acid" = 1) ///RPG Magic. (Admin only) @@ -197,6 +234,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/mythril value_per_unit = 0.75 + beauty_modifier = 0.5 armor_modifiers = list("melee" = 2, "bullet" = 2, "laser" = 2, "energy" = 2, "bomb" = 2, "bio" = 2, "rad" = 2, "fire" = 2, "acid" = 2) /datum/material/mythril/on_applied_obj(atom/source, amount, material_flags) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index b7eac62e83..fb91edb2c9 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -97,9 +97,6 @@ if(current) // remove ourself from our old body's mind variable current.mind = null SStgui.on_transfer(current, new_character) - if(iscarbon(current)) - var/mob/living/carbon/C = current - C.disable_intentional_combat_mode(TRUE) if(key) if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index c56425b074..f5692c297a 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -153,7 +153,13 @@ mood_change = -4 timeout = 2400 +/datum/mood_event/graverobbing + description ="I just desecrated someone's grave... I can't believe I did that...\n" + mood_change = -8 + timeout = 3 MINUTES + //These are unused so far but I want to remember them to use them later + /datum/mood_event/cloned_corpse description = "I recently saw my own corpse...\n" mood_change = -6 @@ -162,6 +168,8 @@ description = "HE'S CUTTING ME OPEN!!\n" mood_change = -8 +//End unused + /datum/mood_event/sad_empath description = "Someone seems upset...\n" mood_change = -2 @@ -199,6 +207,8 @@ mood_change = -2 timeout = 1 MINUTES +//Cursed stuff end. + /datum/mood_event/vampcandle description = "Something is making your mind feel... loose...\n" mood_change = -15 diff --git a/code/datums/position_point_vector.dm b/code/datums/position_point_vector.dm index 608683c3dc..482e15c57d 100644 --- a/code/datums/position_point_vector.dm +++ b/code/datums/position_point_vector.dm @@ -189,6 +189,12 @@ x += mpx * (multiplier) y += mpy * (multiplier) +/datum/point/vector/proc/pixel_increment(pixels = 32, update_iteration = TRUE, realistic_iteration = FALSE) + if(update_iteration) + iteration += realistic_iteration? round(pixels / speed) : 1 + x += sin(angle) * pixels + y += cos(angle) * pixels + /datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE) var/datum/point/vector/v = copy_to() if(force_simulate) diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index 8f3811ca71..933eaf082e 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -250,4 +250,12 @@ cost = 5 placement_weight = 3 always_place = TRUE - allow_duplicates = TRUE + allow_duplicates = TRUE + +/datum/map_template/ruin/lavaland/elephant_graveyard + name = "Elephant Graveyard" + id = "Graveyard" + description = "An abandoned graveyard, calling to those unable to continue." + suffix = "lavaland_surface_elephant_graveyard.dmm" + allow_duplicates = FALSE + cost = 10 diff --git a/code/datums/tgs_event_handler.dm b/code/datums/tgs_event_handler.dm index a3324121bf..731be64183 100644 --- a/code/datums/tgs_event_handler.dm +++ b/code/datums/tgs_event_handler.dm @@ -1,3 +1,6 @@ +/datum/tgs_event_handler/impl + var/datum/timedevent/reattach_timer + /datum/tgs_event_handler/impl/HandleEvent(event_code, ...) switch(event_code) if(TGS_EVENT_REBOOT_MODE_CHANGE) @@ -18,3 +21,19 @@ if(TGS_EVENT_DEPLOYMENT_COMPLETE) message_admins("TGS: Deployment complete!") to_chat(world, "Server updated, changes will be applied on the next round...") + if(TGS_EVENT_WATCHDOG_DETACH) + message_admins("TGS restarting...") + reattach_timer = addtimer(CALLBACK(src, .proc/LateOnReattach), 1 MINUTES) + if(TGS_EVENT_WATCHDOG_REATTACH) + var/datum/tgs_version/old_version = world.TgsVersion() + var/datum/tgs_version/new_version = args[2] + if(!old_version.Equals(new_version)) + to_chat(world, "TGS updated to v[old_version.deprefixed_parameter]") + else + message_admins("TGS: Back online") + if(reattach_timer) + deltimer(reattach_timer) + reattach_timer = null + +/datum/tgs_event_handler/impl/proc/LateOnReattach() + message_admins("Warning: TGS hasn't notified us of it coming back for a full minute! Is there a problem?") diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index d1b5240798..4b039aa1b5 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -10,6 +10,15 @@ lose_text = "You can taste again!" medical_record_text = "Patient suffers from ageusia and is incapable of tasting food or reagents." +/datum/quirk/snob + name = "Snob" + desc = "You care about the finer things, if a room doesn't look nice its just not really worth it, is it?" + value = 0 + gain_text = "You feel like you understand what things should look like." + lose_text = "Well who cares about deco anyways?" + medical_record_text = "Patient seems to be rather stuck up." + mob_trait = TRAIT_SNOB + /datum/quirk/pineapple_liker name = "Ananas Affinity" desc = "You find yourself greatly enjoying fruits of the ananas genus. You can't seem to ever get enough of their sweet goodness!" diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index ce9513609a..75bd4f5c17 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -11,9 +11,6 @@ if(A.attachable) return TRUE -/atom - var/datum/wires/wires = null - /atom/proc/attempt_wire_interaction(mob/user) if(!wires) return WIRE_INTERACTION_FAIL diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index 997c77aa51..19b2b8dda8 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -30,6 +30,7 @@ if(WIRE_POWER1, WIRE_POWER2) // Short for a long while. if(!A.shorted) A.shorted = TRUE + A.update() addtimer(CALLBACK(A, /obj/machinery/power/apc.proc/reset, wire), 1200) if(WIRE_IDSCAN) // Unlock for a little while. A.locked = FALSE @@ -49,6 +50,7 @@ else A.shorted = TRUE A.shock(usr, 50) + A.update() if(WIRE_AI) // Disable AI control. if(mend) A.aidisabled = FALSE diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 5fac1a4b65..dabbe93bec 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -38,6 +38,10 @@ var/poweralm = TRUE var/lightswitch = TRUE + var/totalbeauty = 0 //All beauty in this area combined, only includes indoor area. + var/beauty = 0 // Beauty average per open turf in the area + var/beauty_threshold = 150 //If a room is too big it doesn't have beauty. + var/requires_power = TRUE /// This gets overridden to 1 for space in area/Initialize(). var/always_unpowered = FALSE @@ -65,7 +69,7 @@ /// Hides area from player Teleport function. var/hidden = FALSE /// Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers - var/safe = FALSE + var/safe = FALSE /// If false, loading multiple maps with this area type will create multiple instances. var/unique = TRUE @@ -192,6 +196,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) /area/LateInitialize() if(!base_area) //we don't want to run it twice. power_change() // all machines set to current power level, also updates icon + update_beauty() /area/proc/reg_in_areas_in_z() if(contents.len) @@ -538,6 +543,16 @@ GLOBAL_LIST_EMPTY(teleportlocs) L.client.played = TRUE addtimer(CALLBACK(L.client, /client/proc/ResetAmbiencePlayed), 600) +///Divides total beauty in the room by roomsize to allow us to get an average beauty per tile. +/area/proc/update_beauty() + if(!areasize) + beauty = 0 + return FALSE + if(areasize >= beauty_threshold) + beauty = 0 + return FALSE //Too big + beauty = totalbeauty / areasize + /area/Exited(atom/movable/M) SEND_SIGNAL(src, COMSIG_AREA_EXITED, M) SEND_SIGNAL(M, COMSIG_EXIT_AREA, src) //The atom that exits the area diff --git a/code/game/area/areas/centcom.dm b/code/game/area/areas/centcom.dm index 1241b7a240..96b621acd8 100644 --- a/code/game/area/areas/centcom.dm +++ b/code/game/area/areas/centcom.dm @@ -32,7 +32,8 @@ /area/centcom/vip name = "VIP Zone" dynamic_lighting = DYNAMIC_LIGHTING_DISABLED - /area/centcom/winterball + +/area/centcom/winterball name = "winterball Zone" dynamic_lighting = DYNAMIC_LIGHTING_DISABLED diff --git a/code/game/area/areas/ruins/lavaland.dm b/code/game/area/areas/ruins/lavaland.dm index 76f090d5e3..19a1fd503d 100644 --- a/code/game/area/areas/ruins/lavaland.dm +++ b/code/game/area/areas/ruins/lavaland.dm @@ -32,6 +32,14 @@ /area/ruin/powered/seedvault icon_state = "dk_yellow" +/area/ruin/unpowered/elephant_graveyard + name = "Elephant Graveyard" + icon_state = "dk_yellow" + +/area/ruin/powered/graveyard_shuttle + name = "Elephant Graveyard" + icon_state = "green" + /area/ruin/unpowered/syndicate_lava_base name = "Secret Base" icon_state = "dk_yellow" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1a0507f9df..486ad71a95 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -47,6 +47,8 @@ ///Modifier that raises/lowers the effect of the amount of a material, prevents small and easy to get items from being death machines. var/material_modifier = 1 + var/datum/wires/wires = null + var/icon/blood_splatter_icon var/list/fingerprints var/list/fingerprintshidden @@ -313,10 +315,11 @@ . += desc if(custom_materials) + var/list/materials_list = list() for(var/i in custom_materials) var/datum/material/M = i - . += "It is made out of [M.name]." - + materials_list += "[M.name]" + . += "It is made out of [english_list(materials_list)]." if(reagents) if(reagents.reagents_holder_flags & TRANSPARENT) . += "It contains:" diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 2e5dae3e04..68a9c1ce07 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -36,6 +36,7 @@ targetitem = /obj/item/gun/energy/e_gun/hos difficulty = 10 excludefromjob = list("Head Of Security") + altitems = list(/obj/item/gun/ballistic/revolver/mws) /datum/objective_item/steal/handtele name = "a hand teleporter." diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index e1fbb636c8..e97d276296 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -2,8 +2,7 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE) -/mob - var/datum/hSB/sandbox = null + /mob/proc/CanBuild() sandbox = new/datum/hSB sandbox.owner = src.ckey diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 02d3ccab46..a4beccecbb 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -434,3 +434,45 @@ /obj/machinery/sleeper/old icon_state = "oldpod" + +/obj/machinery/sleeper/party + name = "party pod" + desc = "'Sleeper' units were once known for their healing properties, until a lengthy investigation revealed they were also dosing patients with deadly lead acetate. This appears to be one of those old 'sleeper' units repurposed as a 'Party Pod'. It’s probably not a good idea to use it." + icon_state = "partypod" + idle_power_usage = 3000 + circuit = /obj/item/circuitboard/machine/sleeper/party + var/leddit = FALSE //Get it like reddit and lead alright fine + ui_x = 310 + ui_y = 400 + + controls_inside = TRUE + possible_chems = list( + list(/datum/reagent/consumable/ethanol/beer, /datum/reagent/consumable/laughter), + list(/datum/reagent/spraytan,/datum/reagent/barbers_aid), + list(/datum/reagent/colorful_reagent,/datum/reagent/hair_dye), + list(/datum/reagent/drug/space_drugs,/datum/reagent/baldium) + )//Exclusively uses non-lethal, "fun" chems. At an obvious downside. + var/spray_chems = list( + /datum/reagent/spraytan, /datum/reagent/hair_dye, /datum/reagent/baldium, /datum/reagent/barbers_aid + )//Chemicals that need to have a touch or vapor reaction to be applied, not the standard chamber reaction. + enter_message = "You're surrounded by some funky music inside the chamber. You zone out as you feel waves of krunk vibe within you." + +/obj/machinery/sleeper/party/inject_chem(chem, mob/user) + if(leddit) + occupant.reagents.add_reagent(/datum/reagent/toxin/leadacetate, 4) //You're injecting chemicals into yourself from a recalled, decrepit medical machine. What did you expect? + else if (prob(20)) + occupant.reagents.add_reagent(/datum/reagent/toxin/leadacetate, rand(1,3)) + if(chem in spray_chems) + var/datum/reagents/holder = new() + holder.add_reagent(chem_buttons[chem], 10) //I hope this is the correct way to do this. + holder.reaction(occupant, VAPOR, 0) + holder.trans_to(occupant, 10) + playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE, -6) + if(user) + log_combat(user, occupant, "sprayed [chem] into", addition = "via [src]") + return TRUE + ..() + +/obj/machinery/sleeper/party/emag_act(mob/user) + ..() + leddit = TRUE diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 3b32213509..4eeb6b8b0f 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -60,7 +60,8 @@ /datum/material/runite, /datum/material/plastic, /datum/material/adamantine, - /datum/material/mythril + /datum/material/mythril, + /datum/material/wood ) /// Base print speed diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 00d62aa251..4661e1bd8f 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -3,7 +3,6 @@ desc = "A remote control switch." icon = 'icons/obj/stationobjs.dmi' icon_state = "doorctrl" - plane = ABOVE_WALL_PLANE var/skin = "doorctrl" power_channel = ENVIRON var/obj/item/assembly/device @@ -17,10 +16,13 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF /obj/machinery/button/Initialize(mapload, ndir = 0, built = 0) - if(istext(id) && mapload) - if(id[1] == "!") - id = SSmapping.get_obfuscated_id(id) + if(istext(id) && mapload && id[1] == "!") + id = SSmapping.get_obfuscated_id(id) . = ..() + var/turf/T = get_turf_pixel(src) + if(iswallturf(T)) + plane = ABOVE_WALL_PLANE + if(built) setDir(ndir) pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) @@ -28,7 +30,6 @@ panel_open = TRUE update_icon() - if(!built && !device && device_type) device = new device_type(src) diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 021232f435..33e250fa59 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -75,7 +75,7 @@ // UPGRADE PROCS /obj/machinery/camera/proc/upgradeEmpProof() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS) assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly)) upgrades |= CAMERA_UPGRADE_EMP_PROOF diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 1066261f85..a9127e6f9e 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -225,12 +225,17 @@ desc = "Used for watching an empty arena." icon = 'icons/obj/stationobjs.dmi' icon_state = "telescreen" - plane = ABOVE_WALL_PLANE network = list("thunder") density = FALSE circuit = null light_power = 0 +/obj/machinery/computer/security/telescreen/Initialize() + . = ..() + var/turf/T = get_turf_pixel(src) + if(iswallturf(T)) + plane = ABOVE_WALL_PLANE + /obj/machinery/computer/security/telescreen/update_icon_state() icon_state = initial(icon_state) if(stat & BROKEN) diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 67113fcf78..a2d3cccc35 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -70,14 +70,13 @@ if(W.amount < 5) to_chat(user, "You need at least five wooden planks to make a wall!") return - else - to_chat(user, "You start adding [I] to [src]...") - if(do_after(user, 50, target=src)) - W.use(5) - var/turf/T = get_turf(src) - T.PlaceOnTop(/turf/closed/wall/mineral/wood/nonmetal) - qdel(src) - return + to_chat(user, "You start adding [I] to [src]...") + if(do_after(user, 50, target=src)) + W.use(5) + var/turf/T = get_turf(src) + T.PlaceOnTop(/turf/closed/wall/mineral/wood/nonmetal) + qdel(src) + return return ..() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index d511ff0c95..7b4e598b17 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -474,15 +474,15 @@ if(welded) weld_overlay = get_airlock_overlay("welded", overlays_file) if(obj_integrity < integrity_failure * max_integrity) - damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) else if(obj_integrity < (0.75 * max_integrity)) - damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(lights && hasPower()) if(locked) - lights_overlay = get_airlock_overlay("lights_bolts", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + lights_overlay = get_airlock_overlay("lights_bolts", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) else if(emergency) - lights_overlay = get_airlock_overlay("lights_emergency", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + lights_overlay = get_airlock_overlay("lights_emergency", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(note) note_overlay = get_airlock_overlay(notetype, note_overlay_file) @@ -500,18 +500,18 @@ else panel_overlay = get_airlock_overlay("panel_closed", overlays_file) if(obj_integrity < integrity_failure * max_integrity) - damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) else if(obj_integrity < (0.75 * max_integrity)) - damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(welded) weld_overlay = get_airlock_overlay("welded", overlays_file) - lights_overlay = get_airlock_overlay("lights_denied", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + lights_overlay = get_airlock_overlay("lights_denied", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(note) note_overlay = get_airlock_overlay(notetype, note_overlay_file) if(AIRLOCK_EMAG) frame_overlay = get_airlock_overlay("closed", icon) - sparks_overlay = get_airlock_overlay("sparks", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + sparks_overlay = get_airlock_overlay("sparks", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(airlock_material) filling_overlay = get_airlock_overlay("[airlock_material]_closed", overlays_file) else @@ -522,9 +522,9 @@ else panel_overlay = get_airlock_overlay("panel_closed", overlays_file) if(obj_integrity < integrity_failure * max_integrity) - damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) else if(obj_integrity < (0.75 * max_integrity)) - damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(welded) weld_overlay = get_airlock_overlay("welded", overlays_file) if(note) @@ -537,7 +537,7 @@ else filling_overlay = get_airlock_overlay("fill_closing", icon) if(lights && hasPower()) - lights_overlay = get_airlock_overlay("lights_closing", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + lights_overlay = get_airlock_overlay("lights_closing", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(panel_open) if(security_level) panel_overlay = get_airlock_overlay("panel_closing_protected", overlays_file) @@ -558,7 +558,7 @@ else panel_overlay = get_airlock_overlay("panel_open", overlays_file) if(obj_integrity < (0.75 * max_integrity)) - damag_overlay = get_airlock_overlay("sparks_open", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + damag_overlay = get_airlock_overlay("sparks_open", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(note) note_overlay = get_airlock_overlay("[notetype]_open", note_overlay_file) @@ -569,7 +569,7 @@ else filling_overlay = get_airlock_overlay("fill_opening", icon) if(lights && hasPower()) - lights_overlay = get_airlock_overlay("lights_opening", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) + lights_overlay = get_airlock_overlay("lights_opening", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) if(panel_open) if(security_level) panel_overlay = get_airlock_overlay("panel_opening_protected", overlays_file) @@ -581,11 +581,17 @@ cut_overlays() add_overlay(frame_overlay) add_overlay(filling_overlay) - add_overlay(lights_overlay) + if(lights_overlay) + add_overlay(lights_overlay) + var/mutable_appearance/lights_vis = mutable_appearance(lights_overlay.icon, lights_overlay.icon_state) + add_overlay(lights_vis) add_overlay(panel_overlay) add_overlay(weld_overlay) add_overlay(sparks_overlay) - add_overlay(damag_overlay) + if(damag_overlay) + add_overlay(damag_overlay) + var/mutable_appearance/damage_vis = mutable_appearance(damag_overlay.icon, damag_overlay.icon_state) + add_overlay(damage_vis) add_overlay(note_overlay) check_unres() diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index c4c712ca25..98a888fa66 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -290,8 +290,6 @@ operating = TRUE do_animate("closing") layer = closingLayer - if(!safe) - crush() sleep(5) density = TRUE sleep(5) @@ -303,6 +301,8 @@ update_freelook_sight() if(safe) CheckForMobs() + else + crush() return 1 /obj/machinery/door/proc/CheckForMobs() diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index 87e8c8f6a7..362dde1157 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -53,7 +53,9 @@ if("opening") rad_insulation = 1 if("closing") - rad_insulation = 0.2 + rad_insulation = -0.5 + +// A 3x3 N2 SM setup won't irradiate you if you're behind the shutter at -0.9 insulation. If it starts to delam, it'll start irradiating you slowly. Keep the value between -0.1 to -0.9 /obj/machinery/door/poddoor/shutters/window name = "windowed shutters" diff --git a/code/game/machinery/hypnochair.dm b/code/game/machinery/hypnochair.dm new file mode 100644 index 0000000000..1b57f61b79 --- /dev/null +++ b/code/game/machinery/hypnochair.dm @@ -0,0 +1,205 @@ +/obj/machinery/hypnochair + name = "enhanced interrogation chamber" + desc = "A device used to perform \"enhanced interrogation\" through invasive mental conditioning." + icon = 'icons/obj/machines/implantchair.dmi' + icon_state = "hypnochair" + circuit = /obj/item/circuitboard/machine/hypnochair + density = TRUE + opacity = 0 + ui_x = 375 + ui_y = 480 + var/mob/living/carbon/victim = null ///Keeps track of the victim to apply effects if it teleports away + var/interrogating = FALSE ///Is the device currently interrogating someone? + var/start_time = 0 ///Time when the interrogation was started, to calculate effect in case of interruption + var/trigger_phrase = "" ///Trigger phrase to implant + var/timerid = 0 ///Timer ID for interrogations + + var/message_cooldown = 0 ///Cooldown for breakout message + +/obj/machinery/hypnochair/Initialize() + . = ..() + open_machine() + update_icon() + +/obj/machinery/hypnochair/attackby(obj/item/I, mob/user, params) + if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I)) + update_icon() + return + + if(default_pry_open(I)) + return + + if(default_deconstruction_crowbar(I)) + return + + return ..() + +/obj/machinery/hypnochair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "hypnochair", name, ui_x, ui_y, master_ui, state) + ui.open() + +/obj/machinery/hypnochair/ui_data() + var/list/data = list() + data["occupied"] = occupant ? TRUE : FALSE + data["open"] = state_open + data["interrogating"] = interrogating + + data["occupant"] = list() + if(occupant) + var/mob/living/mob_occupant = occupant + data["occupant"]["name"] = mob_occupant.name + data["occupant"]["stat"] = mob_occupant.stat + + data["trigger"] = trigger_phrase + + return data + +/obj/machinery/hypnochair/ui_act(action, params) + if(..()) + return + switch(action) + if("door") + if(state_open) + close_machine() + else + if(!interrogating) + open_machine() + . = TRUE + if("set_phrase") + set_phrase(params["phrase"]) + . = TRUE + if("interrogate") + if(!interrogating) + interrogate() + else + interrupt_interrogation() + . = TRUE + +/obj/machinery/hypnochair/proc/set_phrase(phrase) + trigger_phrase = phrase + +/obj/machinery/hypnochair/proc/interrogate() + if(!trigger_phrase) + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, TRUE) + return + var/mob/living/carbon/C = occupant + if(!istype(C)) + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, TRUE) + return + victim = C + if(!(C.get_eye_protection() > 0)) + to_chat(C, "Strobing coloured lights assault you relentlessly! You're losing your ability to think straight!") + C.become_blind("hypnochair") + ADD_TRAIT(C, TRAIT_DEAF, "hypnochair") + interrogating = TRUE + START_PROCESSING(SSobj, src) + start_time = world.time + update_icon() + timerid = addtimer(CALLBACK(src, .proc/finish_interrogation), 450, TIMER_STOPPABLE) + +/obj/machinery/hypnochair/process() + var/mob/living/carbon/C = occupant + if(!istype(C) || C != victim) + interrupt_interrogation() + return + if(prob(10) && !(C.get_eye_protection() > 0)) + to_chat(C, "[pick(\ + "...blue... red... green... blue, red, green, blueredgreenblueredgreen",\ + "...pretty colors...",\ + "...you keep hearing words, but you can't seem to understand them...",\ + "...so peaceful...",\ + "...an annoying buzz in your ears..."\ + )]") + +/obj/machinery/hypnochair/proc/finish_interrogation() + interrogating = FALSE + STOP_PROCESSING(SSobj, src) + update_icon() + var/temp_trigger = trigger_phrase + trigger_phrase = "" //Erase evidence, in case the subject is able to look at the panel afterwards + audible_message("[src] pings!") + playsound(src, 'sound/machines/ping.ogg', 30, TRUE) + + if(QDELETED(victim) || victim != occupant) + victim = null + return + victim.cure_blind("hypnochair") + REMOVE_TRAIT(victim, TRAIT_DEAF, "hypnochair") + if(!(victim.get_eye_protection() > 0)) + victim.cure_trauma_type(/datum/brain_trauma/severe/hypnotic_trigger, TRAUMA_RESILIENCE_SURGERY) + if(prob(90)) + victim.gain_trauma(new /datum/brain_trauma/severe/hypnotic_trigger(temp_trigger), TRAUMA_RESILIENCE_SURGERY) + else + victim.gain_trauma(new /datum/brain_trauma/severe/hypnotic_stupor(), TRAUMA_RESILIENCE_SURGERY) + victim = null + +/obj/machinery/hypnochair/proc/interrupt_interrogation() + deltimer(timerid) + interrogating = FALSE + STOP_PROCESSING(SSobj, src) + update_icon() + + if(QDELETED(victim)) + victim = null + return + victim.cure_blind("hypnochair") + REMOVE_TRAIT(victim, TRAIT_DEAF, "hypnochair") + if(!(victim.get_eye_protection() > 0)) + var/time_diff = world.time - start_time + switch(time_diff) + if(0 to 100) + victim.confused += 10 + victim.Dizzy(100) + victim.blur_eyes(5) + if(101 to 200) + victim.confused += 15 + victim.Dizzy(200) + victim.blur_eyes(10) + if(prob(25)) + victim.apply_status_effect(/datum/status_effect/trance, rand(50,150), FALSE) + if(201 to INFINITY) + victim.confused += 20 + victim.Dizzy(300) + victim.blur_eyes(15) + if(prob(65)) + victim.apply_status_effect(/datum/status_effect/trance, rand(50,150), FALSE) + victim = null + +/obj/machinery/hypnochair/update_icon_state() + icon_state = initial(icon_state) + if(state_open) + icon_state += "_open" + if(occupant) + if(interrogating) + icon_state += "_active" + else + icon_state += "_occupied" + +/obj/machinery/hypnochair/container_resist(mob/living/user) + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message("You see [user] kicking against the door of [src]!", \ + "You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(600)].)", \ + "You hear a metallic creaking from [src].") + if(do_after(user,(600), target = src)) + if(!user || user.stat != CONSCIOUS || user.loc != src || state_open) + return + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") + open_machine() + +/obj/machinery/hypnochair/relaymove(mob/user) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") + +/obj/machinery/hypnochair/MouseDrop_T(mob/target, mob/user) + if(user.stat || !Adjacent(user) || !user.Adjacent(target) || !isliving(target) || !user.IsAdvancedToolUser()) + return + if(isliving(user)) + var/mob/living/L = user + if(!(L.mobility_flags & MOBILITY_STAND)) + return + close_machine(target) diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index ff79038a96..1887ee46c0 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -679,7 +679,7 @@ /obj/machinery/porta_turret/syndicate/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) /obj/machinery/porta_turret/syndicate/energy icon_state = "standard_stun" @@ -788,7 +788,7 @@ /obj/machinery/porta_turret/centcom_shuttle/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) /obj/machinery/porta_turret/centcom_shuttle/assess_perp(mob/living/carbon/human/perp) return 0 diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm old mode 100755 new mode 100644 index 8545e6f35c..2fff2011c1 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -17,6 +17,8 @@ /obj/item/melee/baton, /obj/item/ammo_box/magazine/recharge, /obj/item/modular_computer, + /obj/item/ammo_casing/mws_batt, + /obj/item/ammo_box/magazine/mws_mag, /obj/item/twohanded/electrostaff, /obj/item/gun/ballistic/automatic/magrifle)) @@ -143,6 +145,29 @@ using_power = TRUE update_icon() return + + if(istype(charging, /obj/item/ammo_casing/mws_batt)) + var/obj/item/ammo_casing/mws_batt/R = charging + if(R.cell.charge < R.cell.maxcharge) + R.cell.give(R.cell.chargerate * recharge_coeff) + use_power(250 * recharge_coeff) + using_power = 1 + if(R.BB == null) + R.chargeshot() + update_icon(using_power) + + if(istype(charging, /obj/item/ammo_box/magazine/mws_mag)) + var/obj/item/ammo_box/magazine/mws_mag/R = charging + for(var/B in R.stored_ammo) + var/obj/item/ammo_casing/mws_batt/batt = B + if(batt.cell.charge < batt.cell.maxcharge) + batt.cell.give(batt.cell.chargerate * recharge_coeff) + use_power(250 * recharge_coeff) + using_power = 1 + if(batt.BB == null) + batt.chargeshot() + update_icon(using_power) + else return PROCESS_KILL diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm index 69aa3fb654..0954d12790 100644 --- a/code/game/objects/effects/contraband.dm +++ b/code/game/objects/effects/contraband.dm @@ -51,6 +51,7 @@ icon = 'icons/obj/contraband.dmi' plane = ABOVE_WALL_PLANE anchored = TRUE + buildable_sign = FALSE //Cannot be unwrenched from a wall. var/ruined = FALSE var/random_basetype var/never_random = FALSE // used for the 'random' subclasses. @@ -69,6 +70,8 @@ name = "poster - [name]" desc = "A large piece of space-resistant printed paper. [desc]" + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 300)), 0) + /obj/structure/sign/poster/proc/randomise(base_type) var/list/poster_types = subtypesof(base_type) var/list/approved_types = list() diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 5720d5ce34..34996177af 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -5,6 +5,7 @@ var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one? + var/beauty = 0 /obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases) . = ..() @@ -26,6 +27,8 @@ if(LAZYLEN(diseases_to_add)) AddComponent(/datum/component/infective, diseases_to_add) + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, beauty)), 0) + /obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal if(mergeable_decal) qdel(C) diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index 3afc0ef671..fa4bfe7e67 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -3,6 +3,7 @@ name = "xeno blood" desc = "It's green and acidic. It looks like... blood?" color = BLOOD_COLOR_XENO + beauty = -250 /obj/effect/decal/cleanable/blood/splatter/xeno color = BLOOD_COLOR_XENO diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index ab0d1caca4..a5acc7d394 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -7,6 +7,7 @@ blood_state = BLOOD_STATE_BLOOD bloodiness = BLOOD_AMOUNT_PER_DECAL color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere. + beauty = -100 /obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) if (C.blood_DNA) @@ -45,12 +46,14 @@ icon_state = "tracks" desc = "They look like tracks left by wheels." random_icon_states = null + beauty = -50 /obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose name = "blood" icon_state = "ltrails_1" desc = "Your instincts say you shouldn't be following these." random_icon_states = null + beauty = -50 var/list/existing_dirs = list() /obj/effect/decal/cleanable/trail_holder/update_icon() diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index e06c172519..2e45bbfca5 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -3,6 +3,7 @@ desc = "Someone should clean that up." icon = 'icons/obj/objects.dmi' icon_state = "shards" + beauty = -50 /obj/effect/decal/cleanable/ash name = "ashes" @@ -10,6 +11,7 @@ icon = 'icons/obj/objects.dmi' icon_state = "ash" mergeable_decal = FALSE + beauty = -50 /obj/effect/decal/cleanable/ash/Initialize() . = ..() @@ -24,6 +26,7 @@ /obj/effect/decal/cleanable/ash/large name = "large pile of ashes" icon_state = "big_ash" + beauty = -100 /obj/effect/decal/cleanable/ash/large/Initialize() . = ..() @@ -34,6 +37,7 @@ desc = "Back to sand." icon = 'icons/obj/shards.dmi' icon_state = "tiny" + beauty = -100 /obj/effect/decal/cleanable/glass/Initialize() . = ..() @@ -52,6 +56,7 @@ canSmoothWith = list(/obj/effect/decal/cleanable/dirt, /turf/closed/wall, /obj/structure/falsewall) smooth = SMOOTH_FALSE mouse_opacity = MOUSE_OPACITY_TRANSPARENT + beauty = -75 /obj/effect/decal/cleanable/dirt/Initialize() . = ..() @@ -72,6 +77,10 @@ desc = "It's still good. Four second rule!" icon_state = "flour" +/obj/effect/decal/cleanable/dirt/dust + name = "dust" + desc = "A thin layer of dust coating the floor." + /obj/effect/decal/cleanable/greenglow/ecto name = "ectoplasmic puddle" desc = "You know who to call." @@ -80,8 +89,11 @@ /obj/effect/decal/cleanable/greenglow name = "glowing goo" desc = "Jeez. I hope that's not for lunch." + light_power = 1 + light_range = 1 light_color = LIGHT_COLOR_GREEN icon_state = "greenglow" + beauty = -300 /obj/effect/decal/cleanable/greenglow/Initialize(mapload) . = ..() @@ -97,6 +109,7 @@ layer = WALL_OBJ_LAYER icon_state = "cobweb1" resistance_flags = FLAMMABLE + beauty = -100 /obj/effect/decal/cleanable/cobweb/cobweb2 icon_state = "cobweb2" @@ -108,10 +121,12 @@ icon = 'icons/effects/effects.dmi' icon_state = "molten" mergeable_decal = FALSE + beauty = -150 /obj/effect/decal/cleanable/molten_object/large name = "big gooey grey mass" icon_state = "big_molten" + beauty = -300 //Vomit (sorry) /obj/effect/decal/cleanable/vomit @@ -120,6 +135,7 @@ icon = 'icons/effects/blood.dmi' icon_state = "vomit_1" random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") + beauty = -150 /obj/effect/decal/cleanable/vomit/attack_hand(mob/user) . = ..() @@ -152,6 +168,7 @@ gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3") + beauty = -100 /obj/effect/decal/cleanable/plant_smudge name = "plant smudge" diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index cf030df120..2765330977 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -10,6 +10,7 @@ blood_state = BLOOD_STATE_OIL bloodiness = BLOOD_AMOUNT_PER_DECAL mergeable_decal = FALSE + beauty = -50 /obj/effect/decal/cleanable/robot_debris/Initialize(mapload, list/datum/disease/diseases) . = ..() @@ -50,6 +51,7 @@ random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") blood_state = BLOOD_STATE_OIL bloodiness = BLOOD_AMOUNT_PER_DECAL + beauty = -100 /obj/effect/decal/cleanable/oil/Initialize() . = ..() @@ -58,6 +60,7 @@ /obj/effect/decal/cleanable/oil/streak random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5") + beauty = -50 /obj/effect/decal/cleanable/oil/slippery diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 2a4b6d7df5..55549f5fc4 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -138,6 +138,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/skill_difficulty = THRESHOLD_UNTRAINED //how difficult it's to use this item in general. var/skill_gain = DEF_SKILL_GAIN //base skill value gain from using this item. + var/canMouseDown = FALSE + + /obj/item/Initialize() if (attack_verb) @@ -420,14 +423,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) return usr.client.Click(src, src_location, src_control, params) var/list/directaccess = usr.DirectAccess() //This, specifically, is what requires the copypaste. If this were after the adjacency check, then it'd be impossible to use items in your inventory, among other things. //If this were before the above checks, then trying to click on items would act a little funky and signal overrides wouldn't work. - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - if((C.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && ((C.CanReach(src) || (src in directaccess)) && (C.CanReach(over) || (over in directaccess)))) - if(!C.get_active_held_item()) - C.UnarmedAttack(src, TRUE) - if(C.get_active_held_item() == src) - melee_attack_chain(C, over) - return TRUE //returning TRUE as a "is this overridden?" flag + if(SEND_SIGNAL(usr, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && ((usr.CanReach(src) || (src in directaccess)) && (usr.CanReach(over) || (over in directaccess)))) + if(!usr.get_active_held_item()) + usr.UnarmedAttack(src, TRUE) + if(usr.get_active_held_item() == src) + melee_attack_chain(usr, over) + return TRUE //returning TRUE as a "is this overridden?" flag if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index cb44b82ad2..5d9c6ee267 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -745,7 +745,7 @@ RLD if(istype(A, /obj/machinery/light/)) if(checkResource(deconcost, user)) to_chat(user, "You start deconstructing [A]...") - user.Beam(A,icon_state="nzcrentrs_power",time=15) + user.Beam(A,icon_state="light_beam",time=15) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) if(do_after(user, decondelay, target = A)) if(!useResource(deconcost, user)) @@ -759,7 +759,7 @@ RLD var/turf/closed/wall/W = A if(checkResource(floorcost, user)) to_chat(user, "You start building a wall light...") - user.Beam(A,icon_state="nzcrentrs_power",time=15) + user.Beam(A,icon_state="light_beam",time=15) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, 0) if(do_after(user, floordelay, target = A)) @@ -805,7 +805,7 @@ RLD var/turf/open/floor/F = A if(checkResource(floorcost, user)) to_chat(user, "You start building a floor light...") - user.Beam(A,icon_state="nzcrentrs_power",time=15) + user.Beam(A,icon_state="light_beam",time=15) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, 1) if(do_after(user, floordelay, target = A)) @@ -834,6 +834,12 @@ RLD return TRUE return FALSE +/obj/item/construction/rld/mini + name = "mini-rapid-light-device (MRLD)" + desc = "A device used to rapidly provide lighting sources to an area. Reload with metal, plasteel, glass or compressed matter cartridges." + matter = 100 + max_matter = 100 + /obj/item/rcd_upgrade name = "RCD advanced design disk" desc = "It seems to be empty." diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm index 35843c1030..01b351edd0 100644 --- a/code/game/objects/items/RSF.dm +++ b/code/game/objects/items/RSF.dm @@ -7,7 +7,7 @@ RSF name = "\improper Rapid-Service-Fabricator" desc = "A device used to rapidly deploy service items." icon = 'icons/obj/tools.dmi' - icon_state = "rcd" + icon_state = "rsf" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' opacity = 0 @@ -110,7 +110,7 @@ RSF name = "Cookie Synthesizer" desc = "A self-recharging device used to rapidly deploy cookies." icon = 'icons/obj/tools.dmi' - icon_state = "rcd" + icon_state = "rsf" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' var/matter = 10 diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm index 45fea91e49..b6be778456 100644 --- a/code/game/objects/items/airlock_painter.dm +++ b/code/game/objects/items/airlock_painter.dm @@ -125,3 +125,112 @@ user.put_in_hands(ink) to_chat(user, "You remove [ink] from [src].") ink = null + + +/obj/item/airlock_painter/decal + name = "decal painter" + desc = "An airlock painter, reprogramed to use a different style of paint in order to apply decals for floor tiles as well, in addition to repainting doors. Decals break when the floor tiles are removed. Alt-Click to change design." + icon = 'icons/obj/objects.dmi' + icon_state = "decal_sprayer" + item_state = "decalsprayer" + custom_materials = list(/datum/material/iron=2000, /datum/material/glass=500) + var/stored_dir = 2 + var/stored_color = "" + var/stored_decal = "warningline" + var/stored_decal_total = "warningline" + var/color_list = list("","red","white") + var/dir_list = list(1,2,4,8) + var/decal_list = list(list("Warning Line","warningline"), + list("Warning Line Corner","warninglinecorner"), + list("Caution Label","caution"), + list("Directional Arrows","arrows"), + list("Stand Clear Label","stand_clear"), + list("Box","box"), + list("Box Corner","box_corners"), + list("Delivery Marker","delivery"), + list("Warning Box","warn_full")) + +/obj/item/airlock_painter/decal/afterattack(atom/target, mob/user, proximity) + . = ..() + var/turf/open/floor/F = target + if(!proximity) + to_chat(user, "You need to get closer!") + return + if(use_paint(user) && isturf(F)) + F.AddComponent(/datum/component/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha) + +/obj/item/airlock_painter/decal/attack_self(mob/user) + if((ink) && (ink.charges >= 1)) + to_chat(user, "[src] beeps to prevent you from removing the toner until out of charges.") + return + . = ..() + +/obj/item/airlock_painter/decal/AltClick(mob/user) + . = ..() + ui_interact(user) + +/obj/item/airlock_painter/decal/Initialize() + . = ..() + ink = new /obj/item/toner/large(src) + +/obj/item/airlock_painter/decal/proc/update_decal_path() + var/yellow_fix = "" //This will have to do until someone refactor's markings.dm + if (stored_color) + yellow_fix = "_" + stored_decal_total = "[stored_decal][yellow_fix][stored_color]" + return + +/obj/item/airlock_painter/decal/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "decal_painter", name, 500, 400, master_ui, state) + ui.open() + +/obj/item/airlock_painter/decal/ui_data(mob/user) + var/list/data = list() + data["decal_direction"] = stored_dir + data["decal_color"] = stored_color + data["decal_style"] = stored_decal + data["decal_list"] = list() + data["color_list"] = list() + data["dir_list"] = list() + + for(var/i in decal_list) + data["decal_list"] += list(list( + "name" = i[1], + "decal" = i[2] + )) + for(var/j in color_list) + data["color_list"] += list(list( + "colors" = j + )) + for(var/k in dir_list) + data["dir_list"] += list(list( + "dirs" = k + )) + return data + +/obj/item/airlock_painter/decal/ui_act(action,list/params) + if(..()) + return + switch(action) + //Lists of decals and designs + if("select decal") + var/selected_decal = params["decals"] + stored_decal = selected_decal + if("select color") + var/selected_color = params["colors"] + stored_color = selected_color + if("selected direction") + var/selected_direction = text2num(params["dirs"]) + stored_dir = selected_direction + update_decal_path() + . = TRUE + +/obj/item/airlock_painter/decal/debug + name = "extreme decal painter" + icon_state = "decal_sprayer_ex" + +/obj/item/airlock_painter/decal/debug/Initialize() + . = ..() + ink = new /obj/item/toner/extreme(src) \ No newline at end of file diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index 0e3744cd84..b90fd1c1af 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -692,6 +692,17 @@ def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high) needs_anchored = FALSE +/obj/item/circuitboard/machine/chem_dispenser/apothecary + name = "Apotechary Chem Dispenser (Machine Board)" + build_path = /obj/machinery/chem_dispenser/apothecary + req_components = list( + /obj/item/stock_parts/matter_bin = 1, + /obj/item/stock_parts/capacitor = 1, + /obj/item/stock_parts/manipulator = 1, + /obj/item/stack/sheet/glass = 1, + /obj/item/stock_parts/cell = 1) + def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/upgraded/plus) + /obj/item/circuitboard/machine/chem_dispenser/drinks name = "Soda Dispenser (Machine Board)" build_path = /obj/machinery/chem_dispenser/drinks @@ -707,6 +718,10 @@ def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high) needs_anchored = FALSE +/obj/item/circuitboard/machine/sleeper/party + name = "Party Pod (Machine Board)" + build_path = /obj/machinery/sleeper/party + /obj/item/circuitboard/machine/smoke_machine name = "Smoke Machine (Machine Board)" build_path = /obj/machinery/smoke_machine @@ -884,6 +899,16 @@ name = "Departmental Protolathe - Service (Machine Board)" build_path = /obj/machinery/rnd/production/protolathe/department/service +/obj/item/circuitboard/machine/bepis + name = "BEPIS Chamber (Machine Board)" + build_path = /obj/machinery/rnd/bepis + req_components = list( + /obj/item/stack/cable_coil = 5, + /obj/item/stock_parts/capacitor = 1, + /obj/item/stock_parts/manipulator = 1, + /obj/item/stock_parts/micro_laser = 1, + /obj/item/stock_parts/scanning_module = 1) + /obj/item/circuitboard/machine/techfab name = "\improper Techfab (Machine Board)" build_path = /obj/machinery/rnd/production/techfab @@ -1068,3 +1093,12 @@ /obj/item/stock_parts/matter_bin = 3, /obj/item/stock_parts/manipulator = 1, /obj/item/stack/sheet/glass = 1) + +/obj/item/circuitboard/machine/hypnochair + name = "Enhanced Interrogation Chamber (Machine Board)" + icon_state = "security" + build_path = /obj/machinery/hypnochair + req_components = list( + /obj/item/stock_parts/micro_laser = 2, + /obj/item/stock_parts/scanning_module = 2 + ) diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index 5b332cda46..7450cb937c 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -99,7 +99,7 @@ if(href_list["reset_radio_short"]) pai.unshort_radio() if(href_list["setlaws"]) - var/newlaws = stripped_multiline_input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", MAX_MESSAGE_LEN) + var/newlaws = stripped_multiline_input(usr, "Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", "", MAX_MESSAGE_LEN) if(newlaws && pai) pai.add_supplied_law(0,newlaws) if(href_list["toggle_holo"]) diff --git a/code/game/objects/items/devices/polycircuit.dm b/code/game/objects/items/devices/polycircuit.dm new file mode 100644 index 0000000000..fb15ce45dc --- /dev/null +++ b/code/game/objects/items/devices/polycircuit.dm @@ -0,0 +1,52 @@ +/obj/item/stack/circuit_stack + name = "polycircuit aggregate" + desc = "A dense, overdesigned cluster of electronics which attempted to function as a multipurpose circuit electronic. Circuits can be removed from it... if you don't bleed out in the process." + icon_state = "circuit_mess" + item_state = "rods" + w_class = WEIGHT_CLASS_TINY + max_amount = 8 + var/circuit_type = /obj/item/electronics/airlock + var/chosen_circuit = "airlock" + +/obj/item/stack/circuit_stack/attack_self(mob/user)// Prevents the crafting menu, and tells you how to use it. + to_chat(user, "You can't use [src] by itself, you'll have to try and remove one of these circuits by hand... carefully.") + +/obj/item/stack/circuit_stack/attack_hand(mob/user) + var/mob/living/carbon/human/H = user + if(!user.get_inactive_held_item() == src) + return ..() + else + if(zero_amount()) + return + chosen_circuit = input("What type of circuit would you like to remove?", "Choose a Circuit Type", chosen_circuit) in list("airlock","firelock","fire alarm","air alarm","APC") + if(zero_amount()) + return + switch(chosen_circuit) + if("airlock") + circuit_type = /obj/item/electronics/airlock + if("firelock") + circuit_type = /obj/item/electronics/firelock + if("fire alarm") + circuit_type = /obj/item/electronics/firealarm + if("air alarm") + circuit_type = /obj/item/electronics/airalarm + if("APC") + circuit_type = /obj/item/electronics/apc + to_chat(user, "You spot your circuit, and carefully attempt to remove it from [src], hold still!") + if(do_after(user, 30, target = user)) + if(!src || QDELETED(src))//Sanity Check. + return + var/returned_circuit = new circuit_type(src) + user.put_in_hands(returned_circuit) + use(1) + if(!amount) + to_chat(user, "You navigate the sharp edges of circuitry and remove the last board.") + else + to_chat(user, "You navigate the sharp edges of circuitry and remove a single board from [src]") + else + H.apply_damage(15, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + to_chat(user, "You give yourself a wicked cut on [src]'s many sharp corners and edges!") + ..() + +/obj/item/stack/circuit_stack/full + amount = 8 diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 97fce0f096..e26b29289a 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -98,7 +98,7 @@ /obj/item/radio/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) /obj/item/radio/interact(mob/user) if(unscrewed && !isAI(user)) diff --git a/code/game/objects/items/grenades/antigravity.dm b/code/game/objects/items/grenades/antigravity.dm index 43b2f94986..a4bc207be0 100644 --- a/code/game/objects/items/grenades/antigravity.dm +++ b/code/game/objects/items/grenades/antigravity.dm @@ -2,16 +2,16 @@ name = "antigravity grenade" icon_state = "emp" item_state = "emp" - + var/range = 7 var/forced_value = 0 var/duration = 300 /obj/item/grenade/antigravity/prime() update_mob() - + for(var/turf/T in view(range,src)) - var/datum/component/C = T.AddComponent(/datum/component/forced_gravity,forced_value) - QDEL_IN(C,duration) - + T.AddElement(/datum/element/forced_gravity, forced_value) + addtimer(CALLBACK(T, /datum/.proc/_RemoveElement, list(forced_value)), duration) + qdel(src) diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm index 66869d6f04..fe2a27f1a8 100644 --- a/code/game/objects/items/grenades/plastic.dm +++ b/code/game/objects/items/grenades/plastic.dm @@ -26,7 +26,7 @@ /obj/item/grenade/plastic/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) /obj/item/grenade/plastic/Destroy() qdel(nadeassembly) diff --git a/code/game/objects/items/implants/implant_abductor.dm b/code/game/objects/items/implants/implant_abductor.dm index 0c50beadea..e0765e7951 100644 --- a/code/game/objects/items/implants/implant_abductor.dm +++ b/code/game/objects/items/implants/implant_abductor.dm @@ -5,36 +5,30 @@ icon_state = "implant" activated = 1 var/obj/machinery/abductor/pad/home - var/cooldown = 30 + var/next_use = 0 /obj/item/implant/abductor/activate() . = ..() - if(cooldown == initial(cooldown)) + if(next_use <= world.time) home.Retrieve(imp_in,1) - cooldown = 0 - START_PROCESSING(SSobj, src) + next_use = world.time + 60 SECONDS else - to_chat(imp_in, "You must wait [30 - cooldown] seconds to use [src] again!") - -/obj/item/implant/abductor/process() - if(cooldown < initial(cooldown)) - cooldown++ - if(cooldown == initial(cooldown)) - STOP_PROCESSING(SSobj, src) + to_chat(imp_in, "You must wait [DisplayTimeText(next_use - world.time)] to use [src] again!") /obj/item/implant/abductor/implant(mob/living/target, mob/user) - if(..()) - var/obj/machinery/abductor/console/console - if(ishuman(target)) - var/datum/antagonist/abductor/A = target.mind.has_antag_datum(/datum/antagonist/abductor) - if(A) - console = get_abductor_console(A.team.team_number) - home = console.pad - - if(!home) - var/list/consoles = list() - for(var/obj/machinery/abductor/console/C in GLOB.machines) - consoles += C - console = pick(consoles) + . = ..() + if(!.) + return + var/obj/machinery/abductor/console/console + if(ishuman(target)) + var/datum/antagonist/abductor/A = target.mind.has_antag_datum(/datum/antagonist/abductor) + if(A) + console = get_abductor_console(A.team.team_number) home = console.pad - return TRUE + + if(!home) + var/list/consoles = list() + for(var/obj/machinery/abductor/console/C in GLOB.machines) + consoles += C + console = pick(consoles) + home = console.pad diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index 168bca0b9a..77d9f09eff 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -104,10 +104,10 @@ desc = "An occult looking dagger that is cold to the touch. Somehow, the flawless orb on the pommel is made entirely of liquid blood." icon = 'icons/obj/ice_moon/artifacts.dmi' icon_state = "bloodletter" - w_class = WEIGHT_CLASS_NORMAL + w_class = WEIGHT_CLASS_NORMAL /// Bleed stacks applied when an organic mob target is hit var/bleed_stacks_per_hit = 3 - + /obj/item/kitchen/knife/bloodletter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() if(!isliving(target) || !proximity_flag) @@ -198,6 +198,7 @@ throw_speed = 3 throw_range = 7 w_class = WEIGHT_CLASS_NORMAL + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 1.5) attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") custom_price = 200 diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm index c4bb8c594c..ae9ea6985c 100644 --- a/code/game/objects/items/miscellaneous.dm +++ b/code/game/objects/items/miscellaneous.dm @@ -115,6 +115,20 @@ new /obj/item/toy/crayon/spraycan(src) new /obj/item/clothing/shoes/sandal(src) +/obj/item/choice_beacon/hosgun + name = "personal weapon beacon" + desc = "Use this to summon your personal Head of Security issued firearm!" + +/obj/item/choice_beacon/hosgun/generate_display_names() + var/static/list/hos_gun_list + if(!hos_gun_list) + hos_gun_list = list() + var/list/templist = subtypesof(/obj/item/storage/secure/briefcase/hos/) //we have to convert type = name to name = type, how lovely! + for(var/V in templist) + var/atom/A = V + hos_gun_list[initial(A.name)] = A + return hos_gun_list + /obj/item/skub desc = "It's skub." name = "skub" diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 1ca314f749..2f697553f5 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -419,7 +419,7 @@ A.BB.damage = hitdamage if(hitdamage) A.BB.nodamage = FALSE - A.BB.speed = 0.5 + A.BB.pixels_per_second = TILES_TO_PIXELS(20) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) A.fire_casing(target, user, params, 0, 0, null, 0, src) user.visible_message("[user] blasts a flying lollipop at [target]!") @@ -434,7 +434,7 @@ A.BB.damage = hitdamage if(hitdamage) A.BB.nodamage = FALSE - A.BB.speed = 0.5 + A.BB.pixels_per_second = TILES_TO_PIXELS(20) A.BB.color = rgb(rand(0, 255), rand(0, 255), rand(0, 255)) playsound(src.loc, 'sound/weapons/bulletflyby3.ogg', 50, 1) A.fire_casing(target, user, params, 0, 0, null, 0, src) @@ -671,13 +671,13 @@ if(track_projectile) tracked[P] = P.damage P.damage *= projectile_damage_coefficient - P.speed *= projectile_speed_coefficient + P.pixels_per_second *= projectile_speed_coefficient P.add_overlay(projectile_effect) /obj/item/borg/projectile_dampen/proc/restore_projectile(obj/item/projectile/P) tracked -= P P.damage *= (1/projectile_damage_coefficient) - P.speed *= (1/projectile_speed_coefficient) + P.pixels_per_second *= (1/projectile_speed_coefficient) P.cut_overlay(projectile_effect) /********************************************************************** diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 1459afeb2d..b9cde1664f 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -107,7 +107,7 @@ return TRUE /obj/item/shield/proc/user_shieldbash(mob/living/user, atom/target, harmful) - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //Combat mode has to be enabled for shield bashing + if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //Combat mode has to be enabled for shield bashing return FALSE if(!(shield_flags & SHIELD_CAN_BASH)) to_chat(user, "[src] can't be used to shield bash!") @@ -274,7 +274,7 @@ obj/item/shield/riot/bullet_proof item_state = "buckler" lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' - custom_materials = null + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 10) resistance_flags = FLAMMABLE repair_material = /obj/item/stack/sheet/mineral/wood block_chance = 30 diff --git a/code/game/objects/items/stacks/cash.dm b/code/game/objects/items/stacks/cash.dm index a06b96ad9c..ce0bc6591a 100644 --- a/code/game/objects/items/stacks/cash.dm +++ b/code/game/objects/items/stacks/cash.dm @@ -71,3 +71,9 @@ icon_state = "spacecash1000" singular_name = "one thousand credit bill" value = 1000 + +/obj/item/stack/spacecash/c10000 + icon_state = "spacecash10000" + singular_name = "ten thousand credit bill" + value = 10000 + diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index e919f3fe02..4c2c21a7db 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -89,3 +89,19 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \ /obj/item/stack/rods/fifty amount = 50 + +/obj/item/stack/rods/lava + name = "heat resistant rod" + desc = "Treated, specialized metal rods. When exposed to the vaccum of space their coating breaks off, but they can hold up against the extreme heat of active lava." + singular_name = "heat resistant rod" + icon_state = "rods" + item_state = "rods" + color = "#5286b9ff" + flags_1 = CONDUCT_1 + w_class = WEIGHT_CLASS_NORMAL + custom_materials = list(/datum/material/iron=1000, /datum/material/plasma=500, /datum/material/titanium=2000) + max_amount = 30 + resistance_flags = FIRE_PROOF | LAVA_PROOF + +/obj/item/stack/rods/lava/thirty + amount = 30 diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 66f8ecc7e4..5d22e3d61b 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -62,7 +62,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 20), \ new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60), \ null, \ - new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 40, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 40, one_per_turf = TRUE, on_floor = TRUE, trait_booster = TRAIT_QUICK_BUILD, trait_modifier = 0.75), \ null, \ new/datum/stack_recipe("computer frame", /obj/structure/frame/computer, 5, time = 25, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("modular console", /obj/machinery/modular_computer/console/buildable/, 10, time = 25, one_per_turf = TRUE, on_floor = TRUE), \ @@ -240,6 +240,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new /datum/stack_recipe("pew (right)", /obj/structure/chair/pew/right, 3, one_per_turf = TRUE, on_floor = TRUE),\ )), null, \ + new/datum/stack_recipe("wooden firearm body", /obj/item/weaponcrafting/improvised_parts/wooden_body, 10, time = 40), \ new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \ new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \ new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 30), \ @@ -280,11 +281,13 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ icon_state = "sheet-wood" item_state = "sheet-wood" icon = 'icons/obj/stack_objects.dmi' + custom_materials = list(/datum/material/wood=MINERAL_MATERIAL_AMOUNT) sheettype = "wood" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0) resistance_flags = FLAMMABLE merge_type = /obj/item/stack/sheet/mineral/wood novariants = TRUE + material_type = /datum/material/wood grind_results = list(/datum/reagent/carbon = 20) /obj/item/stack/sheet/mineral/wood/attackby(obj/item/W, mob/user, params) // NOTE: sheet_types.dm is where the WOOD stack lives. Maybe move this over there. @@ -403,8 +406,6 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \ resistance_flags = FLAMMABLE force = 0 throwforce = 0 - pull_effort = 90 - is_fabric = TRUE merge_type = /obj/item/stack/sheet/cloth /obj/item/stack/sheet/cloth/get_main_recipes() @@ -425,7 +426,7 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \ new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \ new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \ new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 25), \ - new/datum/stack_recipe("durathread string", /obj/item/weaponcrafting/durathread_string, 1, time = 40) \ + new/datum/stack_recipe("durathread string", /obj/item/weaponcrafting/durathread_string, 1, time = 40), \ )) /obj/item/stack/sheet/durathread @@ -817,13 +818,12 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra max_amount = 80 singular_name = "raw cotton ball" icon_state = "sheet-cotton" - is_fabric = TRUE resistance_flags = FLAMMABLE force = 0 throwforce = 0 merge_type = /obj/item/stack/sheet/cotton - pull_effort = 30 - loom_result = /obj/item/stack/sheet/cloth + var/pull_effort = 30 + var/loom_result = /obj/item/stack/sheet/cloth /obj/item/stack/sheet/cotton/ten amount = 10 diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm index 378855707e..dfba533247 100644 --- a/code/game/objects/items/stacks/sheets/sheets.dm +++ b/code/game/objects/items/stacks/sheets/sheets.dm @@ -13,9 +13,6 @@ mats_per_stack = MINERAL_MATERIAL_AMOUNT var/sheettype = null //this is used for girders in the creation of walls/false walls var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity - var/is_fabric = FALSE //is this a valid material for the loom? - var/loom_result //result from pulling on the loom - var/pull_effort = 0 //amount of delay when pulling on the loom var/shard_type // the shard debris typepath left over by solar panels and windows etc. /obj/item/stack/sheet/Initialize(mapload, new_amount, merge) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index add9ebd6b2..2c8e700316 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -201,8 +201,13 @@ if(!building_checks(R, multiplier)) return if (R.time) + var/adjusted_time = 0 usr.visible_message("[usr] starts building [R.title].", "You start building [R.title]...") - if (!do_after(usr, R.time, target = usr)) + if(HAS_TRAIT(usr, R.trait_booster)) + adjusted_time = (R.time * R.trait_modifier) + else + adjusted_time = R.time + if (!do_after(usr, adjusted_time, target = usr)) return if(!building_checks(R, multiplier)) return @@ -457,8 +462,10 @@ var/window_checks = FALSE var/placement_checks = FALSE var/applies_mats = FALSE + var/trait_booster = null + var/trait_modifier = 1 -/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1,time = 0, one_per_turf = FALSE, on_floor = FALSE, window_checks = FALSE, placement_checks = FALSE, applies_mats = FALSE) +/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1,time = 0, one_per_turf = FALSE, on_floor = FALSE, window_checks = FALSE, placement_checks = FALSE, applies_mats = FALSE, trait_booster = null, trait_modifier = 1) src.title = title @@ -472,6 +479,8 @@ src.window_checks = window_checks src.placement_checks = placement_checks src.applies_mats = applies_mats + src.trait_booster = trait_booster + src.trait_modifier = trait_modifier /* * Recipe list datum */ diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 52802fa3df..5b7eb65d9b 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -61,7 +61,7 @@ switch(contents.len) if(0) icon_state = "[initial(icon_state)]" - if(0 to 11) + if(1 to 11) icon_state = "[initial(icon_state)]1" if(11 to 20) icon_state = "[initial(icon_state)]2" diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index de98963693..092648ee3c 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -223,6 +223,8 @@ /obj/item/storage/pill_bottle/ComponentInitialize() . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT + STR.max_volume = 14 STR.allow_quick_gather = TRUE STR.click_gather = TRUE STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice)) @@ -244,7 +246,7 @@ desc = "Contains pills used to counter radiation poisoning." /obj/item/storage/pill_bottle/anitrad/PopulateContents() - for(var/i in 1 to 5) + for(var/i in 1 to 4) new /obj/item/reagent_containers/pill/antirad(src) /obj/item/storage/pill_bottle/epinephrine @@ -276,7 +278,7 @@ desc = "Guaranteed to give you that extra burst of energy during a long shift!" /obj/item/storage/pill_bottle/stimulant/PopulateContents() - for(var/i in 1 to 5) + for(var/i in 1 to 4) new /obj/item/reagent_containers/pill/stimulant(src) /obj/item/storage/pill_bottle/mining diff --git a/code/game/objects/items/storage/secure.dm b/code/game/objects/items/storage/secure.dm index ef70bd201d..1caf13454b 100644 --- a/code/game/objects/items/storage/secure.dm +++ b/code/game/objects/items/storage/secure.dm @@ -147,6 +147,35 @@ for(var/i = 0, i < STR.max_items - 2, i++) new /obj/item/stack/spacecash/c1000(src) +/obj/item/storage/secure/briefcase/mws_pack + name = "\improper \'MWS\' gun kit" + desc = "A storage case for a multi-purpose handgun. Variety hour!" + +/obj/item/storage/secure/briefcase/mws_pack/PopulateContents() + new /obj/item/gun/ballistic/revolver/mws(src) + new /obj/item/ammo_box/magazine/mws_mag(src) + for(var/path in subtypesof(/obj/item/ammo_casing/mws_batt)) + new path(src) + +/obj/item/storage/secure/briefcase/hos/mws_pack_hos + name = "\improper \'MWS\' gun kit" + desc = "A storage case for a multi-purpose handgun. Variety hour!" + +/obj/item/storage/secure/briefcase/hos/mws_pack_hos/PopulateContents() + new /obj/item/gun/ballistic/revolver/mws(src) + new /obj/item/ammo_box/magazine/mws_mag(src) + new /obj/item/ammo_casing/mws_batt/lethal(src) + new /obj/item/ammo_casing/mws_batt/lethal(src) + new /obj/item/ammo_casing/mws_batt/stun(src) + new /obj/item/ammo_casing/mws_batt/stun(src) + new /obj/item/ammo_casing/mws_batt/ion(src) + +/obj/item/storage/secure/briefcase/hos/multiphase_box + name = "\improper X-01 Multiphase energy gun box" + desc = "A storage case for a high-tech energy firearm." + +/obj/item/storage/secure/briefcase/mws_pack_hos/PopulateContents() + new /obj/item/gun/energy/e_gun/hos(src) // ----------------------------- // Secure Safe @@ -183,4 +212,4 @@ return attack_self(user) /obj/item/storage/secure/safe/HoS - name = "head of security's safe" + name = "head of security's safe" \ No newline at end of file diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index 634537e5a2..e9364bcede 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -16,7 +16,7 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80) var/stamforce = 35 - var/status = FALSE + var/turned_on = FALSE var/knockdown = TRUE var/obj/item/stock_parts/cell/cell var/hitcost = 750 @@ -49,7 +49,7 @@ /obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() //Only mob/living types have stun handling - if(status && prob(throw_hit_chance) && iscarbon(hit_atom)) + if(turned_on && prob(throw_hit_chance) && iscarbon(hit_atom)) baton_stun(hit_atom) /obj/item/melee/baton/loaded //this one starts with a cell pre-installed. @@ -66,16 +66,16 @@ copper_top.use(min(chrgdeductamt, copper_top.charge), explode) if(QDELETED(src)) return FALSE - if(status && (!copper_top || !copper_top.charge || (chargecheck && copper_top.charge < (hitcost * STUNBATON_CHARGE_LENIENCY)))) + if(turned_on && (!copper_top || !copper_top.charge || (chargecheck && copper_top.charge < (hitcost * STUNBATON_CHARGE_LENIENCY)))) //we're below minimum, turn off switch_status(FALSE) /obj/item/melee/baton/proc/switch_status(new_status = FALSE, silent = FALSE) - if(status != new_status) - status = new_status + if(turned_on != new_status) + turned_on = new_status if(!silent) playsound(loc, "sparks", 75, 1, -1) - if(status) + if(turned_on) START_PROCESSING(SSobj, src) else STOP_PROCESSING(SSobj, src) @@ -85,7 +85,7 @@ deductcharge(round(hitcost * STUNBATON_DEPLETION_RATE), FALSE, FALSE) /obj/item/melee/baton/update_icon_state() - if(status) + if(turned_on) icon_state = "[initial(name)]_active" else if(!cell) icon_state = "[initial(name)]_nocell" @@ -134,8 +134,8 @@ else to_chat(user, "[src] is out of charge.") else - switch_status(!status) - to_chat(user, "[src] is now [status ? "on" : "off"].") + switch_status(!turned_on) + to_chat(user, "[src] is now [turned_on ? "on" : "off"].") add_fingerprint(user) /obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user) @@ -151,7 +151,7 @@ /obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE) if(iscyborg(M) || !isliving(M)) //can't baton cyborgs return FALSE - if(status && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) + if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) clowning_around(user) if(IS_STAMCRIT(user)) //CIT CHANGE - makes it impossible to baton in stamina softcrit to_chat(user, "You're too exhausted for that.") @@ -160,7 +160,7 @@ var/mob/living/carbon/human/L = M if(check_martial_counter(L, user)) return TRUE - if(status) + if(turned_on) if(baton_stun(M, user, disarming)) user.do_attack_animation(M) user.adjustStaminaLossBuffered(getweight(user, STAM_COST_BATON_MOB_MULT)) @@ -292,6 +292,48 @@ sparkler?.activate() . = ..() +/obj/item/melee/baton/boomerang + name = "\improper OZtek Boomerang" + desc = "A device invented in 2486 for the great Space Emu War by the confederacy of Australicus, these high-tech boomerangs also work exceptionally well at stunning crewmembers. Just be careful to catch it when thrown!" + throw_speed = 1 + icon_state = "boomerang" + item_state = "boomerang" + force = 5 + throwforce = 5 + throw_range = 5 + hitcost = 2000 + throw_hit_chance = 99 //Have you prayed today? + custom_materials = list(/datum/material/iron = 10000, /datum/material/glass = 4000, /datum/material/silver = 10000, /datum/material/gold = 2000) + +/obj/item/melee/baton/boomerang/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force) + if(turned_on) + if(ishuman(thrower)) + var/mob/living/carbon/human/H = thrower + H.throw_mode_off() //so they can catch it on the return. + return ..() + +/obj/item/melee/baton/boomerang/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + if(turned_on) + var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum) + if(ishuman(hit_atom) && !caught && prob(throw_hit_chance))//if they are a carbon and they didn't catch it + baton_stun(hit_atom) + if(thrownby && !caught) + sleep(1) + if(!QDELETED(src)) + throw_at(thrownby, throw_range+2, throw_speed, null, TRUE) + else + return ..() + +/obj/item/melee/baton/boomerang/update_icon() + if(turned_on) + icon_state = "[initial(icon_state)]_active" + else if(!cell) + icon_state = "[initial(icon_state)]_nocell" + else + icon_state = "[initial(icon_state)]" + +/obj/item/melee/baton/boomerang/loaded //Same as above, comes with a cell. + preload_cell_type = /obj/item/stock_parts/cell/high #undef STUNBATON_CHARGE_LENIENCY #undef STUNBATON_DEPLETION_RATE diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm index e81294ceea..817258d1c7 100644 --- a/code/game/objects/items/tanks/jetpack.dm +++ b/code/game/objects/items/tanks/jetpack.dm @@ -14,13 +14,15 @@ var/full_speed = TRUE // If the jetpack will have a speedboost in space/nograv or not var/datum/effect_system/trail_follow/ion/ion_trail -/obj/item/tank/jetpack/New() +/obj/item/tank/jetpack/Initialize() ..() + ion_trail = new + ion_trail.set_up(src) + +/obj/item/tank/jetpack/populate_gas() if(gas_type) air_contents.gases[gas_type] = ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - ion_trail = new - ion_trail.set_up(src) /obj/item/tank/jetpack/ui_action_click(mob/user, action) if(istype(action, /datum/action/item_action/toggle_jetpack)) @@ -188,8 +190,8 @@ var/obj/item/tank/internals/tank = null var/mob/living/carbon/human/cur_user -/obj/item/tank/jetpack/suit/New() - ..() +/obj/item/tank/jetpack/suit/Initialize() + . = ..() STOP_PROCESSING(SSobj, src) temp_air_contents = air_contents diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm index 0e6dfaa1b3..8f5303da8e 100644 --- a/code/game/objects/items/tanks/tank_types.dm +++ b/code/game/objects/items/tanks/tank_types.dm @@ -12,15 +12,13 @@ */ /obj/item/tank/internals/oxygen name = "oxygen tank" - desc = "A tank of oxygen." + desc = "A tank of oxygen, this one is blue." icon_state = "oxygen" distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE force = 10 dog_fashion = /datum/dog_fashion/back - -/obj/item/tank/internals/oxygen/New() - ..() +/obj/item/tank/internals/oxygen/populate_gas() air_contents.gases[/datum/gas/oxygen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) return @@ -35,6 +33,8 @@ icon_state = "oxygen_fr" dog_fashion = null +/obj/item/tank/internals/oxygen/empty/populate_gas() + return /* * Anesthetic @@ -46,11 +46,9 @@ item_state = "an_tank" force = 10 -/obj/item/tank/internals/anesthetic/New() - ..() +/obj/item/tank/internals/anesthetic/populate_gas() air_contents.gases[/datum/gas/oxygen] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD air_contents.gases[/datum/gas/nitrous_oxide] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD - return /* * Air @@ -63,11 +61,9 @@ force = 10 dog_fashion = /datum/dog_fashion/back -/obj/item/tank/internals/air/New() - ..() +/obj/item/tank/internals/air/populate_gas() air_contents.gases[/datum/gas/oxygen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD air_contents.gases[/datum/gas/nitrogen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD - return /* @@ -82,10 +78,8 @@ force = 8 -/obj/item/tank/internals/plasma/New() - ..() +/obj/item/tank/internals/plasma/populate_gas() air_contents.gases[/datum/gas/plasma] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) - return /obj/item/tank/internals/plasma/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/flamethrower)) @@ -100,10 +94,8 @@ else return ..() -/obj/item/tank/internals/plasma/full/New() - ..() // Plasma asserted in parent +/obj/item/tank/internals/plasma/full/populate_gas() air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) - return /* @@ -118,13 +110,10 @@ force = 10 distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE -/obj/item/tank/internals/plasmaman/New() - ..() +/obj/item/tank/internals/plasmaman/populate_gas() air_contents.gases[/datum/gas/plasma] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) - return -/obj/item/tank/internals/plasmaman/full/New() - ..() // Plasma asserted in parent +/obj/item/tank/internals/plasmaman/full/populate_gas() air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) return @@ -137,12 +126,12 @@ volume = 6 w_class = WEIGHT_CLASS_SMALL //thanks i forgot this -/obj/item/tank/internals/plasmaman/belt/full/New() - ..() // Plasma asserted in parent +/obj/item/tank/internals/plasmaman/belt/full/populate_gas() air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) return - +/obj/item/tank/internals/plasmaman/belt/empty/populate_gas() + return /* * Emergency Oxygen @@ -159,17 +148,25 @@ volume = 3 //Tiny. Real life equivalents only have 21 breaths of oxygen in them. They're EMERGENCY tanks anyway -errorage (dangercon 2011) -/obj/item/tank/internals/emergency_oxygen/New() - ..() +/obj/item/tank/internals/emergency_oxygen/populate_gas() air_contents.gases[/datum/gas/oxygen] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) return +/obj/item/tank/internals/emergency_oxygen/empty/populate_gas() + return + /obj/item/tank/internals/emergency_oxygen/engi name = "extended-capacity emergency oxygen tank" icon_state = "emergency_engi" volume = 6 +/obj/item/tank/internals/emergency_oxygen/engi/empty/populate_gas() + return + /obj/item/tank/internals/emergency_oxygen/double name = "double emergency oxygen tank" icon_state = "emergency_double" volume = 10 + +/obj/item/tank/internals/emergency_oxygen/double/empty/populate_gas() + return \ No newline at end of file diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 0877f56725..96ba2d11d4 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -60,14 +60,19 @@ H.update_action_buttons_icon() -/obj/item/tank/New() - ..() +/obj/item/tank/Initialize() + . = ..() air_contents = new(volume) //liters air_contents.temperature = T20C + populate_gas() + START_PROCESSING(SSobj, src) +/obj/item/tank/proc/populate_gas() + return + /obj/item/tank/Destroy() if(air_contents) qdel(air_contents) @@ -78,9 +83,9 @@ /obj/item/tank/examine(mob/user) var/obj/icon = src . = ..() - if (istype(src.loc, /obj/item/assembly)) + if(istype(src.loc, /obj/item/assembly)) icon = src.loc - if(!in_range(src, user)) + if(!in_range(src, user) && !isobserver(user)) if (icon == src) . += "If you want any more information you'll need to get closer." return diff --git a/code/game/objects/items/tools/saw.dm b/code/game/objects/items/tools/saw.dm new file mode 100644 index 0000000000..aab59c00be --- /dev/null +++ b/code/game/objects/items/tools/saw.dm @@ -0,0 +1,47 @@ +/obj/item/hatchet/saw + name = "handsaw" + desc = "A very sharp handsaw, it's compact." + icon = 'icons/obj/tools.dmi' + icon_state = "saw" + item_state = "sawhandle_greyscale" + lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi' + tool_behaviour = TOOL_SAW + force = 10 + throwforce = 8 + throw_speed = 3 + throw_range = 5 + custom_materials = list(/datum/material/iron = 5000) + attack_verb = list("sawed", "sliced", "cut") + hitsound = 'sound/weapons/bladeslice.ogg' + sharpness = IS_SHARP + var/random_color = TRUE //code taken from screwdrivers.dm; cool handles are cool. + var/static/list/saw_colors = list( + "blue" = rgb(24, 97, 213), + "red" = rgb(255, 0, 0), + "pink" = rgb(213, 24, 141), + "brown" = rgb(160, 82, 18), + "green" = rgb(14, 127, 27), + "cyan" = rgb(24, 162, 213), + "yellow" = rgb(255, 165, 0) + ) + +/obj/item/hatchet/saw/Initialize() + . = ..() + if(random_color) + icon_state = "sawhandle_greyscale" + var/our_color = pick(saw_colors) + add_atom_colour(saw_colors[our_color], FIXED_COLOUR_PRIORITY) + update_icon() + if(prob(75)) + pixel_y = rand(-8, 8) + +/obj/item/hatchet/saw/update_overlays() + . = ..() + if(!random_color) //icon override + return + var/mutable_appearance/base_overlay = mutable_appearance(icon, "sawblade") + base_overlay.appearance_flags = RESET_COLOR + . += base_overlay + +// END \ No newline at end of file diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index ff59b85332..bc0c1328af 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -777,6 +777,7 @@ var/cooldown = 0 var/obj/machinery/computer/holodeck/holo = null // Holodeck cards should not be infinite var/list/cards = list() + var/original_size = 52 /obj/item/toy/cards/deck/Initialize() . = ..() @@ -834,11 +835,11 @@ /obj/item/toy/cards/deck/update_icon_state() switch(cards.len) - if(27 to INFINITY) + if(INFINITY to original_size/2) icon_state = "deck_[deckstyle]_full" - if(11 to 27) + if(original_size/2 to original_size/4) icon_state = "deck_[deckstyle]_half" - if(1 to 11) + if(original_size/4 to 1) icon_state = "deck_[deckstyle]_low" else icon_state = "deck_[deckstyle]_empty" diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index aa0aa70e03..1bb4579176 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -477,20 +477,12 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 throw_speed = 5 throw_range = 2 attack_verb = list("busted") + var/impressiveness = 45 -/obj/item/statuebust/attack_self(mob/living/user) - add_fingerprint(user) - user.examinate(src) - -/obj/item/statuebust/examine(mob/living/user) +/obj/item/statuebust/Initialize() . = ..() - if(.) - return - if (!isliving(user)) - return - user.visible_message("[user] stops to admire [src].", \ - "You take in [src], admiring its fine craftsmanship.") - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) + AddElement(/datum/element/art, impressiveness) + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 1000)), 0) /obj/item/tailclub name = "tail club" @@ -566,6 +558,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 force = 10 throwforce = 12 attack_verb = list("beat", "smacked") + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 3.5) w_class = WEIGHT_CLASS_BULKY var/homerun_ready = 0 var/homerun_able = 0 diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm index 98f772a116..fcc26d1313 100644 --- a/code/game/objects/structures/artstuff.dm +++ b/code/game/objects/structures/artstuff.dm @@ -240,7 +240,7 @@ /obj/structure/sign/painting/Initialize(mapload, dir, building) . = ..() SSpersistence.painting_frames += src - AddComponent(/datum/component/art, 20) + AddElement(/datum/element/art, 20) if(dir) setDir(dir) if(building) diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 57d7e08862..bd6dcb2aff 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -261,6 +261,11 @@ LINEN BINS var/list/sheets = list() var/obj/item/hidden = null +/obj/structure/bedsheetbin/empty + amount = 0 + icon_state = "linenbin-empty" + anchored = FALSE + /obj/structure/bedsheetbin/examine(mob/user) . = ..() if(amount < 1) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index e5c50af782..9f4da351fa 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -76,12 +76,13 @@ new /obj/item/storage/box/flashbangs(src) new /obj/item/shield/riot/tele(src) new /obj/item/storage/belt/security/full(src) - new /obj/item/gun/energy/e_gun/hos(src) + new /obj/item/choice_beacon/hosgun(src) new /obj/item/flashlight/seclite(src) new /obj/item/pinpointer/nuke(src) new /obj/item/circuitboard/machine/techfab/department/security(src) new /obj/item/storage/photo_album/HoS(src) new /obj/item/clothing/suit/hooded/wintercoat/hos(src) + /obj/structure/closet/secure_closet/warden name = "\proper warden's locker" req_access = list(ACCESS_ARMORY) diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index c0ee7bb987..c1f8af43f0 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -302,7 +302,8 @@ /obj/item/twohanded/required/kirbyplants/Initialize() . = ..() - AddComponent(/datum/component/tactical) + AddElement(/datum/element/tactical) + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 500)), 0) /obj/item/twohanded/required/kirbyplants/random icon = 'icons/obj/flora/_flora.dmi' diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index fd62ffd368..cacf361722 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -6,6 +6,7 @@ density = TRUE var/state = GIRDER_NORMAL var/girderpasschance = 20 // percentage chance that a projectile passes through the girder. + var/next_beep = 0 //Prevents spamming of the construction sound var/can_displace = TRUE //If the girder can be moved around by wrenching it max_integrity = 200 rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE @@ -27,11 +28,17 @@ . += "[src] is disassembled! You probably shouldn't be able to see this examine message." /obj/structure/girder/attackby(obj/item/W, mob/user, params) + var/platingmodifier = 1 + if(HAS_TRAIT(user, TRAIT_QUICK_BUILD)) + platingmodifier = 0.7 + if(next_beep <= world.time) + next_beep = world.time + 10 + playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE) add_fingerprint(user) if(istype(W, /obj/item/gun/energy/plasmacutter)) to_chat(user, "You start slicing apart the girder...") - if(W.use_tool(src, user, 40, volume=100)) + if(W.use_tool(src, user, 40*platingmodifier, volume=100)) to_chat(user, "You slice apart the girder.") var/obj/item/stack/sheet/metal/M = new (loc, 2) M.add_fingerprint(user) @@ -62,7 +69,7 @@ to_chat(user, "You need at least two rods to create a false wall!") return to_chat(user, "You start building a reinforced false wall...") - if(do_after(user, 20, target = src)) + if(do_after(user, 20*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -75,7 +82,7 @@ to_chat(user, "You need at least five rods to add plating!") return to_chat(user, "You start adding plating...") - if(do_after(user, 40, target = src)) + if(do_after(user, 40*platingmodifier, target = src)) if(S.get_amount() < 5) return S.use(5) @@ -96,7 +103,7 @@ to_chat(user, "You need two sheets of metal to create a false wall!") return to_chat(user, "You start building a false wall...") - if(do_after(user, 20, target = src)) + if(do_after(user, 20*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -109,7 +116,7 @@ to_chat(user, "You need two sheets of metal to finish a wall!") return to_chat(user, "You start adding plating...") - if (do_after(user, 40, target = src)) + if (do_after(user, 40*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -126,7 +133,7 @@ to_chat(user, "You need at least two sheets to create a false wall!") return to_chat(user, "You start building a reinforced false wall...") - if(do_after(user, 20, target = src)) + if(do_after(user, 20*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -139,7 +146,7 @@ if(S.get_amount() < 1) return to_chat(user, "You start finalizing the reinforced wall...") - if(do_after(user, 50, target = src)) + if(do_after(user, 50*platingmodifier, target = src)) if(S.get_amount() < 1) return S.use(1) @@ -153,7 +160,7 @@ if(S.get_amount() < 1) return to_chat(user, "You start reinforcing the girder...") - if(do_after(user, 60, target = src)) + if(do_after(user, 60*platingmodifier, target = src)) if(S.get_amount() < 1) return S.use(1) @@ -172,7 +179,7 @@ if(S.get_amount() < 2) to_chat(user, "You need at least two sheets to create a false wall!") return - if(do_after(user, 20, target = src)) + if(do_after(user, 20*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -188,7 +195,7 @@ to_chat(user, "You need at least two sheets to add plating!") return to_chat(user, "You start adding plating...") - if (do_after(user, 40, target = src)) + if (do_after(user, 40*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index c41d6d32af..6e497cff60 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -149,3 +149,30 @@ pixel_x = 0 pixel_y = 0 return TRUE + +/obj/structure/lattice/lava + name = "heatproof support lattice" + desc = "A specialized support beam for building across lava. Watch your step." + icon = 'icons/obj/smooth_structures/catwalk.dmi' + icon_state = "catwalk" + number_of_rods = 1 + color = "#5286b9ff" + smooth = SMOOTH_TRUE + canSmoothWith = null + obj_flags = CAN_BE_HIT | BLOCK_Z_FALL + resistance_flags = FIRE_PROOF | LAVA_PROOF + +/obj/structure/lattice/lava/deconstruction_hints(mob/user) + return "The rods look like they could be cut, but the heat treatment will shatter off. There's space for a tile." + +/obj/structure/lattice/lava/attackby(obj/item/C, mob/user, params) + . = ..() + if(istype(C, /obj/item/stack/tile/plasteel)) + var/obj/item/stack/tile/plasteel/P = C + if(P.use(1)) + to_chat(user, "You construct a floor plating, as lava settles around the rods.") + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) + new /turf/open/floor/plating(locate(x, y, z)) + else + to_chat(user, "You need one floor tile to build atop [src].") + return diff --git a/code/game/objects/structures/loom.dm b/code/game/objects/structures/loom.dm index ad128b01c2..164e597117 100644 --- a/code/game/objects/structures/loom.dm +++ b/code/game/objects/structures/loom.dm @@ -21,21 +21,21 @@ return TRUE ///Handles the weaving. -/obj/structure/loom/proc/weave(obj/item/stack/sheet/S, mob/user) - if(!istype(S) || !S.is_fabric) +/obj/structure/loom/proc/weave(obj/item/stack/sheet/cotton/W, mob/user) + if(!istype(W)) return FALSE if(!anchored) user.show_message("The loom needs to be wrenched down.", MSG_VISUAL) return FALSE - if(S.amount < FABRIC_PER_SHEET) - user.show_message("You need at least [FABRIC_PER_SHEET] units of fabric before using this.", 1) + if(W.amount < FABRIC_PER_SHEET) + user.show_message("You need at least [FABRIC_PER_SHEET] units of fabric before using this.", MSG_VISUAL) return FALSE - user.show_message("You start weaving \the [S.name] through the loom..", MSG_VISUAL) - if(S.use_tool(src, user, S.pull_effort)) - if(S.amount >= FABRIC_PER_SHEET) - new S.loom_result(drop_location()) - S.use(FABRIC_PER_SHEET) - user.show_message("You weave \the [S.name] into a workable fabric.", MSG_VISUAL) + user.show_message("You start weaving \the [W.name] through the loom..", MSG_VISUAL) + if(W.use_tool(src, user, W.pull_effort)) + if(W.amount >= FABRIC_PER_SHEET) + new W.loom_result(drop_location()) + W.use(FABRIC_PER_SHEET) + user.show_message("You weave \the [W.name] into a workable fabric.", MSG_VISUAL) return TRUE #undef FABRIC_PER_SHEET \ No newline at end of file diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index a1de5fe6a3..aa31fe9542 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -36,6 +36,7 @@ "You unfasten [src].") var/obj/item/sign_backing/SB = new (get_turf(user)) SB.icon_state = icon_state + SB.set_custom_materials(custom_materials) //This is here so picture frames and wooden things don't get messed up. SB.sign_path = type SB.setDir(dir) qdel(src) diff --git a/code/game/objects/structures/signs/signs_plaques.dm b/code/game/objects/structures/signs/signs_plaques.dm index 78c88cd09d..d1067f1963 100644 --- a/code/game/objects/structures/signs/signs_plaques.dm +++ b/code/game/objects/structures/signs/signs_plaques.dm @@ -46,3 +46,4 @@ name = "Mr. Deempisi portrait" desc = "Under the painting a plaque reads: 'While the meat grinder may not have spared you, fear not. Not one part of you has gone to waste... You were delicious.'" icon_state = "monkey_painting" + custom_materials = list(/datum/material/wood = 2000) //The same as /obj/structure/sign/picture_frame diff --git a/code/game/objects/structures/signs/signs_warning.dm b/code/game/objects/structures/signs/signs_warning.dm index f735ed7bc9..3138d44e9d 100644 --- a/code/game/objects/structures/signs/signs_warning.dm +++ b/code/game/objects/structures/signs/signs_warning.dm @@ -73,3 +73,8 @@ name = "\improper ENGINEERING SAFETY" desc = "A sign detailing the various safety protocols when working on-site to ensure a safe shift." icon_state = "safety" + +/obj/structure/sign/warning/explosives + name = "\improper HIGH EXPLOSIVES sign" + desc = "A warning sign which reads 'HIGH EXPLOSIVES'." + icon_state = "explosives" diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm index 1f9491f4cf..466912f93e 100644 --- a/code/game/objects/structures/statues.dm +++ b/code/game/objects/structures/statues.dm @@ -11,6 +11,12 @@ var/impressiveness = 15 CanAtmosPass = ATMOS_PASS_DENSITY + +/obj/structure/statue/Initialize() + . = ..() + AddElement(/datum/element/art, impressiveness) + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, impressiveness * 75)), 0) + /obj/structure/statue/attackby(obj/item/W, mob/living/user, params) add_fingerprint(user) if(!(flags_1 & NODECONSTRUCT_1)) @@ -29,29 +35,6 @@ return return ..() -/obj/structure/statue/attack_hand(mob/living/user) - . = ..() - if(.) - return - user.changeNext_move(CLICK_CD_MELEE) - add_fingerprint(user) - if(!do_after(user, 20, target = src)) - return - user.visible_message("[user] rubs some dust off [src].", \ - "You take in [src], rubbing some dust off its surface.") - if(!ishuman(user)) // only humans have the capacity to appreciate art - return - var/totalimpressiveness = (impressiveness *(obj_integrity/max_integrity)) - switch(totalimpressiveness) - if(GREAT_ART to 100) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) - if (GOOD_ART to GREAT_ART) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) - if (BAD_ART to GOOD_ART) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) - if (0 to BAD_ART) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) - /obj/structure/statue/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) if(material_drop_type) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 3d552fa236..012d92e103 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -163,6 +163,9 @@ if(istype(I, /obj/item/storage/bag/tray)) var/obj/item/storage/bag/tray/T = I if(T.contents.len > 0) // If the tray isn't empty + for(var/x in T.contents) + var/obj/item/item = x + AfterPutItemOnTable(item, user) SEND_SIGNAL(I, COMSIG_TRY_STORAGE_QUICK_EMPTY, drop_location()) user.visible_message("[user] empties [I] on [src].") return @@ -177,10 +180,14 @@ //Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf) I.pixel_x = clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2) I.pixel_y = clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2) - return 1 + AfterPutItemOnTable(I, user) + return TRUE else return ..() +/obj/structure/table/proc/AfterPutItemOnTable(obj/item/I, mob/living/user) + return + /obj/structure/table/alt_attack_hand(mob/user) if(user && Adjacent(user) && !user.incapacitated()) user.changeNext_move(CLICK_CD_MELEE*0.5) @@ -214,6 +221,37 @@ material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS buildstack = null //No buildstack, so generate from mat datums +///Table on wheels +/obj/structure/table/rolling + name = "Rolling table" + desc = "A NT brand \"Rolly poly\" rolling table. It can and will move." + anchored = FALSE + smooth = SMOOTH_FALSE + canSmoothWith = list() + icon = 'icons/obj/smooth_structures/rollingtable.dmi' + icon_state = "rollingtable" + var/list/attached_items = list() + +/obj/structure/table/rolling/AfterPutItemOnTable(obj/item/I, mob/living/user) + . = ..() + attached_items += I + RegisterSignal(I, COMSIG_MOVABLE_MOVED, .proc/RemoveItemFromTable) //Listen for the pickup event, unregister on pick-up so we aren't moved + +/obj/structure/table/rolling/proc/RemoveItemFromTable(datum/source, newloc, dir) + if(newloc != loc) //Did we not move with the table? because that shit's ok + return FALSE + attached_items -= source + UnregisterSignal(source, COMSIG_MOVABLE_MOVED) + +/obj/structure/table/rolling/Moved(atom/OldLoc, Dir) + for(var/mob/M in OldLoc.contents)//Kidnap everyone on top + M.forceMove(loc) + for(var/x in attached_items) + var/atom/movable/AM = x + if(!AM.Move(loc)) + RemoveItemFromTable(AM, AM.loc) + return TRUE + /* * Glass tables */ diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 95edd15951..ddf7fa6bc6 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -11,6 +11,8 @@ var/cistern = 0 //if the cistern bit is open var/w_items = 0 //the combined w_class of all the items in the cistern var/mob/living/swirlie = null //the mob being given a swirlie + var/buildstacktype = /obj/item/stack/sheet/metal //they're metal now, shut up + var/buildstackamount = 1 /obj/structure/toilet/Initialize() . = ..() @@ -72,7 +74,18 @@ /obj/structure/toilet/update_icon_state() icon_state = "toilet[open][cistern]" +/obj/structure/toilet/deconstruct() + if(!(flags_1 & NODECONSTRUCT_1)) + if(buildstacktype) + new buildstacktype(loc,buildstackamount) + else + for(var/i in custom_materials) + var/datum/material/M = i + new M.sheet_type(loc, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1)) + ..() + /obj/structure/toilet/attackby(obj/item/I, mob/living/user, params) + add_fingerprint(user) if(istype(I, /obj/item/crowbar)) to_chat(user, "You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]...") playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1) @@ -80,7 +93,9 @@ user.visible_message("[user] [cistern ? "replaces the lid on the cistern" : "lifts the lid off the cistern"]!", "You [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]!", "You hear grinding porcelain.") cistern = !cistern update_icon() - + else if(I.tool_behaviour == TOOL_WRENCH && !(flags_1&NODECONSTRUCT_1)) + I.play_tool_sound(src) + deconstruct() else if(cistern) if(user.a_intent != INTENT_HARM) if(I.w_class > WEIGHT_CLASS_NORMAL) @@ -95,6 +110,10 @@ w_items += I.w_class to_chat(user, "You carefully place [I] into the cistern.") + if(istype(I, /obj/item/reagent_containers/food/snacks/cube)) + var/obj/item/reagent_containers/food/snacks/cube/cube = I + cube.Expand() + return else if(istype(I, /obj/item/reagent_containers)) if (!open) return @@ -130,6 +149,11 @@ /obj/structure/toilet/secret/prison secret_type = /obj/effect/spawner/lootdrop/prison_loot_toilet +/obj/structure/toilet/greyscale + + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR + buildstacktype = null + /obj/structure/urinal name = "urinal" desc = "The HU-452, an experimental urinal. Comes complete with experimental urinal cake." @@ -459,6 +483,8 @@ anchored = TRUE var/busy = FALSE //Something's being washed at the moment var/dispensedreagent = /datum/reagent/water // for whenever plumbing happens + var/buildstacktype = /obj/item/stack/sheet/metal + var/buildstackamount = 1 /obj/structure/sink/attack_hand(mob/living/user) . = ..() @@ -520,7 +546,7 @@ if(istype(O, /obj/item/melee/baton)) var/obj/item/melee/baton/B = O if(B.cell) - if(B.cell.charge > 0 && B.status == 1) + if(B.cell.charge > 0 && B.turned_on) flick("baton_active", src) var/stunforce = B.stamforce user.DefaultCombatKnockdown(stunforce * 2) @@ -537,6 +563,11 @@ playsound(loc, 'sound/effects/slosh.ogg', 25, 1) return + if(O.tool_behaviour == TOOL_WRENCH && !(flags_1&NODECONSTRUCT_1)) + O.play_tool_sound(src) + deconstruct() + return + if(istype(O, /obj/item/stack/medical/gauze)) var/obj/item/stack/medical/gauze/G = O new /obj/item/reagent_containers/rag(src.loc) @@ -568,9 +599,18 @@ else return ..() -/obj/structure/sink/deconstruct(disassembled = TRUE) - new /obj/item/stack/sheet/metal (loc, 3) - qdel(src) +/obj/structure/sink/deconstruct() + if(!(flags_1 & NODECONSTRUCT_1)) + drop_materials() + ..() + +/obj/structure/sink/proc/drop_materials() + if(buildstacktype) + new buildstacktype(loc,buildstackamount) + else + for(var/i in custom_materials) + var/datum/material/M = i + new M.sheet_type(loc, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1)) /obj/structure/sink/kitchen name = "kitchen sink" @@ -655,6 +695,11 @@ icon_state = "puddle" resistance_flags = UNACIDABLE +/obj/structure/sink/greyscale + icon_state = "sink_greyscale" + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR + buildstacktype = null + //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/structure/sink/puddle/attack_hand(mob/M) icon_state = "puddle-splash" @@ -669,6 +714,10 @@ /obj/structure/sink/puddle/deconstruct(disassembled = TRUE) qdel(src) +/obj/structure/sink/greyscale + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR + buildstacktype = null + //Shower Curtains// //Defines used are pre-existing in layers.dm// diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 3a719d05b9..38e0839617 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -80,7 +80,10 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( var/old_dynamic_lighting = dynamic_lighting var/old_affecting_lights = affecting_lights var/old_lighting_object = lighting_object - var/old_corners = corners + var/old_lc_topright = lc_topright + var/old_lc_topleft = lc_topleft + var/old_lc_bottomright = lc_bottomright + var/old_lc_bottomleft = lc_bottomleft var/old_exl = explosion_level var/old_exi = explosion_id @@ -119,7 +122,10 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( recalc_atom_opacity() lighting_object = old_lighting_object affecting_lights = old_affecting_lights - corners = old_corners + lc_topright = old_lc_topright + lc_topleft = old_lc_topleft + lc_bottomright = old_lc_bottomright + lc_bottomleft = old_lc_bottomleft if (old_opacity != opacity || dynamic_lighting != old_dynamic_lighting) reconsider_lights() diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index c9b429cecc..06cd38a4c3 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -11,6 +11,7 @@ desc = "Stylish dark wood." icon_state = "wood" floor_tile = /obj/item/stack/tile/wood + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 0.25) broken_states = list("wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7") footstep = FOOTSTEP_WOOD barefootstep = FOOTSTEP_WOOD_BAREFOOT diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm index af48160ef1..0f366fae03 100644 --- a/code/game/turfs/simulated/floor/plasteel_floor.dm +++ b/code/game/turfs/simulated/floor/plasteel_floor.dm @@ -146,3 +146,95 @@ /turf/open/floor/plasteel/sepia icon_state = "sepia" + +/////////////////////////////// +// Pre-Applied Decal Floors // +////////////////////////////// + +// Neutral +/turf/open/floor/plasteel/neutral + icon_state = "neutral_full" +/turf/open/floor/plasteel/neutral/side + icon_state = "neutral" +/turf/open/floor/plasteel/neutral/corner + icon_state = "neutral_corner" + +// Dark Neutral +/turf/open/floor/plasteel/dark/neutral + icon_state = "dark_neutral_full" +/turf/open/floor/plasteel/dark/neutral/checker + icon_state = "dark_neutral_checker" +/turf/open/floor/plasteel/dark/neutral/side + icon_state = "dark_neutral" +/turf/open/floor/plasteel/dark/neutral/corner + icon_state = "dark_neutral_corner" + +// Dark Security +/turf/open/floor/plasteel/dark/security + icon_state = "dark_red_full" +/turf/open/floor/plasteel/dark/security/checker + icon_state = "dark_red_checker" +/turf/open/floor/plasteel/dark/security/side + icon_state = "dark_red" +/turf/open/floor/plasteel/dark/security/corner + icon_state = "dark_red_corner" + +// Engineering +/turf/open/floor/plasteel/engineering + icon_state = "engineering_full" +/turf/open/floor/plasteel/engineering/side + icon_state = "engineering" +/turf/open/floor/plasteel/engineering/corner + icon_state = "engineering_corner" + +// Atmospherics +/turf/open/floor/plasteel/atmospherics + icon_state = "atmospherics_full" +/turf/open/floor/plasteel/atmospherics/side + icon_state = "atmospherics" +/turf/open/floor/plasteel/atmospherics/corner + icon_state = "atmospherics_corner" + +// Command +/turf/open/floor/plasteel/command + icon_state = "command_full" +/turf/open/floor/plasteel/command/side + icon_state = "command" +/turf/open/floor/plasteel/command/corner + icon_state = "command_corner" + +// Medical +/turf/open/floor/plasteel/medical + icon_state = "medical_full" +/turf/open/floor/plasteel/medical/alt + icon_state = "medical_alt" +/turf/open/floor/plasteel/medical/side + icon_state = "medical" +/turf/open/floor/plasteel/medical/corner + icon_state = "medical_corner" + +// Security +/turf/open/floor/plasteel/security + icon_state = "security_full" +/turf/open/floor/plasteel/security/side + icon_state = "security" +/turf/open/floor/plasteel/security/corner + icon_state = "security_corner" + +// Cargo +/turf/open/floor/plasteel/cargo + icon_state = "cargo_full" +/turf/open/floor/plasteel/cargo/side + icon_state = "cargo" +/turf/open/floor/plasteel/cargo/corner + icon_state = "cargo_corner" + +// Misc +/turf/open/floor/plasteel/showroomfloor/shower + icon_state = "shower" +/turf/open/floor/plasteel/goonplaque/alien + icon_state = "plaque1" + desc = "\"This is a plaque is a collaboration of iconography celebrating the peaceful collaboration between the people of Earth and distant alien species." +/turf/open/floor/plasteel/goonplaque/charter + icon_state = "plaque2" + desc = "\"A golden plaque. Etched into it is the introductory article for a cross-species interplanetary constitution, guaranteeing equal rights between species that Nanotrasen relunctantly agreed to." diff --git a/code/game/turfs/simulated/floor/plating/misc_plating.dm b/code/game/turfs/simulated/floor/plating/misc_plating.dm index 23e32ebfe3..5323db001f 100644 --- a/code/game/turfs/simulated/floor/plating/misc_plating.dm +++ b/code/game/turfs/simulated/floor/plating/misc_plating.dm @@ -198,8 +198,7 @@ /turf/open/floor/plating/ice/smooth icon_state = "smooth" smooth = SMOOTH_MORE | SMOOTH_BORDER - canSmoothWith = list(/turf/open/floor/plating/ice/smooth, /turf/open/floor/plating/ice) - /turf/open/floor/plating/ice/colder + canSmoothWith = list(/turf/open/floor/plating/ice/smooth, /turf/open/floor/plating/ice, /turf/open/floor/plating/ice/colder) /turf/open/floor/plating/ice/colder temperature = 140 diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index dd2b9dfa18..2f223f2c40 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -81,10 +81,25 @@ /turf/open/lava/TakeTemperature(temp) +/turf/open/lava/attackby(obj/item/C, mob/user, params) + ..() + if(istype(C, /obj/item/stack/rods/lava)) + var/obj/item/stack/rods/lava/R = C + var/obj/structure/lattice/lava/H = locate(/obj/structure/lattice/lava, src) + if(H) + to_chat(user, "There is already a lattice here!") + return + if(R.use(1)) + to_chat(user, "You construct a lattice.") + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) + new /obj/structure/lattice/lava(locate(x, y, z)) + else + to_chat(user, "You need one rod to build a heatproof lattice.") + return /turf/open/lava/proc/is_safe() //if anything matching this typecache is found in the lava, we don't burn things - var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile)) + var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile, /obj/structure/lattice/lava)) var/list/found_safeties = typecache_filter_list(contents, lava_safeties_typecache) for(var/obj/structure/stone_tile/S in found_safeties) if(S.fallen) diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index 7d476d559e..048394b942 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -832,7 +832,7 @@ initial_gas_mix = OPENTURF_DEFAULT_ATMOS defer_change = TRUE - + /turf/closed/mineral/gibtonite/ice environment_type = "snow_cavern" icon_state = "icerock_Gibtonite" @@ -846,3 +846,55 @@ turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS + +/turf/closed/mineral/strong + name = "Very strong rock" + desc = "Seems to be stronger than the other rocks in the area. Only a master of mining techniques could destroy this." + environment_type = "basalt" + turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface + baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface + initial_gas_mix = LAVALAND_DEFAULT_ATMOS + defer_change = 1 + smooth_icon = 'icons/turf/walls/rock_wall.dmi' + +/* +/turf/closed/mineral/strong/attackby(obj/item/I, mob/user, params) + if(!ishuman(user)) + to_chat(usr, "Only a more advanced species could break a rock such as this one!") + return FALSE + var/mob/living/carbon/human/H = user + if(H.mind.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER) + . = ..() + else + to_chat(usr, "The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner.") +*/ + +/turf/closed/mineral/strong/gets_drilled(mob/user) + if(!ishuman(user)) + return // see attackby + /* + var/mob/living/carbon/human/H = user + if(!(H.mind.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER)) + return + */ + drop_ores() +// H.client.give_award(/datum/award/achievement/skill/legendary_miner, H) + var/flags = NONE + if(defer_change) // TODO: make the defer change var a var for any changeturf flag + flags = CHANGETURF_DEFER_CHANGE + ScrapeAway(flags=flags) + addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE) + playsound(src, 'sound/effects/break_stone.ogg', 50, TRUE) //beautiful destruction +// H.mind.adjust_experience(/datum/skill/mining, 100) //yay! + +/turf/closed/mineral/strong/proc/drop_ores() + if(prob(10)) + new /obj/item/stack/sheet/mineral/mythril(src, 5) + else + new /obj/item/stack/sheet/mineral/adamantine(src, 5) + +/turf/closed/mineral/strong/acid_melt() + return + +/turf/closed/mineral/strong/ex_act(severity, target) + return diff --git a/code/game/world.dm b/code/game/world.dm index 904954e49e..bc5f28594a 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -136,6 +136,7 @@ GLOBAL_LIST(topic_status_cache) 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" + GLOB.click_log = "[GLOB.log_directory]/click.log" GLOB.world_asset_log = "[GLOB.log_directory]/asset.log" @@ -156,6 +157,7 @@ GLOBAL_LIST(topic_status_cache) start_log(GLOB.subsystem_log) start_log(GLOB.reagent_log) start_log(GLOB.world_crafting_log) + start_log(GLOB.click_log) GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently if(fexists(GLOB.config_error_log)) diff --git a/code/modules/admin/chat_commands.dm b/code/modules/admin/chat_commands.dm index e2ddcdcf6a..9b15729a9e 100644 --- a/code/modules/admin/chat_commands.dm +++ b/code/modules/admin/chat_commands.dm @@ -142,3 +142,51 @@ GLOBAL_LIST(round_end_notifiees) log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.") message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.") return "[params] has been added to the current round's bunker bypass list." + +// More (silly) chat commands citadel added. +/datum/tgs_chat_command/wheelofsalt + name = "wheelofsalt" + help_text = "What are Citadel Station 13 players salting about today? Spin the wheel and find out!" + +/datum/tgs_chat_command/wheelofsalt/Run(datum/tgs_chat_user/sender, params) + var/saltresult = "The wheel of salt [pick("clatters","screams","vibrates","clanks","resonates","groans","moans","squeaks","emits a[pick(" god-forsaken"," lewd"," creepy"," generic","n orgasmic"," demonic")] [pick("airhorn","bike horn","trumpet","clown","latex","vore","dog","laughing")] noise")] as it spins violently... And it seems the salt of the day is the " + var/saltprimarysubject = "[pick("combat","medical","grab","furry","wall","orgasm","cat","ERP","lizard","dog","latex","vision cone","atmospherics","table","chem","vore","dogborg","Skylar Lineman","Mekhi Anderson","Peppermint","rework","cum","dick","cockvore","Medihound","sleeper","belly sleeper","door wires","flightsuit","coder privilege","Developer abuse","ban reason","github self merge","red panda","beret","male catgirl","powergame","hexacrocin","Discord server","Clitadel","Cargonia","Solarian Republic","Main and RP merger","bluespace","salt","chem dispenser theft","Botany","moth","BWOINK","anal vore","stamina","Mason Jakops","mining","noodle","milf","Lavaland","Necropolis","Ashwalker","Chase Redtail","Drew Mint","Pavel Marsk","Joker Amari","Durgit","chaplain","Antag","nanite","Syndicate","Nar-Sie","Ratvar","Cult","maint","Foam-Force","AI","cyborg","ghost","clockwork","cyberpunk","vaporwave","Clown","Leon Beech","Mime","security","research","Megafauna","Bubblegum","Ash Drake","Legion","Colossus","White Shuttle","Changeling","Cowboy","Space Ninja","Poly","Revolutionary","Skyrim","forbidden fruits","xenomorph","blob","Nuclear Operative","crossdressing")]" + var/saltsecondarysubject = "[pick("rework","changes","r34","ban","removal","addition","leak","proposal","fanart","introduction","tabling","ERP","bikeshedding","crossdressing","sprites","semen keg","argument","theft","nerf","screeching","salt","creampie","lewding","murder","kissing","marriage","replacement","fucking","ship","netflix adaptation","dance","remaster","system","voyeur","decoration","pre-order","bukkake","seduction","worship","gangbang","handholding")]" + if(prob(10)) + saltresult += "@here for your salt, all day every day" + if(prob(1)) + saltresult += " @everyone gets some salt this time too" + else + saltresult += "[saltprimarysubject] [saltsecondarysubject]" + return "[saltresult]!" + +/datum/tgs_chat_command/valentine + name = "valentine" + help_text = "Get a random flirt line." + +/datum/tgs_chat_command/valentine/Run(datum/tgs_chat_user/sender, params) + return "[pick(GLOB.flirts)]" + +/datum/tgs_chat_command/despacito + name = "despacito" //someone please high effort this sometime and make it a full on ytdl search + help_text = "This is so sad." + +/datum/tgs_chat_command/despacito/Run() + return "https://www.youtube.com/watch?v=kJQP7kiw5Fk" + +/datum/tgs_chat_command/poly + name = "poly" + help_text = "The Lewder, more applicable Poly speak for Citadel Station 13." + var/list/speech_buffer + +/datum/tgs_chat_command/poly/Run() + LAZYINITLIST(speech_buffer) //I figure this is just safe to do for everything at this point + if(length(speech_buffer)) //Let's not look up the whole json EVERY TIME, just the first time. + return "[pick(speech_buffer)]" + else + var/json_file = file("data/npc_saves/Poly.json") + if(!fexists(json_file)) + return "**BAWWWWWK!** LEAVE THE HEADSET! ***BAWKKKKK!!***" + var/list/json = json_decode(file2text(json_file)) + speech_buffer = json["phrases"] + return "[pick(speech_buffer)]" diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm index 4e4b270c12..47a98623db 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm @@ -177,7 +177,7 @@ if(owner.current.blood_volume < BLOOD_VOLUME_BAD / 2) owner.current.blur_eyes(8 - 8 * (owner.current.blood_volume / BLOOD_VOLUME_BAD)) // Nutrition - owner.current.set_nutrition(min(owner.current.blood_volume, NUTRITION_LEVEL_FULL)) //The amount of blood is how full we are. + owner.current.set_nutrition(min(owner.current.blood_volume, NUTRITION_LEVEL_FED)) //The amount of blood is how full we are. //A bit higher regeneration based on blood volume if(owner.current.blood_volume < 700) additional_regen = 0.4 diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 0feb6dfa7e..888db8193b 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -39,7 +39,7 @@ var/passive_blood_drain = -0.1 //The amount of blood we loose each bloodsucker life() tick // LISTS var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_NIGHT_VISION, \ - TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE) + TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE, TRAIT_NODECAP, TRAIT_NOGUT) /datum/antagonist/bloodsucker/on_gain() SSticker.mode.bloodsuckers |= owner // Add if not already in here (and you might be, if you were picked at round start) diff --git a/code/modules/antagonists/bloodsucker/powers/feed.dm b/code/modules/antagonists/bloodsucker/powers/feed.dm index cbb9693fba..a113f9c083 100644 --- a/code/modules/antagonists/bloodsucker/powers/feed.dm +++ b/code/modules/antagonists/bloodsucker/powers/feed.dm @@ -43,10 +43,14 @@ to_chat(owner, "Lesser beings require a tighter grip.") return FALSE // Bloodsuckers: - else if(iscarbon(target) && target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) - if(display_error) - to_chat(owner, "Other Bloodsuckers will not fall for your subtle approach.") - return FALSE + else if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(!H.can_inject(owner, TRUE, BODY_ZONE_CHEST)) + return FALSE + if(target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) + if(display_error) + to_chat(owner, "Other Bloodsuckers will not fall for your subtle approach.") + return FALSE // Must have Target if(!target) // || !ismob(target) if(display_error) @@ -63,6 +67,8 @@ return FALSE if(ishuman(target)) var/mob/living/carbon/human/H = target + if(!H.can_inject(owner, TRUE, BODY_ZONE_HEAD) && target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE) + return FALSE if(NOBLOOD in H.dna.species.species_traits)// || owner.get_blood_id() != target.get_blood_id()) if(display_error) to_chat(owner, "Your victim's blood is not suitable for you to take.") diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm index a4b19f2d40..f1ce13a90f 100644 --- a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm +++ b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm @@ -113,6 +113,8 @@ "You start tenderly lifting [skewee] off of [src]...") if(!do_after(user, 60, target = skewee)) skewee.visible_message("[skewee] painfully slides back down [src].") + if(skewee.stat >= UNCONSCIOUS) + return //by ratvar, no more spamming my deadchat, holy fuck skewee.say("Oof, ouch owwie!!", forced = "fail brass skewer removal") return skewee.visible_message("[skewee] comes free of [src] with a squelching pop!", \ diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 93927f4420..58e826b36d 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -244,6 +244,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) if(!ispath(path)) path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around gases[path] = text2num(gas[id]) + archive() return 1 /datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4) diff --git a/code/modules/client/client_colour.dm b/code/modules/client/client_colour.dm index 22b15ea868..d89598f6cb 100644 --- a/code/modules/client/client_colour.dm +++ b/code/modules/client/client_colour.dm @@ -17,11 +17,6 @@ //eg: "Bloody screen" > "goggles colour" as the former is much more important -/mob - var/list/client_colours = list() - - - /* Adds an instance of colour_type to the mob's client_colours list colour_type - a typepath (subtyped from /datum/client_colour) @@ -113,4 +108,4 @@ priority = INFINITY //we can't see colors anyway! /datum/client_colour/monochrome/trance - priority = 1 \ No newline at end of file + priority = 1 diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 47255d9535..7d87a82afb 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -99,5 +99,37 @@ /// custom movement keys for this client var/list/movement_keys = list() + ///Autoclick list of two elements, first being the clicked thing, second being the parameters. + var/list/atom/selected_target[2] + ///Autoclick variable referencing the associated item. + var/obj/item/active_mousedown_item = null + ///Used in MouseDrag to preserve the original mouse click parameters + var/mouseParams = "" + ///Used in MouseDrag to preserve the last mouse-entered location. + var/mouseLocation = null + ///Used in MouseDrag to preserve the last mouse-entered object. + var/mouseObject = null + var/mouseControlObject = null + //Middle-mouse-button click dragtime control for aimbot exploit detection. + var/middragtime = 0 + //Middle-mouse-button clicked object control for aimbot exploit detection. + var/atom/middragatom + /// Messages currently seen by this client var/list/seen_messages + ///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns + var/cryo_warned = -5 MINUTES + + var/list/parallax_layers + var/list/parallax_layers_cached + var/atom/movable/movingmob + var/turf/previous_turf + ///world.time of when we can state animate()ing parallax again + var/dont_animate_parallax + ///world.time of last parallax update + var/last_parallax_shift + ///ds between parallax updates + var/parallax_throttle = 0 + var/parallax_movedir = 0 + var/parallax_layers_max = 3 + var/parallax_animate_timer diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 38afc9fa45..6cb5f334df 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -791,7 +791,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) log_game("[key_name(src)] is using the middle click aimbot exploit") message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] is using the middle click aimbot exploit") add_system_note("aimbot", "Is using the middle click aimbot exploit") - + log_click(object, location, control, params, src, "lockout (spam - minute ab c [ab] s [middragtime])", TRUE) + else + log_click(object, location, control, params, src, "lockout (spam - minute)", TRUE) log_game("[key_name(src)] Has hit the per-minute click limit of [mcl] clicks in a given game minute") message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute click limit of [mcl] clicks in a given game minute") to_chat(src, "[msg]") @@ -811,8 +813,12 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) return if(ab) //Citadel edit, things with stuff. + log_click(object, location, control, params, src, "dropped (ab c [ab] s [middragtime])", TRUE) return + if(prefs.log_clicks) + log_click(object, location, control, params, src) + if (prefs.hotkeys) // If hotkey mode is enabled, then clicking the map will automatically // unfocus the text bar. This removes the red color from the text bar diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 77bcbacfcf..040b56f124 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -15,6 +15,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/muted = 0 var/last_ip var/last_id + var/log_clicks = FALSE var/icon/custom_holoform_icon var/list/cached_holoform_icons diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index a7384ad392..a2da5d1ae2 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -317,8 +317,23 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car no_tetris_storage = sanitize_integer(no_tetris_storage, 0, 1, initial(no_tetris_storage)) key_bindings = sanitize_islist(key_bindings, list()) + verify_keybindings_valid() // one of these days this will runtime and you'll be glad that i put it in a different proc so no one gets their saves wiped + return 1 +/datum/preferences/proc/verify_keybindings_valid() + // Sanitize the actual keybinds to make sure they exist. + for(var/key in key_bindings) + if(!islist(key_bindings[key])) + key_bindings -= key + var/list/binds = key_bindings[key] + for(var/bind in binds) + if(!GLOB.keybindings_by_name[bind]) + binds -= bind + if(!length(binds)) + key_bindings -= key + // End + /datum/preferences/proc/save_preferences() if(!path) return 0 diff --git a/code/modules/clothing/glasses/phantomthief.dm b/code/modules/clothing/glasses/phantomthief.dm index fecf660450..6d209ec695 100644 --- a/code/modules/clothing/glasses/phantomthief.dm +++ b/code/modules/clothing/glasses/phantomthief.dm @@ -24,7 +24,7 @@ . += "[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again." /obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/living/user, was_forced = FALSE) - if(user.combat_flags & COMBAT_FLAG_COMBAT_TOGGLED && world.time >= nextadrenalinepop) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_TOGGLED) && world.time >= nextadrenalinepop) nextadrenalinepop = world.time + 5 MINUTES user.reagents.add_reagent(/datum/reagent/syndicateadrenals, 5) user.playsound_local(user, 'sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE) diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 63521c9b75..31e9407cdb 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -13,6 +13,53 @@ custom_price = 1200 custom_premium_price = 1200 +/obj/item/toy/sprayoncan + name = "spray-on insulation applicator" + desc = "What is the number one problem facing our station today?" + icon = 'icons/obj/clothing/gloves.dmi' + icon_state = "sprayoncan" + +/obj/item/toy/sprayoncan/afterattack(atom/target, mob/living/carbon/user, proximity) + if(iscarbon(target) && proximity) + var/mob/living/carbon/C = target + var/mob/living/carbon/U = user + var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, TRUE, TRUE) + if(success) + if(C == user) + C.visible_message("[U] sprays their hands with glittery rubber!") + else + C.visible_message("[U] sprays glittery rubber on the hands of [C]!") + else + C.visible_message("The rubber fails to stick to [C]'s hands!") + + qdel(src) + +/obj/item/clothing/gloves/color/yellow/sprayon + desc = "How're you gonna get 'em off, nerd?" + name = "spray-on insulated gloves" + icon_state = "sprayon" + item_state = "sprayon" + permeability_coefficient = 0 + resistance_flags = ACID_PROOF + var/shocks_remaining = 10 + +/obj/item/clothing/gloves/color/yellow/sprayon/Initialize() + .=..() + ADD_TRAIT(src, TRAIT_NODROP, GLOVE_TRAIT) + +/obj/item/clothing/gloves/color/yellow/sprayon/equipped(mob/user, slot) + . = ..() + RegisterSignal(user, COMSIG_LIVING_SHOCK_PREVENTED, .proc/Shocked) + +/obj/item/clothing/gloves/color/yellow/sprayon/proc/Shocked() + shocks_remaining-- + if(shocks_remaining < 0) + qdel(src) //if we run out of uses, the gloves crumble away into nothing, just like my dreams after working with .dm + +/obj/item/clothing/gloves/color/yellow/sprayon/dropped() + .=..() + qdel(src) //loose nodrop items bad + /obj/item/clothing/gloves/color/fyellow //Cheap Chinese Crap desc = "These gloves are cheap knockoffs of the coveted ones - no way this can end badly." name = "budget insulated gloves" @@ -202,6 +249,17 @@ permeability_coefficient = 0.3 resistance_flags = FIRE_PROOF | ACID_PROOF +/obj/item/clothing/gloves/color/latex/engineering + name = "tinker's gloves" + desc = "Overdesigned engineering gloves that have automated construction subrutines dialed in, allowing for faster construction while worn." + icon = 'icons/obj/clothing/clockwork_garb.dmi' + icon_state = "clockwork_gauntlets" + item_state = "clockwork_gauntlets" + siemens_coefficient = 0.8 + permeability_coefficient = 0.3 + carrytrait = TRAIT_QUICK_BUILD + custom_materials = list(/datum/material/iron=2000, /datum/material/silver=1500, /datum/material/gold = 1000) + /obj/item/clothing/gloves/color/white name = "white gloves" desc = "These look pretty fancy." diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index ffd50cbfbe..80d0b7c8a8 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -60,6 +60,16 @@ cold_protection = HEAD min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT +/obj/item/clothing/head/hardhat/red/upgraded + name = "workplace-ready firefighter helmet" + desc = "By applying state of the art lighting technology to a fire helmet, and using photo-chemical hardening methods, this hardhat will protect you from robust workplace hazards." + icon_state = "hardhat0_purple" + item_state = "hardhat0_purple" + brightness_on = 5 + resistance_flags = FIRE_PROOF | ACID_PROOF + custom_materials = list(/datum/material/iron = 4000, /datum/material/glass = 1000, /datum/material/plastic = 3000, /datum/material/silver = 500) + hat_type = "purple" + /obj/item/clothing/head/hardhat/white icon_state = "hardhat0_white" item_state = "hardhat0_white" diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 90b3d7d86b..2778c6abeb 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -198,6 +198,7 @@ desc = "A creepy wooden mask. Surprisingly expressive for a poorly carved bit of wood." icon_state = "tiki_eyebrow" item_state = "tiki_eyebrow" + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 1.25) resistance_flags = FLAMMABLE max_integrity = 100 actions_types = list(/datum/action/item_action/adjust) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 9c6c81372a..b197f4cf38 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -45,6 +45,7 @@ desc = "A pair of rather plain wooden sandals." name = "sandals" icon_state = "wizard" + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 0.5) strip_delay = 50 equip_delay_other = 50 permeability_coefficient = 0.9 diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index f4fd3f7bf3..3d55e569dc 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -444,7 +444,6 @@ Contains: desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats. Alas, this one looks pretty worn out and rusted." armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) slowdown = 0.8 - obj_flags = IMMUTABLE_SLOW //rest in peace rusty joints. helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old charges = 12 @@ -470,7 +469,6 @@ Contains: desc = "Voices echo from the hardsuit, driving the user insane. This one is pretty battle-worn, but still fearsome." armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) slowdown = 0.8 - obj_flags = IMMUTABLE_SLOW //rest in peace rusty joints. helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old charges = 6 diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index e392a6b2d1..047dc7b7a3 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -165,31 +165,134 @@ var/robe_charge = TRUE actions_types = list(/datum/action/item_action/stickmen) +/obj/item/clothing/suit/wizrobe/paper/item_action_slot_check(slot, mob/user, datum/action/A) + if(A.type == /datum/action/item_action/stickmen && slot != SLOT_WEAR_SUIT) + return FALSE + return ..() -/obj/item/clothing/suit/wizrobe/paper/ui_action_click(mob/user, action) - stickmen() +//Stickmemes. VV-friendly. +/datum/action/item_action/stickmen + name = "Summon Stick Minions" + desc = "Allows you to summon faithful stickmen allies to aide you in battle." + icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon_state = "art_summon" + var/ready = TRUE + var/list/summoned_stickmen = list() + var/summoned_mob_path = /mob/living/simple_animal/hostile/stickman //Must be an hostile animal path. + var/max_stickmen = 8 + var/cooldown = 3 SECONDS + var/list/book_of_grudges = list() + +/datum/action/item_action/stickmen/New(Target) + ..() + if(isitem(Target)) + RegisterSignal(Target, COMSIG_PARENT_EXAMINE, .proc/give_infos) + +/datum/action/item_action/stickmen/Destroy() + for(var/A in summoned_stickmen) + var/mob/living/simple_animal/hostile/S = A + if(S.client) + to_chat(S, "A dizzying sensation strikes you as the comglomerate of pencil lines you call \ + your body crumbles under the pressure of an invisible eraser, soon to join bilions discarded sketches. \ + It seems whatever was keeping you in this realm has come to an end, like all things.") + animate(S, alpha = 0, time = 5 SECONDS) + QDEL_IN(S, 5 SECONDS) + return ..() + +/datum/action/item_action/stickmen/proc/give_infos(atom/source, mob/user, list/examine_list) + examine_list += "Making sure you are properly wearing or holding it, \ + point at whatever you want to rally your minions to its position." + examine_list += "While on harm intent, pointed mobs (minus you and the minions) \ + will also be marked as foes for your minions to attack for the next 2 minutes." + +/datum/action/item_action/stickmen/Grant(mob/M) + . = ..() + if(owner) + RegisterSignal(M, COMSIG_MOB_POINTED, .proc/rally) + if(book_of_grudges[M]) //Stop attacking your new master. + book_of_grudges -= M + for(var/A in summoned_stickmen) + var/mob/living/simple_animal/hostile/S = A + if(!S.mind) + S.LoseTarget() -/obj/item/clothing/suit/wizrobe/paper/verb/stickmen() - set category = "Object" - set name = "Summon Stick Minions" - set src in usr - if(!isliving(usr)) +/datum/action/item_action/stickmen/Remove(mob/M) + . = ..() + UnregisterSignal(M, COMSIG_MOB_POINTED) + +/datum/action/item_action/stickmen/Trigger() + . = ..() + if(!.) return - if(!robe_charge) - to_chat(usr, "\The robe's internal magic supply is still recharging!") + if(!ready) + to_chat(owner, "[src]'s internal magic supply is still recharging!") + return FALSE + var/summon = TRUE + if(length(summoned_stickmen) >= max_stickmen) + var/mob/living/simple_animal/hostile/S = popleft(summoned_stickmen) + if(!S.client) + qdel(S) + else + S.forceMove(owner.drop_location()) + S.revive(TRUE) + summoned_stickmen[S] = TRUE + summon = FALSE + + owner.say("Rise, my creation! Off your page into this realm!", forced = "stickman summoning") + playsound(owner, 'sound/magic/summon_magic.ogg', 50, 1, 1) + if(summon) + var/mob/living/simple_animal/hostile/S = new summoned_mob_path (get_turf(usr)) + S.faction = owner.faction + S.foes = book_of_grudges + RegisterSignal(S, COMSIG_PARENT_QDELETING, .proc/remove_from_list) + ready = FALSE + addtimer(CALLBACK(src, .proc/ready_again), cooldown) + +/datum/action/item_action/stickmen/proc/remove_from_list(datum/source, forced) + summoned_stickmen -= source + +/datum/action/item_action/stickmen/proc/ready_again() + ready = TRUE + if(owner) + to_chat(owner, "[src] hums, its internal magic supply restored.") + +/** + * Rallies your army of stickmen to whichever target the user is pointing. + * Should the user be on harm intent and the target be a living mob that's not the user or a fellow stickman, + * said target will be added to a list of foes which the stickmen will gladly dispose regardless of faction. + * This is designed so stickmen will move toward whatever you point at even when you don't want to, that's the downside. + */ +/datum/action/item_action/stickmen/proc/rally(mob/source, atom/A) + var/turf/T = get_turf(A) + var/list/surrounding_turfs = block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + 1, T.y + 1, T.z)) + if(!surrounding_turfs.len) return + if(source.a_intent == INTENT_HARM && A != source && !summoned_stickmen[A]) + var/mob/living/L + if(isliving(A)) //Gettem boys! + L = A + else if(ismecha(A)) + var/obj/mecha/M = A + L = M.occupant + if(L && L.stat != DEAD && !HAS_TRAIT(L, TRAIT_DEATHCOMA)) //Taking revenge on the deads would be proposterous. + addtimer(CALLBACK(src, .proc/clear_grudge, L), 2 MINUTES, TIMER_OVERRIDE|TIMER_UNIQUE) + if(!book_of_grudges[L]) + RegisterSignal(L, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_DEATH), .proc/grudge_settled) + book_of_grudges[L] = TRUE + for(var/k in summoned_stickmen) //Shamelessly copied from the blob rally power + var/mob/living/simple_animal/hostile/S = k + if(!S.mind && isturf(S.loc) && get_dist(S, T) <= 10) + S.LoseTarget() + S.Goto(pick(surrounding_turfs), S.move_to_delay) - usr.say("Rise, my creation! Off your page into this realm!", forced = "stickman summoning") - playsound(src.loc, 'sound/magic/summon_magic.ogg', 50, 1, 1) - var/mob/living/M = new /mob/living/simple_animal/hostile/stickman(get_turf(usr)) - var/list/factions = usr.faction - M.faction = factions - src.robe_charge = FALSE - sleep(30) - src.robe_charge = TRUE - to_chat(usr, "\The robe hums, its internal magic supply restored.") +/datum/action/item_action/stickmen/proc/clear_grudge(mob/living/L) + if(!QDELETED(L)) + book_of_grudges -= L +/datum/action/item_action/stickmen/proc/grudge_settled(mob/living/L) + UnregisterSignal(L, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_DEATH)) + book_of_grudges -= L //Shielded Armour diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index 77bb7661ba..48fb688d70 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -40,6 +40,7 @@ /datum/reagent/pax, /datum/reagent/consumable/laughter, /datum/reagent/concentrated_barbers_aid, + /datum/reagent/baldium, /datum/reagent/colorful_reagent, /datum/reagent/peaceborg_confuse, /datum/reagent/peaceborg_tire, diff --git a/code/modules/fields/gravity.dm b/code/modules/fields/gravity.dm index 8b16bb6487..2334a84e04 100644 --- a/code/modules/fields/gravity.dm +++ b/code/modules/fields/gravity.dm @@ -2,16 +2,17 @@ name = "modified gravity zone" setup_field_turfs = TRUE var/gravity_value = 0 - var/list/grav_components = list() + var/list/modified_turfs = list() field_shape = FIELD_SHAPE_RADIUS_SQUARE /datum/proximity_monitor/advanced/gravity/setup_field_turf(turf/T) . = ..() - grav_components[T] = T.AddComponent(/datum/component/forced_gravity,gravity_value) + T.AddElement(/datum/element/forced_gravity, gravity_value) + modified_turfs[T] = gravity_value /datum/proximity_monitor/advanced/gravity/cleanup_field_turf(turf/T) . = ..() - var/datum/component/forced_gravity/G = grav_components[T] - grav_components -= T - if(G) - qdel(G) \ No newline at end of file + if(isnull(modified_turfs[T])) + return + T.RemoveElement(/datum/element/forced_gravity, modified_turfs[T]) + modified_turfs -= T \ No newline at end of file diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_frozen.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_frozen.dm index 3e47904e6e..5b81c54bc5 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_frozen.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_frozen.dm @@ -15,7 +15,7 @@ result = /obj/item/reagent_containers/food/snacks/banana_split subcategory = CAT_ICE - /datum/crafting_recipe/food/bluecharrie_float +/datum/crafting_recipe/food/bluecharrie_float name = "Blue Cherry Shake" always_availible = FALSE reqs = list( @@ -276,4 +276,4 @@ /datum/reagent/consumable/laughter = 5 ) result = /obj/item/reagent_containers/food/snacks/snowcones/clown - subcategory = CAT_ICE \ No newline at end of file + subcategory = CAT_ICE diff --git a/code/modules/games/unum.dm b/code/modules/games/unum.dm new file mode 100644 index 0000000000..9820fa6754 --- /dev/null +++ b/code/modules/games/unum.dm @@ -0,0 +1,22 @@ +/// A deck of unum cards. Classic. +/obj/item/toy/cards/deck/unum + name = "\improper UNUM deck" + desc = "A deck of unum cards. House rules to argue over not included." + icon = 'icons/obj/toy.dmi' + icon_state = "deck_unum_full" + deckstyle = "unum" + original_size = 108 + +//Populate the deck. +/obj/item/toy/cards/deck/unum/populate_deck() + for(var/colour in list("Red","Yellow","Green","Blue")) + cards += "[colour] 0" //Uno, i mean, cough cough, Unum decks have only one colour of each 0, weird huh? + for(var/k in 0 to 1) //two of each colour of number + cards += "[colour] skip" + cards += "[colour] reverse" + cards += "[colour] draw 2" + for(var/i in 1 to 9) + cards += "[colour] [i]" + for(var/k in 0 to 3) //4 wilds and draw 4s + cards += "Wildcard" + cards += "Draw 4" diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index d4dc3cb213..3455a97ba2 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -403,6 +403,12 @@ h1.alert, h2.alert {color: #000000;} .his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;} .spooky {color: #FF6100;} .velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;} + +.lethal {color: #bf3d3d; font-weight: bold;} +.stun {color: #0f81bc; font-weight: bold;} +.ion {color: #d084d6; font-weight: bold;} +.xray {color: #32c025; font-weight: bold;} + @keyframes velvet { 0% { color: #400020; } 40% { color: #FF0000; } diff --git a/code/modules/holiday/halloween/bartholomew.dm b/code/modules/holiday/halloween/bartholomew.dm index f51b8b7ea1..4ef00e29cb 100644 --- a/code/modules/holiday/halloween/bartholomew.dm +++ b/code/modules/holiday/halloween/bartholomew.dm @@ -117,7 +117,7 @@ /obj/item/weldingtool = 3, /obj/item/wirecutters = 2, /obj/item/wrench = 4, - /obj/item/weaponcrafting/receiver = 1, + /obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 1, /obj/item/geiger_counter = 3, /obj/item/reagent_containers/food/snacks/grown/citrus/orange = 5, /obj/item/assembly/infra = 1, diff --git a/code/modules/keybindings/keybind/living.dm b/code/modules/keybindings/keybind/living.dm index 0408d0889b..38c666e186 100644 --- a/code/modules/keybindings/keybind/living.dm +++ b/code/modules/keybindings/keybind/living.dm @@ -22,12 +22,8 @@ full_name = "Toggle combat mode" description = "Toggles whether or not you're in combat mode." -/datum/keybinding/living/toggle_combat_mode/can_use(client/user) - return iscarbon(user.mob) // for now, only carbons should be using combat mode, although all livings have combat mode implemented. - /datum/keybinding/living/toggle_combat_mode/down(client/user) - var/mob/living/carbon/C = user.mob - C.user_toggle_intentional_combat_mode() + SEND_SIGNAL(user.mob, COMSIG_TOGGLE_COMBAT_MODE) return TRUE /datum/keybinding/living/toggle_resting diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index d4530acd04..c6e363be07 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -2,11 +2,11 @@ // And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't). // For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting. -// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list. -GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST)) - /datum/lighting_corner - var/list/turf/masters + var/turf/northeast + var/turf/northwest + var/turf/southeast + var/turf/southwest var/list/datum/light_source/affecting // Light sources affecting us. var/active = FALSE // TRUE if one of our masters has dynamic lighting. @@ -25,10 +25,18 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, var/cache_b = LIGHTING_SOFT_THRESHOLD var/cache_mx = 0 -/datum/lighting_corner/New(var/turf/new_turf, var/diagonal) +// Diagonal is our direction FROM them, not to. +/datum/lighting_corner/New(turf/new_turf, diagonal) . = ..() - masters = list() - masters[new_turf] = turn(diagonal, 180) + +#define SET_DIAGONAL(turf, diagonal) \ + switch(diagonal){ \ + if(SOUTHWEST) { northeast = turf; turf.lc_bottomleft = src; } \ + if(SOUTHEAST) { northwest = turf; turf.lc_bottomright = src; } \ + if(NORTHEAST) { southwest = turf; turf.lc_topright = src; } \ + if(NORTHWEST) { southeast = turf; turf.lc_topleft = src; } \ + } + SET_DIAGONAL(new_turf, diagonal) z = new_turf.z var/vertical = diagonal & ~(diagonal - 1) // The horizontal directions (4 and 8) are bigger than the vertical ones (1 and 2), so we can reliably say the lsb is the horizontal direction. @@ -37,52 +45,28 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, x = new_turf.x + (horizontal == EAST ? 0.5 : -0.5) y = new_turf.y + (vertical == NORTH ? 0.5 : -0.5) - // My initial plan was to make this loop through a list of all the dirs (horizontal, vertical, diagonal). - // Issue being that the only way I could think of doing it was very messy, slow and honestly overengineered. - // So we'll have this hardcode instead. var/turf/T - var/i - - // Diagonal one is easy. + // Build diagonal one T = get_step(new_turf, diagonal) - if (T) // In case we're on the map's border. - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = diagonal - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180)) - T.corners[i] = src - - // Now the horizontal one. + if(T) + SET_DIAGONAL(T, turn(diagonal, 180)) + // Build horizontal T = get_step(new_turf, horizontal) - if (T) // Ditto. - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates. - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180)) - T.corners[i] = src - - // And finally the vertical one. + if(T) + SET_DIAGONAL(T, turn(((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH), 180)) + // Build vertical T = get_step(new_turf, vertical) - if (T) - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates. - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180)) - T.corners[i] = src + if(T) + SET_DIAGONAL(T, turn(((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH), 180)) update_active() +#undef SET_DIAGONAL + /datum/lighting_corner/proc/update_active() active = FALSE - var/turf/T - var/thing - for (thing in masters) - T = thing - if (T.lighting_object) - active = TRUE + if(northeast?.lighting_object || northwest?.lighting_object || southeast?.lighting_object || southwest?.lighting_object) + active = TRUE // God that was a mess, now to do the rest of the corner code! Hooray! /datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b) @@ -122,13 +106,12 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, #endif cache_mx = round(mx, LIGHTING_ROUND_VALUE) - for (var/TT in masters) - var/turf/T = TT - if (T.lighting_object) - if (!T.lighting_object.needs_update) - T.lighting_object.needs_update = TRUE - GLOB.lighting_update_objects += T.lighting_object - + #define QUEUE(turf) if(turf?.lighting_object && !turf.lighting_object.needs_update) { turf.lighting_object.needs_update = TRUE; GLOB.lighting_update_objects += turf.lighting_object } + QUEUE(northeast) + QUEUE(northwest) + QUEUE(southeast) + QUEUE(southwest) + #undef QUEUE /datum/lighting_corner/dummy/New() return diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm index 9ceb341f91..ffa2d86e15 100644 --- a/code/modules/lighting/lighting_object.dm +++ b/code/modules/lighting/lighting_object.dm @@ -55,7 +55,7 @@ if (loc) var/turf/oldturf = get_turf(myturf) var/turf/newturf = get_turf(loc) - warning("A lighting object realised it's loc had changed in update() ([myturf]\[[myturf ? myturf.type : "null"]]([COORD(oldturf)]) -> [loc]\[[ loc ? loc.type : "null"]]([COORD(newturf)]))!") + stack_trace("A lighting object realised it's loc had changed in update() ([myturf]\[[myturf ? myturf.type : "null"]]([COORD(oldturf)]) -> [loc]\[[ loc ? loc.type : "null"]]([COORD(newturf)]))!") qdel(src, TRUE) return @@ -71,16 +71,10 @@ // See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are. var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new - var/list/corners = myturf.corners - var/datum/lighting_corner/cr = dummy_lighting_corner - var/datum/lighting_corner/cg = dummy_lighting_corner - var/datum/lighting_corner/cb = dummy_lighting_corner - var/datum/lighting_corner/ca = dummy_lighting_corner - if (corners) //done this way for speed - cr = corners[3] || dummy_lighting_corner - cg = corners[2] || dummy_lighting_corner - cb = corners[4] || dummy_lighting_corner - ca = corners[1] || dummy_lighting_corner + var/datum/lighting_corner/cr = myturf.lc_bottomleft || dummy_lighting_corner + var/datum/lighting_corner/cg = myturf.lc_bottomright || dummy_lighting_corner + var/datum/lighting_corner/cb = myturf.lc_topleft || dummy_lighting_corner + var/datum/lighting_corner/ca = myturf.lc_topright || dummy_lighting_corner var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx) diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 6e48d0097c..d97967dff9 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -237,18 +237,25 @@ return //nothing's changed var/list/datum/lighting_corner/corners = list() + var/datum/lighting_corner/C var/list/turf/turfs = list() var/thing - var/datum/lighting_corner/C var/turf/T if (source_turf) var/oldlum = source_turf.luminosity source_turf.luminosity = CEILING(light_range, 1) for(T in view(CEILING(light_range, 1), source_turf)) - for (thing in T.get_corners(source_turf)) - C = thing - corners[C] = 0 turfs += T + if(!IS_DYNAMIC_LIGHTING(T) && !T.light_sources) + continue + if(!T.lighting_corners_initialised) + T.generate_missing_corners() + if(T.has_opaque_atom) + continue + corners[T.lc_topright] = 0 + corners[T.lc_bottomright] = 0 + corners[T.lc_bottomleft] = 0 + corners[T.lc_topleft] = 0 source_turf.luminosity = oldlum LAZYINITLIST(affecting_turfs) diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index fdd581a292..fc9cd0336d 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -6,9 +6,15 @@ var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf. var/tmp/atom/movable/lighting_object/lighting_object // Our lighting object. - var/tmp/list/datum/lighting_corner/corners + var/tmp/datum/lighting_corner/lc_topleft + var/tmp/datum/lighting_corner/lc_topright + var/tmp/datum/lighting_corner/lc_bottomleft + var/tmp/datum/lighting_corner/lc_bottomright var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile. +// counterclockwisse 0 to 360 +#define PROC_ON_CORNERS(operation) lc_topright?.##operation;lc_bottomright?.##operation;lc_bottomleft?.##operation;lc_topleft?.##operation + // Causes any affecting light sources to be queued for a visibility update, for example a door got opened. /turf/proc/reconsider_lights() var/datum/light_source/L @@ -21,13 +27,7 @@ if (lighting_object) qdel(lighting_object, TRUE) - var/datum/lighting_corner/C - var/thing - for (thing in corners) - if(!thing) - continue - C = thing - C.update_active() + PROC_ON_CORNERS(update_active()) // Builds a lighting object for us, but only if our area is dynamic. /turf/proc/lighting_build_overlay() @@ -43,32 +43,31 @@ new/atom/movable/lighting_object(src) - var/thing - var/datum/lighting_corner/C var/datum/light_source/S - for (thing in corners) - if(!thing) - continue - C = thing - if (!C.active) // We would activate the corner, calculate the lighting for it. - for (thing in C.affecting) - S = thing - S.recalc_corner(C) - C.active = TRUE + var/i +#define OPERATE(corner) \ + if(corner && !corner.active) { \ + for(i in corner.affecting) { \ + S = i ; \ + S.recalc_corner(corner) \ + } \ + corner.active = TRUE \ + } + OPERATE(lc_topright) + OPERATE(lc_bottomright) + OPERATE(lc_bottomleft) + OPERATE(lc_topleft) +#undef OPERATE // Used to get a scaled lumcount. /turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1) - if (!lighting_object) + if(!lighting_object) return 1 - var/totallums = 0 - var/thing - var/datum/lighting_corner/L - for (thing in corners) - if(!thing) - continue - L = thing - totallums += L.lum_r + L.lum_b + L.lum_g + var/totallums = (lc_topright? (lc_topright.lum_r + lc_topright.lum_g + lc_topright.lum_b) : 0) \ + + (lc_bottomright? (lc_bottomright.lum_r + lc_bottomright.lum_g + lc_bottomright.lum_b) : 0) \ + + (lc_bottomleft? (lc_bottomleft.lum_r + lc_bottomleft.lum_g + lc_bottomleft.lum_b) : 0) \ + + (lc_topleft? (lc_topleft.lum_r + lc_topleft.lum_g + lc_topleft.lum_b) : 0) totallums /= 12 // 4 corners, each with 3 channels, get the average. @@ -110,27 +109,18 @@ else lighting_clear_overlay() -/turf/proc/get_corners() - if (!IS_DYNAMIC_LIGHTING(src) && !light_sources) - return null - if (!lighting_corners_initialised) - generate_missing_corners() - if (has_opaque_atom) - return null // Since this proc gets used in a for loop, null won't be looped though. - - return corners - /turf/proc/generate_missing_corners() if (!IS_DYNAMIC_LIGHTING(src) && !light_sources) return lighting_corners_initialised = TRUE - if (!corners) - corners = list(null, null, null, null) - - for (var/i = 1 to 4) - if (corners[i]) // Already have a corner on this direction. - continue - - corners[i] = new/datum/lighting_corner(src, GLOB.LIGHTING_CORNER_DIAGONAL[i]) - + // counterclockwise from 0 to 360. + if(!lc_topright) + new /datum/lighting_corner(src, NORTHEAST) + if(!lc_bottomright) + new /datum/lighting_corner(src, SOUTHEAST) + if(!lc_bottomleft) + new /datum/lighting_corner(src, SOUTHWEST) + if(!lc_topleft) + new /datum/lighting_corner(src, NORTHWEST) +#undef PROC_ON_CORNERS diff --git a/code/modules/mapping/mapping_helpers/network_builder/_network_builder.dm b/code/modules/mapping/mapping_helpers/network_builder/_network_builder.dm index 78a835cffa..69a75148dd 100644 --- a/code/modules/mapping/mapping_helpers/network_builder/_network_builder.dm +++ b/code/modules/mapping/mapping_helpers/network_builder/_network_builder.dm @@ -12,7 +12,6 @@ /obj/effect/mapping_helpers/network_builder/Initialize(mapload) . = ..() - to_chat(world, "DEBUG: Initializing [COORD(src)]") var/conflict = check_duplicates() if(conflict) stack_trace("WARNING: [type] network building helper found check_duplicates() conflict [conflict] in its location.!") @@ -27,7 +26,6 @@ /// How this works: On LateInitialize, detect all directions that this should be applicable to, and do what it needs to do, and then inform all network builders in said directions that it's been around since it won't be around afterwards. /obj/effect/mapping_helpers/network_builder/LateInitialize() - to_chat(world, "DEBUG: LateInitializing [COORD(src)]") scan_directions() build_network() if(!custom_spawned) diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 1fd1b31b69..dcd8e1a4ae 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -417,7 +417,7 @@ marker.icon_state = "chronobolt" marker.damage = bonus_value marker.nodamage = FALSE - marker.speed = 2 + marker.pixels_per_second = TILES_TO_PIXELS(5) deadly_shot = FALSE /obj/item/crusher_trophy/blaster_tubes/on_mark_detonation(mob/living/target, mob/living/user) diff --git a/code/modules/mining/equipment/lazarus_injector.dm b/code/modules/mining/equipment/lazarus_injector.dm index f8b155cb9f..db826fdb49 100644 --- a/code/modules/mining/equipment/lazarus_injector.dm +++ b/code/modules/mining/equipment/lazarus_injector.dm @@ -33,7 +33,7 @@ if(malfunctioning) H.faction |= list("lazarus", "[REF(user)]") H.robust_searching = 1 - H.friends += user + H.friends[user]++ H.attack_same = 1 log_game("[key_name(user)] has revived hostile mob [key_name(target)] with a malfunctioning lazarus injector") else diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index ce76ad04fc..50a3dec9dd 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -168,3 +168,17 @@ throwforce = 7 custom_materials = list(/datum/material/iron=50) w_class = WEIGHT_CLASS_SMALL + +/obj/item/shovel/serrated + name = "serrated bone shovel" + desc = "A wicked tool that cleaves through dirt just as easily as it does flesh. The design was styled after ancient lavaland tribal designs." + icon_state = "shovel_bone" + item_state = "shovel_bone" + lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi' + force = 15 + throwforce = 12 + w_class = WEIGHT_CLASS_NORMAL + toolspeed = 0.7 + attack_verb = list("slashed", "impaled", "stabbed", "sliced") + sharpness = IS_SHARP diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index bbab74689c..ab0356aa66 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -270,6 +270,7 @@ desc = "A sign of relief for weary miners, and a warning for would-be competitors to Nanotrasen's mining claims." icon = 'icons/turf/walls/survival_pod_walls.dmi' icon_state = "ntpod" + buildable_sign = FALSE /obj/structure/sign/mining/survival name = "shelter sign" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm index 6126b6c04b..b39f48f858 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm @@ -1,7 +1,7 @@ /datum/sprite_accessory/horns icon = 'icons/mob/mutant_bodyparts.dmi' color_src = HORNCOLOR - relevant_layers = list(BODY_ADJ_LAYER) + relevant_layers = list(HORNS_LAYER) /datum/sprite_accessory/horns/none name = "None" diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 838de24b60..5364486b04 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -287,12 +287,12 @@ Works together with spawning an observer, noted above. var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) penalty = CANT_REENTER_ROUND - if(!(ckey in GLOB.client_ghost_timeouts)) - GLOB.client_ghost_timeouts += ckey - GLOB.client_ghost_timeouts[ckey] = 0 - else if(GLOB.client_ghost_timeouts[ckey] == CANT_REENTER_ROUND) + if(!(ghost.ckey in GLOB.client_ghost_timeouts)) + GLOB.client_ghost_timeouts += ghost.ckey + GLOB.client_ghost_timeouts[ghost.ckey] = 0 + else if(GLOB.client_ghost_timeouts[ghost.ckey] == CANT_REENTER_ROUND) return - GLOB.client_ghost_timeouts[ckey] = max(GLOB.client_ghost_timeouts[ckey],penalty) + GLOB.client_ghost_timeouts[ghost.ckey] = max(GLOB.client_ghost_timeouts[ghost.ckey],penalty) // needs to be done AFTER the ckey transfer, too return ghost diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 6d3bf648f6..687442c1f8 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -137,11 +137,11 @@ if(cached_Bdamage <= HEALTH_THRESHOLD_DEAD) //Fixing dead brains yeilds a trauma if((cached_Bdamage <= HEALTH_THRESHOLD_DEAD) && (brainmob.health > HEALTH_THRESHOLD_DEAD)) if(prob(80)) - gain_trauma_type(BRAIN_TRAUMA_MILD) + gain_trauma_type(BRAIN_TRAUMA_MILD, natural_gain = TRUE) else if(prob(50)) - gain_trauma_type(BRAIN_TRAUMA_SEVERE) + gain_trauma_type(BRAIN_TRAUMA_SEVERE, natural_gain = TRUE) else - gain_trauma_type(BRAIN_TRAUMA_SPECIAL) + gain_trauma_type(BRAIN_TRAUMA_SPECIAL, natural_gain = TRUE) return if((organ_flags & ORGAN_FAILING) && O.is_drainable() && O.reagents.has_reagent(/datum/reagent/medicine/mannitol)) //attempt to heal the brain @@ -253,16 +253,16 @@ damage_delta = damage - prev_damage if(damage > BRAIN_DAMAGE_MILD) if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_MILD)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% //learn how to do your bloody math properly goddamnit - gain_trauma_type(BRAIN_TRAUMA_MILD) + gain_trauma_type(BRAIN_TRAUMA_MILD, natural_gain = TRUE) if(prev_damage <= BRAIN_DAMAGE_MILD && owner) var/datum/skill_modifier/S ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/brain_damage, null, owner, S) if(damage > BRAIN_DAMAGE_SEVERE) if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_SEVERE)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% if(prob(20)) - gain_trauma_type(BRAIN_TRAUMA_SPECIAL) + gain_trauma_type(BRAIN_TRAUMA_SPECIAL, natural_gain = TRUE) else - gain_trauma_type(BRAIN_TRAUMA_SEVERE) + gain_trauma_type(BRAIN_TRAUMA_SEVERE, natural_gain = TRUE) if(prev_damage <= BRAIN_DAMAGE_SEVERE && owner) var/datum/skill_modifier/S ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/heavy_brain_damage, null, owner, S) @@ -308,7 +308,7 @@ if(istype(BT, brain_trauma_type) && (BT.resilience <= resilience)) . += BT -/obj/item/organ/brain/proc/can_gain_trauma(datum/brain_trauma/trauma, resilience) +/obj/item/organ/brain/proc/can_gain_trauma(datum/brain_trauma/trauma, resilience, natural_gain = FALSE) if(!ispath(trauma)) trauma = trauma.type if(!initial(trauma.can_gain)) @@ -341,7 +341,7 @@ if(TRAUMA_RESILIENCE_ABSOLUTE) max_traumas = TRAUMA_LIMIT_ABSOLUTE - if(resilience_tier_count >= max_traumas) + if(natural_gain && resilience_tier_count >= max_traumas) return FALSE return TRUE @@ -381,11 +381,11 @@ 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) +/obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience, natural_gain = FALSE) var/list/datum/brain_trauma/possible_traumas = list() for(var/T in subtypesof(brain_trauma_type)) var/datum/brain_trauma/BT = T - if(can_gain_trauma(BT, resilience) && initial(BT.random_gain)) + if(can_gain_trauma(BT, resilience, natural_gain) && initial(BT.random_gain)) possible_traumas += BT if(!LAZYLEN(possible_traumas)) diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 00d929a1e0..a4da38c4da 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -24,12 +24,12 @@ if(!eye_blind) blind_eyes(1) update_mobility() - else - if(stat == UNCONSCIOUS) - stat = CONSCIOUS - if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT)) - set_resting(FALSE, TRUE) + else if(stat == UNCONSCIOUS) + stat = CONSCIOUS + if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT)) + set_resting(FALSE, TRUE) + if(eye_blind <= 1) adjust_blindness(-1) - update_mobility() + update_mobility() update_damage_hud() update_health_hud() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 39179346f1..37b364ea6f 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -443,14 +443,14 @@ //dropItemToGround(I) CIT CHANGE - makes it so the item doesn't drop if the modifier rolls above 100 - var/modifier = 0 + var/modifier = 50 if(HAS_TRAIT(src, TRAIT_CLUMSY)) modifier -= 40 //Clumsy people are more likely to hit themselves -Honk! //CIT CHANGES START HERE - else if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) - modifier += 50 + else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) + modifier -= 50 if(modifier < 100) dropItemToGround(I) @@ -828,16 +828,17 @@ return if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT))) stat = UNCONSCIOUS - disable_intentional_combat_mode(FALSE, FALSE) + SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE) if(!eye_blind) blind_eyes(1) else if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT)) stat = SOFT_CRIT - disable_intentional_combat_mode(FALSE, FALSE) + SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE) else stat = CONSCIOUS - adjust_blindness(-1) + if(eye_blind <= 1) + adjust_blindness(-1) update_mobility() update_damage_hud() update_health_hud() @@ -1123,10 +1124,6 @@ if(mood.sanity < SANITY_UNSTABLE) return TRUE -/mob/living/carbon/transfer_ckey(mob/new_mob, send_signal = TRUE) - disable_intentional_combat_mode(TRUE, FALSE) - return ..() - /mob/living/carbon/can_see_reagents() . = ..() if(.) //No need to run through all of this if it's already true. diff --git a/code/modules/mob/living/carbon/carbon_combat.dm b/code/modules/mob/living/carbon/carbon_combat.dm deleted file mode 100644 index f43d850401..0000000000 --- a/code/modules/mob/living/carbon/carbon_combat.dm +++ /dev/null @@ -1,6 +0,0 @@ -/mob/living/carbon/enable_intentional_combat_mode() - . = ..() - if(.) - if(voremode) - toggle_vore_mode() - diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 94589b3a4a..6303cf4c5c 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -78,12 +78,6 @@ /mob/living/carbon/attacked_by(obj/item/I, mob/living/user) var/totitemdamage = pre_attacked_by(I, user) - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - totitemdamage *= 0.5 - if(!CHECK_MOBILITY(user, MOBILITY_STAND)) - totitemdamage *= 0.5 - if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - totitemdamage *= 1.5 var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected) if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, null) & BLOCK_SUCCESS)) return FALSE diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 4cf82bb0b4..c3e849efa6 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -8,8 +8,6 @@ if(!gibbed) emote("deathgasp") - disable_intentional_combat_mode(TRUE, FALSE) - . = ..() for(var/T in get_traumas()) @@ -62,7 +60,3 @@ var/obj/item/bodypart/BP = X BP.drop_limb() BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5) - -/mob/living/carbon/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE) - disable_intentional_combat_mode(TRUE, FALSE) - return ..() diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 1ee3369701..8dbfba47b1 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -90,7 +90,7 @@ if(digitalcamo) . += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly unsimian manner." - if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) + if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) . += "[t_He] [t_is] visibly tense[CHECK_MOBILITY(src, MOBILITY_STAND) ? "." : ", and [t_is] standing in combative stance."]" var/trait_exam = common_trait_examine() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 007bca3518..de703b8ad4 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -39,6 +39,7 @@ . = ..() if(!CONFIG_GET(flag/disable_human_mood)) AddComponent(/datum/component/mood) + AddComponent(/datum/component/combat_mode) AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text") AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!") AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 733f792109..63ca3f372e 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -16,8 +16,6 @@ if(!SSI) SSI = CONFIG_GET_ENTRY(number/movedelay/sprint_speed_increase) . -= SSI.config_entry_value - if(wrongdirmovedelay) - . += 1 if (m_intent == MOVE_INTENT_WALK && HAS_TRAIT(src, TRAIT_SPEEDY_STEP)) . -= 1.5 diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 5018b04cc4..5f07f0829c 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -630,6 +630,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.remove_overlay(BODY_ADJ_LAYER) H.remove_overlay(BODY_ADJ_UPPER_LAYER) H.remove_overlay(BODY_FRONT_LAYER) + H.remove_overlay(HORNS_LAYER) if(!mutant_bodyparts) return @@ -841,8 +842,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(!S.mutant_part_string) dna_feature_as_text_string[S] = bodypart - var/static/list/layer_text = list("[BODY_BEHIND_LAYER]" = "BEHIND", "[BODY_ADJ_LAYER]" = "ADJ", \ - "[BODY_ADJ_UPPER_LAYER]" = "ADJUP", "[BODY_FRONT_LAYER]" = "FRONT") + var/static/list/layer_text = list( + "[BODY_BEHIND_LAYER]" = "BEHIND", + "[BODY_ADJ_LAYER]" = "ADJ", + "[BODY_ADJ_UPPER_LAYER]" = "ADJUP", + "[BODY_FRONT_LAYER]" = "FRONT", + "[HORNS_LAYER]" = "HORNS", + ) var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m" var/list/colorlist = list() @@ -1022,6 +1028,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.apply_overlay(BODY_ADJ_LAYER) H.apply_overlay(BODY_ADJ_UPPER_LAYER) H.apply_overlay(BODY_FRONT_LAYER) + H.apply_overlay(HORNS_LAYER) /* @@ -1475,11 +1482,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/punchedbrute = target.getBruteLoss() //CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage - if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) damage *= 1.5 if(!CHECK_MOBILITY(user, MOBILITY_STAND)) damage *= 0.5 - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) damage *= 0.25 //END OF CITADEL CHANGES @@ -1627,11 +1634,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) log_combat(user, target, "disarmed out of grab from") return var/randn = rand(1, 100) - if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) // CITADEL CHANGE + if(SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) // CITADEL CHANGE randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed if(!CHECK_MOBILITY(user, MOBILITY_STAND)) //CITADEL CHANGE randn += 100 //CITADEL CHANGE - No kosher disarming if you're resting - if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //CITADEL CHANGE + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) //CITADEL CHANGE randn += 25 //CITADEL CHANGE - Makes it harder to disarm outside of combat mode if(user.pulling == target) randn -= 20 //If you have the time to get someone in a grab, you should have a greater chance at snatching the thing in their hand. Will be made completely obsolete by the grab rework but i've got a poor track record for releasing big projects on time so w/e i guess @@ -1829,7 +1836,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(IS_STAMCRIT(user)) to_chat(user, "You're too exhausted for that.") return - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) to_chat(user, "You need combat mode to be active to that!") return if(user.IsKnockdown() || user.IsParalyzed() || user.IsStun()) diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm index dfeff24141..bc5f198b4d 100644 --- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm +++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm @@ -6,8 +6,8 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // name = "Dwarf" id = "dwarf" //Also called Homo sapiens pumilionis default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NO_UNDERWEAR,TRAIT_DWARF) - inherent_traits = list() + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS) + inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB) limbs_id = "human" use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM say_mod = "bellows" //high energy, EXTRA BIOLOGICAL FUEL @@ -87,9 +87,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // var/heal_rate = 0.5 //The rate they heal damages over 400 alcohol stored. Default is 0.5 so we times 3 since 3 seconds. var/alcohol_rate = 0.25 //The rate the alcohol ticks down per each iteration of dwarf_eth_ticker completing. //These count in on_life ticks which should be 2 seconds per every increment of 1 in a perfect world. - var/dwarf_filth_ticker = 0 //Currently set =< 4, that means this will fire the proc around every 4-8 seconds. var/dwarf_eth_ticker = 0 //Currently set =< 1, that means this will fire the proc around every 2 seconds - var/last_filth_spam var/last_alcohol_spam /obj/item/organ/dwarfgland/prepare_eat() @@ -100,64 +98,10 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // /obj/item/organ/dwarfgland/on_life() //Primary loop to hook into to start delayed loops for other loops.. . = ..() if(owner && owner.stat != DEAD) - dwarf_cycle_ticker() - -//Handles the delayed tick cycle by just adding on increments per each on_life() tick -/obj/item/organ/dwarfgland/proc/dwarf_cycle_ticker() - dwarf_eth_ticker++ - dwarf_filth_ticker++ - - if(dwarf_filth_ticker >= 4) //Should be around 4-8 seconds since a tick is around 2 seconds. - dwarf_filth_cycle() //On_life will adjust regarding other factors, so we are along for the ride. - dwarf_filth_ticker = 0 //We set the ticker back to 0 to go again. - if(dwarf_eth_ticker >= 1) //Alcohol reagent check should be around 2 seconds, since a tick is around 2 seconds. - dwarf_eth_cycle() - dwarf_eth_ticker = 0 - -//If this still friggin uses too much CPU, I'll make a for view subsystem If I have to. -/obj/item/organ/dwarfgland/proc/dwarf_filth_cycle() - if(!owner?.client || !owner?.mind) - return - //Filth Reactions - Since miasma now exists - var/filth_counter = 0 //Holder for the filth check cycle, basically contains how much filth dwarf sees numerically. - for(var/fuck in owner.fov_view(7)) //hello byond for view loop. - if(istype(fuck, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = fuck - if(H.stat == DEAD || (HAS_TRAIT(H, TRAIT_FAKEDEATH))) - filth_counter += 10 - if(istype(fuck, /obj/effect/decal/cleanable/blood)) - if(istype(fuck, /obj/effect/decal/cleanable/blood/gibs)) - filth_counter += 1 - else - filth_counter += 0.1 - if(istype(fuck,/obj/effect/decal/cleanable/vomit)) //They are disgusted by their own vomit too. - filth_counter += 10 //Dwarves could technically chainstun each other in a vomit tantrum spiral. - switch(filth_counter) - if(11 to 25) - if(last_filth_spam + 40 SECONDS < world.time) - to_chat(owner, "Someone should really clean up in here!") - last_filth_spam = world.time - if(26 to 50) - if(prob(6)) //And then the probability they vomit along with it. - to_chat(owner, "The stench makes you queasy.") - owner.vomit(10) //I think vomit should stay over a disgust adjustment. - if(51 to 75) - if(prob(9)) - to_chat(owner, "By Armok! You won't be able to keep alcohol down at all!") - owner.vomit(20) //Its more funny - if(76 to 100) - if(prob(11)) - to_chat(owner, "You can't live in such FILTH!") - owner.adjustToxLoss(10) //Now they start dying. - owner.vomit(20) - if(101 to INFINITY) //Now they will really start dying - if(last_filth_spam + 12 SECONDS < world.time) - to_chat(owner, " THERES TOO MUCH FILTH, OH GODS THE FILTH!") - last_filth_spam = world.time - if(prob(40)) - owner.adjustToxLoss(15) - owner.vomit(30) - CHECK_TICK //Check_tick right here, its motherfuckin magic. (To me at least) + dwarf_eth_ticker++ + if(dwarf_eth_ticker >= 1) //Alcohol reagent check should be around 2 seconds, since a tick is around 2 seconds. + dwarf_eth_cycle() + dwarf_eth_ticker = 0 //Handles the dwarf alcohol cycle tied to on_life, it ticks in dwarf_cycle_ticker. /obj/item/organ/dwarfgland/proc/dwarf_eth_cycle() diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index e85769ca12..4e5b033688 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -523,7 +523,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put //this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc.. /mob/living/carbon/handle_status_effects() ..() - if(getStaminaLoss() && !(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active + if(getStaminaLoss() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active adjustStaminaLoss(!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? -7.5 : -6) : -3)//CIT CHANGE - decreases adjuststaminaloss to stop stamina damage from being such a joke if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 502ebcbe5d..c1038fbb41 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -322,7 +322,7 @@ set_pull_offsets(M, state) /mob/living/proc/set_pull_offsets(mob/living/M, grab_state = GRAB_PASSIVE) - if(M.buckled || M.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) + if(M.buckled || SEND_SIGNAL(M, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) return //don't make them change direction or offset them if they're buckled into something or in combat mode. var/offset = 0 switch(grab_state) diff --git a/code/modules/mob/living/living_combat.dm b/code/modules/mob/living/living_combat.dm deleted file mode 100644 index dbdcd1ea5b..0000000000 --- a/code/modules/mob/living/living_combat.dm +++ /dev/null @@ -1,93 +0,0 @@ -/mob/living/ComponentInitialize() - . = ..() - RegisterSignal(src, SIGNAL_TRAIT(TRAIT_COMBAT_MODE_LOCKED), .proc/update_combat_lock) - -/mob/living/proc/update_combat_lock() - var/locked = HAS_TRAIT(src, TRAIT_COMBAT_MODE_LOCKED) - var/desired = (combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) - var/actual = (combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) - if(actual) - if(locked) - disable_combat_mode(FALSE, TRUE, FALSE, FALSE) - else if(!desired) - disable_combat_mode(TRUE, TRUE, FALSE, FALSE) - else - if(desired && !locked) - enable_combat_mode(FALSE, TRUE, FALSE, FALSE) - update_combat_mode_icon() - -/mob/living/proc/disable_combat_mode(silent = TRUE, was_forced = FALSE, visible = FALSE, update_icon = TRUE) - if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) || (combat_flags & COMBAT_FLAG_COMBAT_FORCED)) - return - DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_COMBAT_ACTIVE) - SEND_SIGNAL(src, COMSIG_LIVING_COMBAT_DISABLED, was_forced) - if(visible) - visible_message("[src] goes limp.", "Your muscles are forcibly relaxed!") - else if(!silent) - to_chat(src, was_forced? "Your muscles are forcibly relaxed!" : "You relax your muscles.") - if(update_icon) - update_combat_mode_icon() - -/mob/living/proc/enable_combat_mode(silent = TRUE, was_forced = FALSE, visible = FALSE, update_icon = TRUE) - if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) - return - ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_COMBAT_ACTIVE) - SEND_SIGNAL(src, COMSIG_LIVING_COMBAT_ENABLED, was_forced) - if(visible) - visible_message("[src] drops into a combative stance!", "You drop into a combative stance!") - else if(!silent) - to_chat(src, was_forced? "Your muscles reflexively tighten!" : "You tighten your muscles.") - if(update_icon) - update_combat_mode_icon() - -/// Updates the combat mode HUD icon. -/mob/living/proc/update_combat_mode_icon() - var/obj/screen/combattoggle/T = locate() in hud_used?.static_inventory - T?.update_icon() - -/// Enables intentionally being in combat mode. Please try not to use this proc for feedback whenever possible. -/mob/living/proc/enable_intentional_combat_mode(silent = TRUE, visible = FALSE) - if((combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) && (combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - return - ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_COMBAT_TOGGLED) - if(!HAS_TRAIT(src, TRAIT_COMBAT_MODE_LOCKED) && !(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - enable_combat_mode(silent, FALSE, visible, FALSE) - update_combat_mode_icon() - client?.show_popup_menus = FALSE - return TRUE - -/// Disables intentionally being in combat mode. Please try not to use this proc for feedback whenever possible. -/mob/living/proc/disable_intentional_combat_mode(silent = TRUE, visible = FALSE) - if(!(combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) && !(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - return - if(combat_flags & COMBAT_FLAG_COMBAT_FORCED) - return - DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_COMBAT_TOGGLED) - if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) - disable_combat_mode(silent, FALSE, visible, FALSE) - update_combat_mode_icon() - client?.show_popup_menus = TRUE - return TRUE - -/// Toggles whether the user is intentionally in combat mode. THIS should be the proc you generally use! Has built in visual/to other player feedback, as well as an audible cue to ourselves. -/mob/living/proc/user_toggle_intentional_combat_mode(visible = TRUE) - var/old = (combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) - if(old) - if(combat_flags & COMBAT_FLAG_COMBAT_FORCED) - to_chat(src, "You are unable to relax your muscles.") - return - disable_intentional_combat_mode() - playsound_local(src, 'sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the above! - else if(CAN_TOGGLE_COMBAT_MODE(src)) - enable_intentional_combat_mode() - var/current = (combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) //because we could be locked - if(current != old) //only sound effect if you succeeded. Could have the feedback system be better but shrug, someone else can do it. - if(current) - playsound_local(src, 'sound/misc/ui_toggle.ogg', 50, FALSE, pressure_affected = FALSE) //Sound from interbay! - if(visible) - if(world.time >= combatmessagecooldown) - combatmessagecooldown = world.time + 10 SECONDS - if(a_intent != INTENT_HELP) - visible_message("[src] [resting ? "tenses up" : (prob(95)? "drops into a combative stance" : (prob(95)? "poses aggressively" : "asserts dominance with their pose"))].") - else - visible_message("[src] [pick("looks","seems","goes")] [pick("alert","attentive","vigilant")].") diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index f8abf94083..282dab79a8 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -122,7 +122,7 @@ //// CITADEL STATION COMBAT //// /// See __DEFINES/combat.dm - var/combat_flags = COMBAT_FLAGS_STAMSYSTEM_EXEMPT + var/combat_flags = COMBAT_FLAGS_SPRINT_EXEMPT /// Next world.time when we will show a visible message on entering combat mode voluntarily again. var/combatmessagecooldown = 0 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 98a5f0f234..633135b3d2 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -14,7 +14,7 @@ spark_system.attach(src) wires = new /datum/wires/robot(src) - AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) robot_modules_background = new() robot_modules_background.icon_state = "block" diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm index 860d531608..b3be01e1b0 100644 --- a/code/modules/mob/living/silicon/robot/robot_defines.dm +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -9,6 +9,8 @@ maxHealth = 100 health = 100 + combat_flags = COMBAT_FLAGS_DEFAULT + var/custom_name = "" var/braintype = "Cyborg" var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of.. diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index a4aeeb2ffc..0d0f7f9c97 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -15,8 +15,6 @@ speech_span = SPAN_ROBOT flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1 vore_flags = NO_VORE - /// Enable sprint system but not stamina - combat_flags = COMBAT_FLAGS_STAMEXEMPT_YESSPRINT var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS var/last_lawchange_announce = 0 diff --git a/code/modules/mob/living/simple_animal/astral.dm b/code/modules/mob/living/simple_animal/astral.dm index 48203b24b9..4fb9e9273e 100644 --- a/code/modules/mob/living/simple_animal/astral.dm +++ b/code/modules/mob/living/simple_animal/astral.dm @@ -52,14 +52,14 @@ to_chat(src, "The intensity of the astrogen in your body is too much allow you to return to yourself yet!") return to_chat(src, "You astrally possess [H]!") - log_game("FERMICHEM: [src] has astrally possessed [A]!") + log_reagent("FERMICHEM: [src] has astrally possessed [A]!") src.mind.transfer_to(H) qdel(src) var/message = html_decode(stripped_input(src, "Enter a message to send to [A]", MAX_MESSAGE_LEN)) if(!message) return to_chat(A, "[src] projects into your mind, \"[message]\"") - log_game("FERMICHEM: [src] has astrally transmitted [message] into [A]") + log_reagent("FERMICHEM: [src] has astrally transmitted [message] into [A]") //Delete the mob if there's no mind! Pay that mob no mind. /mob/living/simple_animal/astral/Life() diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 59fa94a1fa..e9bc3c549d 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -500,3 +500,33 @@ user.visible_message("[user] milks [src] using \the [O].", "You milk [src] using \the [O].") else to_chat(user, "The udder is dry. Wait a bit longer...") + +/mob/living/simple_animal/deer + name = "doe" + desc = "A gentle, peaceful forest animal. How did this get into space?" + icon_state = "deer-doe" + icon_living = "deer-doe" + icon_dead = "deer-doe-dead" + gender = FEMALE + mob_biotypes = MOB_ORGANIC|MOB_BEAST + speak = list("Weeeeeeee?","Weeee","WEOOOOOOOOOO") + speak_emote = list("grunts","grunts lowly") + emote_hear = list("brays.") + emote_see = list("shakes its head.") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3) + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently nudges" + response_disarm_simple = "gently nudge" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + attack_verb_continuous = "bucks" + attack_verb_simple = "buck" + attack_sound = 'sound/weapons/punch1.ogg' + health = 75 + maxHealth = 75 + blood_volume = BLOOD_VOLUME_NORMAL + footstep_type = FOOTSTEP_MOB_SHOE \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm index 83fe42a7a4..df416047e2 100644 --- a/code/modules/mob/living/simple_animal/friendly/sloth.dm +++ b/code/modules/mob/living/simple_animal/friendly/sloth.dm @@ -27,7 +27,7 @@ glide_size = 2 footstep_type = FOOTSTEP_MOB_CLAW -/mob/living/simple_animal/pet/fox/ComponentInitialize() +/mob/living/simple_animal/pet/sloth/ComponentInitialize() . = ..() AddElement(/datum/element/mob_holder, "sloth") //finally oranges can be held diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm index b1a4f05e8c..a2fc3aec88 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm @@ -23,29 +23,21 @@ for(var/ab in boss_abilities) boss_abilities -= ab var/datum/action/boss/AB = new ab() - AB.boss = src AB.Grant(src) boss_abilities += AB atb.assign_abilities(boss_abilities) - /mob/living/simple_animal/hostile/boss/Destroy() - qdel(atb) - atb = null - for(var/ab in boss_abilities) - var/datum/action/boss/AB = ab - AB.boss = null - AB.Remove(src) - qdel(AB) - boss_abilities.Cut() + QDEL_NULL(atb) + QDEL_LIST(boss_abilities) return ..() - //Action datum for bosses //Override Trigger() as shown below to do things /datum/action/boss check_flags = AB_CHECK_CONSCIOUS //Incase the boss is given a player + required_mobility_flags = NONE var/boss_cost = 100 //Cost of usage for the boss' AI 1-100 var/usage_probability = 100 var/mob/living/simple_animal/hostile/boss/boss @@ -53,23 +45,34 @@ var/needs_target = TRUE //Does the boss need to have a target? (Only matters for the AI) var/say_when_triggered = "" //What does the boss Say() when the ability triggers? +/datum/action/boss/Destroy() + boss = null + return ..() + +/datum/action/boss/Grant(mob/M) + . = ..() + boss = owner + +/datum/action/boss/Remove(mob/M) + . = ..() + boss = null + /datum/action/boss/Trigger() . = ..() - if(.) - if(!istype(boss, boss_type)) - return 0 - if(!boss.atb) - return 0 - if(boss.atb.points < boss_cost) - return 0 - if(!boss.client) - if(needs_target && !boss.target) - return 0 - if(boss) - if(say_when_triggered) - boss.say(say_when_triggered, forced = "boss action") - if(!boss.atb.spend(boss_cost)) - return 0 + if(!.) + return + if(!istype(boss, boss_type)) + return FALSE + if(!boss.atb) + return FALSE + if(boss.atb.points < boss_cost) + return FALSE + if(!boss.client && needs_target && !boss.target) + return FALSE + if(!boss.atb.spend(boss_cost)) + return FALSE + if(say_when_triggered) + boss.say(say_when_triggered, forced = "boss action") //Example: /* @@ -83,7 +86,8 @@ /datum/boss_active_timed_battle var/list/abilities //a list of /datum/action/boss owned by a boss mob var/point_regen_delay = 5 - var/points = 50 //1-100, start with 50 so we can use some abilities but not insta-buttfug somebody + var/max_points = 100 + var/points = 50 //start with 50 so we can use some abilities but not insta-buttfug somebody var/next_point_time = 0 var/chance_to_hold_onto_points = 50 var/highest_cost = 0 @@ -108,22 +112,22 @@ /datum/boss_active_timed_battle/proc/spend(cost) if(cost <= points) points = max(0,points-cost) - return 1 - return 0 + return TRUE + return FALSE /datum/boss_active_timed_battle/proc/refund(cost) - points = min(points+cost, 100) + points = min(points+cost, max_points) /datum/boss_active_timed_battle/process() - if(world.time >= next_point_time) + if(world.time >= next_point_time && points < max_points) next_point_time = world.time + point_regen_delay - points = min(100, ++points) //has to be out of 100 + points = min(max_points, ++points) //has to be out of 100 if(abilities) chance_to_hold_onto_points = highest_cost*0.5 - if(points != 100 && prob(chance_to_hold_onto_points)) + if(points != max_points && prob(chance_to_hold_onto_points)) return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!) if(!boss.client) abilities = shuffle(abilities) @@ -135,5 +139,5 @@ /datum/boss_active_timed_battle/Destroy() abilities = null - SSobj.processing.Remove(src) + STOP_PROCESSING(SSobj, src) return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm index aef3fb714d..4d45120a59 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm @@ -32,25 +32,47 @@ name = "Summon Minions" icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "art_summon" - usage_probability = 40 + usage_probability = 20 boss_cost = 30 boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard needs_target = FALSE say_when_triggered = "Rise, my creations! Jump off your pages and into this realm!" - var/static/summoned_minions = 0 + var/list/summoned_minions = list() + var/maximum_stickmen = 6 + var/stickmen_to_summon = 3 /datum/action/boss/wizard_summon_minions/Trigger() - if(summoned_minions <= 6 && ..()) - var/list/minions = list( - /mob/living/simple_animal/hostile/stickman, - /mob/living/simple_animal/hostile/stickman/ranged, - /mob/living/simple_animal/hostile/stickman/dog) - var/list/directions = GLOB.cardinals.Copy() - for(var/i in 1 to 3) - var/minions_chosen = pick_n_take(minions) - new minions_chosen (get_step(boss,pick_n_take(directions)), 1) - summoned_minions += 3; + . =..() + if(!.) + return + var/to_summon = stickmen_to_summon + var/current_len = length(summoned_minions) + if(current_len > maximum_stickmen - stickmen_to_summon) + for(var/a in (maximum_stickmen - stickmen_to_summon) to current_len) + var/mob/living/simple_animal/hostile/stickman/S = popleft(summoned_minions) + if(!S.client) + qdel(S) + else + S.forceMove(boss.drop_location()) + S.revive(TRUE) + summoned_minions += S + to_summon-- + var/static/list/minions = list( + /mob/living/simple_animal/hostile/stickman, + /mob/living/simple_animal/hostile/stickman/ranged, + /mob/living/simple_animal/hostile/stickman/dog) + + var/list/directions = GLOB.cardinals.Copy() + for(var/i in 1 to to_summon) + var/minions_chosen = pick(minions) + var/mob/living/simple_animal/hostile/stickman/S = new minions_chosen (get_step(boss,pick_n_take(directions)), 1) + S.faction = boss.faction + RegisterSignal(S, COMSIG_PARENT_QDELETING, .proc/remove_from_list) + summoned_minions += S + +/datum/action/boss/wizard_summon_minions/proc/remove_from_list(datum/source, forced) + summoned_minions -= source //Mimic Ability //Summons mimics of himself with magical papercraft @@ -66,28 +88,32 @@ say_when_triggered = "" /datum/action/boss/wizard_mimic/Trigger() - if(..()) - var/mob/living/target - if(!boss.client) //AI's target - target = boss.target - else //random mob - var/list/threats = boss.PossibleThreats() - if(threats.len) - target = pick(threats) - if(target) - var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss - var/directions = GLOB.cardinals.Copy() - for(var/i in 1 to 3) - var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions))) - wiz.copies += C - C.original = wiz - C.say("My craft defines me, you could even say it IS me!") - wiz.say("My craft defines me, you could even say it IS me!") - wiz.forceMove(get_step(target,pick_n_take(directions))) - wiz.minimum_distance = 1 //so he doesn't run away and ruin everything - wiz.retreat_distance = 0 + . = ..() + if(!.) + return + var/mob/living/target + if(!boss.client) //AI's target + target = boss.target + else //random mob + var/list/threats = boss.PossibleThreats() + if(threats.len) + target = pick(threats) else - boss.atb.refund(boss_cost) + to_chat(owner, "There is no potential foe of different faction around to attack") + if(target) + var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss + var/directions = GLOB.cardinals.Copy() + for(var/i in 1 to 3) + var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions))) + wiz.copies += C + C.original = wiz + C.say("My craft defines me, you could even say it IS me!") + wiz.say("My craft defines me, you could even say it IS me!") + wiz.forceMove(get_step(target,pick_n_take(directions))) + wiz.minimum_distance = 1 //so he doesn't run away and ruin everything + wiz.retreat_distance = 0 + else + boss.atb.refund(boss_cost) /mob/living/simple_animal/hostile/boss/paper_wizard/copy desc = "'Tis a ruse!" diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index cae8948fdd..e41fa7c896 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -20,6 +20,7 @@ var/casingtype //set ONLY it and NULLIFY projectiletype, if we have projectile IN CASING var/move_to_delay = 3 //delay for the automated movement. var/list/friends = list() + var/list/foes = list() var/list/emote_taunt = list() var/taunt_chance = 0 @@ -62,6 +63,8 @@ /mob/living/simple_animal/hostile/Destroy() targets_from = null + friends = null + foes = null return ..() /mob/living/simple_animal/hostile/Life() @@ -193,7 +196,7 @@ // Please do not add one-off mob AIs here, but override this function for your mob /mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target? - if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids + if(!the_target || the_target.type == /atom/movable/lighting_object || isturf(the_target)) // bail out on invalids return FALSE if(ismob(the_target)) //Target is in godmode, ignore it. @@ -208,13 +211,13 @@ if(search_objects < 2) if(isliving(the_target)) var/mob/living/L = the_target - var/faction_check = faction_check_mob(L) + var/faction_check = !foes[L] && faction_check_mob(L) if(robust_searching) if(faction_check && !attack_same) return FALSE - if(L.stat > stat_attack) + if(L.stat > stat_attack || (L.stat == UNCONSCIOUS && stat_attack == UNCONSCIOUS && HAS_TRAIT(L, TRAIT_DEATHCOMA))) return FALSE - if(L in friends) + if(friends[L] > 0 && foes[L] < 1) return FALSE else if((faction_check && !attack_same) || L.stat) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index 8c358fd625..3ef4ef9be9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -75,7 +75,7 @@ Difficulty: Medium /obj/item/projectile/kinetic/miner damage = 40 - speed = 0.9 + pixels_per_second = TILES_TO_PIXELS(11.111) icon_state = "ka_tracer" range = MINER_DASH_RANGE 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 be3552822f..04ff9413aa 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -212,7 +212,7 @@ Difficulty: Very Hard icon_state= "chronobolt" damage = 25 armour_penetration = 100 - speed = 2 + pixels_per_second = TILES_TO_PIXELS(5) eyeblur = 0 damage_type = BRUTE pass_flags = PASSTABLE diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm index 88e33ed91a..5e866f95f1 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm @@ -71,7 +71,10 @@ Difficulty: Extremely Hard /mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/OpenFire() check_enraged() - projectile_speed_multiplier = 1 - enraged * 0.25 + if(enraged) + projectile_speed_multiplier = 1.33 + else + projectile_speed_multiplier = 1 SetRecoveryTime(100, 100) if(client) @@ -109,7 +112,7 @@ Difficulty: Extremely Hard icon_state = "ice_1" damage = 20 armour_penetration = 100 - speed = 10 + pixels_per_second = TILES_TO_PIXELS(1) homing_turn_speed = 30 damage_type = BURN @@ -123,7 +126,7 @@ Difficulty: Extremely Hard icon_state = "nuclear_particle" damage = 5 armour_penetration = 100 - speed = 4 + pixels_per_second = TILES_TO_PIXELS(2.5) damage_type = BRUTE /obj/item/projectile/ice_blast @@ -131,7 +134,7 @@ Difficulty: Extremely Hard icon_state = "ice_2" damage = 15 armour_penetration = 100 - speed = 4 + pixels_per_second = TILES_TO_PIXELS(2.5) damage_type = BRUTE /obj/item/projectile/ice_blast/on_hit(atom/target, blocked = FALSE) @@ -185,7 +188,7 @@ Difficulty: Extremely Hard if(!startloc || !endloc) break var/obj/item/projectile/ice_blast/P = new(startloc) - P.speed *= projectile_speed_multiplier + P.pixels_per_second *= projectile_speed_multiplier P.preparePixelProjectile(endloc, startloc, null, angle + rand(-10, 10)) P.firer = firer if(original) @@ -201,7 +204,7 @@ Difficulty: Extremely Hard if(!endloc) break var/obj/item/projectile/P = new /obj/item/projectile/snowball(startloc) - P.speed *= projectile_speed_multiplier + P.pixels_per_second *= projectile_speed_multiplier P.preparePixelProjectile(endloc, startloc, null, rand(-spread, spread)) P.firer = src if(target) @@ -220,7 +223,7 @@ Difficulty: Extremely Hard if(!endloc) break var/obj/item/projectile/P = new /obj/item/projectile/ice_blast(startloc) - P.speed *= projectile_speed_multiplier + P.pixels_per_second *= projectile_speed_multiplier P.preparePixelProjectile(endloc, startloc, null, spread) P.firer = src if(target) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index c406baf2a6..02e1b47c95 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -145,6 +145,7 @@ /mob/living/simple_animal/hostile/megafauna/proc/SetRecoveryTime(buffer_time) recovery_time = world.time + buffer_time + ranged_cooldown = max(ranged_cooldown, world.time + buffer_time) // CITADEL BANDAID FIX FOR MEGAFAUNA NOT RESPECTING RECOVERY TIME. /mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype, scoretype, crusher_kill) if(!medal_type || (flags_1 & ADMIN_SPAWNED_1)) //Don't award medals if the medal type isn't set diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm index b69a4b69cf..306011dc80 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm @@ -84,8 +84,33 @@ crusher_loot = /obj/item/crusher_trophy/watcher_wing loot = list() butcher_results = list(/obj/item/stack/ore/diamond = 2, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 1) + search_objects = 1 + wanted_objects = list(/obj/item/pen/survival, /obj/item/stack/ore/diamond) field_of_vision_type = FOV_270_DEGREES //Obviously, it's one eyeball. +/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/Life() + . = ..() + if(stat == CONSCIOUS) + consume_bait() + +/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/proc/consume_bait() + var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in oview(src, 9) + var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in oview(src, 9) + if(!diamonds && !bait) + return + if(diamonds) + var/distanced = 0 + distanced = get_dist(loc,diamonds.loc) + if(distanced <= 1 && diamonds) + qdel(diamonds) + src.visible_message("[src] consumes [diamonds], and it disappears! ...At least, you think.") + if(bait) + var/distanceb = 0 + distanceb = get_dist(loc,bait.loc) + if(distanceb <= 1 && bait) + qdel(bait) + visible_message("[src] examines [bait] closer, and telekinetically shatters the pen.") + /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random/Initialize() . = ..() if(prob(1)) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm index 106cb20efc..78b24acfb0 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm @@ -217,7 +217,7 @@ icon_state= "chronobolt" damage = 15 armour_penetration = 60 - speed = 2 + pixels_per_second = TILES_TO_PIXELS(5) eyeblur = 0 damage_type = BRUTE pass_flags = PASSTABLE diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm index c2faa002bc..31f925fb2b 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm @@ -298,5 +298,5 @@ var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc) A.flags_1 |= (flags_1 & ADMIN_SPAWNED_1) A.GiveTarget(target) - A.friends = user + A.friends[user]++ A.faction = user.faction.Copy() diff --git a/code/modules/mob/living/simple_animal/hostile/stickman.dm b/code/modules/mob/living/simple_animal/hostile/stickman.dm index 2edcc4021a..226af952b1 100644 --- a/code/modules/mob/living/simple_animal/hostile/stickman.dm +++ b/code/modules/mob/living/simple_animal/hostile/stickman.dm @@ -13,7 +13,7 @@ speed = 0 blood_volume = 0 stat_attack = UNCONSCIOUS - robust_searching = 1 + robust_searching = TRUE //This is also required for the paper robe rallying to work. environment_smash = ENVIRONMENT_SMASH_NONE maxHealth = 100 health = 100 @@ -30,8 +30,6 @@ faction = list("hostile","stickman") check_friendly_fire = 1 status_flags = CANPUSH - var/datum/action/boss/wizard_summon_minions/changesummons = /datum/action/boss/wizard_summon_minions - var/summoned_by_wizard = 0 /mob/living/simple_animal/hostile/stickman/ranged ranged = 1 @@ -43,7 +41,6 @@ projectilesound = 'sound/misc/bang.ogg' loot = list(/obj/item/gun/ballistic/automatic/pistol/stickman) - /mob/living/simple_animal/hostile/stickman/dog name = "Angry Stick Dog" desc = "Stickman's best friend, if he could see him at least." @@ -52,12 +49,6 @@ icon_dead = "stickdog_dead" mob_biotypes = MOB_BEAST -/mob/living/simple_animal/hostile/stickman/Initialize(mapload, var/wizard_summoned) +/mob/living/simple_animal/hostile/stickman/Initialize(mapload) . = ..() new /obj/effect/temp_visual/paper_scatter(src) - summoned_by_wizard = wizard_summoned - -/mob/living/simple_animal/hostile/stickman/death() - ..() - if(summoned_by_wizard == 1) - changesummons.summoned_minions -- diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 0d41347179..0029300936 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -571,12 +571,13 @@ /mob/living/proc/cure_blind(source) REMOVE_TRAIT(src, TRAIT_BLIND, source) if(!HAS_TRAIT(src, TRAIT_BLIND)) - update_blindness() + if(eye_blind <= 1) //little hack now that we don't actively check for trait and unconsciousness on update_blindness. + adjust_blindness(-1) /mob/living/proc/become_blind(source) if(!HAS_TRAIT(src, TRAIT_BLIND)) // not blind already, add trait then overlay ADD_TRAIT(src, TRAIT_BLIND, source) - update_blindness() + blind_eyes(1) else ADD_TRAIT(src, TRAIT_BLIND, source) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index a09749ba04..e14ff2f721 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -128,15 +128,13 @@ * * target (optional) is the other mob involved with the visible message. For example, the attacker in many combat messages. * * target_message (optional) is what the target mob will see e.g. "[src] does something to you!" */ -/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, mob/target, target_message) +/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, ignored_mobs, mob/target, target_message) var/turf/T = get_turf(src) if(!T) return var/list/hearers = get_hearers_in_view(vision_distance, src) //caches the hearers and then removes ignored mobs. if(!length(hearers)) return - if(!islist(ignored_mobs)) - ignored_mobs = list(ignored_mobs) hearers -= ignored_mobs if(target_message && target && istype(target) && target.client) @@ -150,7 +148,7 @@ msg = blind_message if(msg) target.show_message(msg, MSG_VISUAL,blind_message, MSG_AUDIBLE) - else if(self_message) + if(self_message) hearers -= src for(var/mob/M in hearers) if(!M.client) @@ -185,15 +183,13 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA * * hearing_distance (optional) is the range, how many tiles away the message can be heard. * * ignored_mobs (optional) doesn't show any message to any given mob in the list. */ -/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs) +/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, ignored_mobs) var/turf/T = get_turf(src) if(!T) return var/list/hearers = get_hearers_in_view(hearing_distance, src) if(!length(hearers)) return - if(!islist(ignored_mobs)) - ignored_mobs = list(ignored_mobs) hearers -= ignored_mobs if(self_message) hearers -= src @@ -377,7 +373,7 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA return FALSE new /obj/effect/temp_visual/point(A,invisibility) - + SEND_SIGNAL(src, COMSIG_MOB_POINTED, A) return TRUE /mob/proc/can_resist() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 9947c8ca1e..9dcfb4e99a 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -127,6 +127,13 @@ var/registered_z + var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly + var/list/screens = list() + var/list/client_colours = list() + var/hud_type = /datum/hud + + var/datum/hSB/sandbox = null + var/mob/audiovisual_redirect //Mob to redirect messages, speech, and sounds to var/siliconaccessareas = list() diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 2bcfd47344..9867da1ed4 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -101,10 +101,10 @@ mob.throwing.finalize(FALSE) var/atom/movable/AM = L.pulling - if(AM && AM.density && !(L.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && !ismob(AM)) + if(AM && AM.density && !SEND_SIGNAL(L, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && !ismob(AM)) L.setDir(turn(L.dir, 180)) - SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc) + SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc, add_delay) /// Process_Grab(): checks for grab, attempts to break if so. Return TRUE to prevent movement. /client/proc/Process_Grab() diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index 6be1afb5de..fbef8fd244 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -23,9 +23,9 @@ * Sets a mob's blindness to an amount if it was not above it already, similar to how status effects work */ /mob/proc/blind_eyes(amount) - var/old_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND) - eye_blind = max(eye_blind, amount) - var/new_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND) + var/old_blind = eye_blind + eye_blind = max((!eye_blind && stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : eye_blind , amount) + var/new_blind = eye_blind if(old_blind != new_blind) update_blindness() @@ -36,21 +36,21 @@ */ /mob/proc/adjust_blindness(amount) var/old_eye_blind = eye_blind - eye_blind = max(0, eye_blind + amount) - if(!old_eye_blind || !eye_blind && !HAS_TRAIT(src, TRAIT_BLIND)) + eye_blind = max((stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : 0, eye_blind + amount) + if(!old_eye_blind || !eye_blind) update_blindness() /** * Force set the blindness of a mob to some level */ /mob/proc/set_blindness(amount) var/old_eye_blind = eye_blind - eye_blind = max(amount, 0) - if(!old_eye_blind || !eye_blind && !HAS_TRAIT(src, TRAIT_BLIND)) + eye_blind = max(amount, (stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : 0) + if(!old_eye_blind || !eye_blind) update_blindness() /// proc that adds and removes blindness overlays when necessary /mob/proc/update_blindness() - if(stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND) || eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness + if(eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness if(stat == CONSCIOUS || stat == SOFT_CRIT) throw_alert("blind", /obj/screen/alert/blind) overlay_fullscreen("blind", /obj/screen/fullscreen/blind) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 8fa3ba0f36..dcce95f448 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -302,3 +302,6 @@ /obj/item/paper/crumpled/bloody icon_state = "scrap_bloodied" + +/obj/item/paper/crumpled/muddy + icon_state = "scrap_mud" diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index ca5219375f..1c14a30a8a 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -220,3 +220,17 @@ item_state = initial(item_state) lefthand_file = initial(lefthand_file) righthand_file = initial(righthand_file) + +/obj/item/pen/survival + name = "survival pen" + desc = "The latest in portable survival technology, this pen was designed as a miniature diamond pickaxe. Watchers find them very desirable for their diamond exterior." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "digging_pen" + item_state = "pen" + force = 3 + w_class = WEIGHT_CLASS_TINY + custom_materials = list(/datum/material/iron=10, /datum/material/diamond=100, /datum/material/titanium = 10) + pressure_resistance = 2 + grind_results = list(/datum/reagent/iron = 2, /datum/reagent/iodine = 1) + tool_behaviour = TOOL_MINING //For the classic "digging out of prison with a spoon but you're in space so this analogy doesn't work" situation. + toolspeed = 10 //You will never willingly choose to use one of these over a shovel. diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 19aaa43859..cbedb915ec 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -323,3 +323,15 @@ grind_results = list(/datum/reagent/iodine = 40, /datum/reagent/iron = 10) var/charges = 5 var/max_charges = 5 + +/obj/item/toner/large + name = "large toner cartridge" + grind_results = list(/datum/reagent/iodine = 90, /datum/reagent/iron = 10) + charges = 15 + max_charges = 15 + +/obj/item/toner/extreme + name = "extremely large toner cartridge" + desc = "Why would ANYONE need THIS MUCH TONER?" + charges = 200 + max_charges = 200 diff --git a/code/modules/photography/photos/frame.dm b/code/modules/photography/photos/frame.dm index 11ad81ebf0..9e6f827629 100644 --- a/code/modules/photography/photos/frame.dm +++ b/code/modules/photography/photos/frame.dm @@ -4,7 +4,7 @@ name = "picture frame" desc = "The perfect showcase for your favorite deathtrap memories." icon = 'icons/obj/decals.dmi' - custom_materials = null + custom_materials = list(/datum/material/wood = 2000) flags_1 = 0 icon_state = "frame-empty" result_path = /obj/structure/sign/picture_frame @@ -64,6 +64,7 @@ desc = "Every time you look it makes you laugh." icon = 'icons/obj/decals.dmi' icon_state = "frame-empty" + custom_materials = list(/datum/material/wood = 2000) var/obj/item/photo/framed var/persistence_id var/can_decon = TRUE diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index eb3f2a5dc3..60532028da 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1406,6 +1406,7 @@ if(WIRE_POWER1, WIRE_POWER2) if(!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2)) shorted = FALSE + update() if(WIRE_AI) if(!wires.is_cut(WIRE_AI)) aidisabled = FALSE diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index cc321fdb4d..c788b9b033 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -227,6 +227,7 @@ icon_state = "h+cell" maxcharge = 15000 chargerate = 2250 + rating = 2 /obj/item/stock_parts/cell/high/empty start_charged = FALSE @@ -237,6 +238,7 @@ maxcharge = 20000 custom_materials = list(/datum/material/glass=300) chargerate = 2000 + rating = 3 /obj/item/stock_parts/cell/super/empty start_charged = FALSE @@ -247,6 +249,7 @@ maxcharge = 30000 custom_materials = list(/datum/material/glass=400) chargerate = 3000 + rating = 4 /obj/item/stock_parts/cell/hyper/empty start_charged = FALSE @@ -258,6 +261,7 @@ maxcharge = 40000 custom_materials = list(/datum/material/glass=600) chargerate = 4000 + rating = 5 /obj/item/stock_parts/cell/bluespace/empty start_charged = FALSE @@ -313,7 +317,7 @@ /obj/item/stock_parts/cell/emproof/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF) /obj/item/stock_parts/cell/emproof/empty start_charged = FALSE diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 344d41071d..3c3f3c9541 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -314,8 +314,11 @@ . = ..() SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) if(on && status == LIGHT_OK) - SSvis_overlays.add_vis_overlay(src, overlayicon, base_state, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE, dir, clamp(light_power*250, 30, 200)) - + var/overlay_alpha = clamp(light_power*250, 30, 200) + SSvis_overlays.add_vis_overlay(src, overlayicon, base_state, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE, dir, overlay_alpha) + var/mutable_appearance/M = mutable_appearance(overlayicon, base_state) + M.alpha = overlay_alpha + . += M // update the icon_state and luminosity of the light depending on its state /obj/machinery/light/proc/update(trigger = TRUE) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index ecea673a70..de167f17bc 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -310,6 +310,7 @@ if(H.gloves) var/obj/item/clothing/gloves/G = H.gloves if(G.siemens_coefficient == 0) + SEND_SIGNAL(M, COMSIG_LIVING_SHOCK_PREVENTED, power_source, source, siemens_coeff, dist_check) return 0 //to avoid spamming with insulated glvoes on var/area/source_area diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index d57f78e5b6..0d182e0a1b 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -75,7 +75,7 @@ /obj/machinery/power/emitter/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) /obj/machinery/power/emitter/RefreshParts() var/max_firedelay = 120 diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 950e34098c..af2237a426 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -61,7 +61,7 @@ field_generator power level display /obj/machinery/field/generator/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) /obj/machinery/field/generator/process() if(active == FG_ONLINE) diff --git a/code/modules/projectiles/boxes_magazines/external/rechargable.dm b/code/modules/projectiles/boxes_magazines/external/rechargable.dm index 7ed0cde50a..7a3c82489c 100644 --- a/code/modules/projectiles/boxes_magazines/external/rechargable.dm +++ b/code/modules/projectiles/boxes_magazines/external/rechargable.dm @@ -12,3 +12,105 @@ /obj/item/ammo_box/magazine/recharge/attack_self() //No popping out the "bullets" return + +// MWS Magazine // +/obj/item/ammo_box/magazine/mws_mag + name = "microbattery magazine" + desc = "A microbattery holder for the 'Big Iron'" + + icon = 'icons/obj/ammo.dmi' + icon_state = "mws_mag" + caliber = "mws" + ammo_type = /obj/item/ammo_casing/mws_batt + start_empty = TRUE + max_ammo = 3 + + var/list/modes = list() + +/obj/item/ammo_box/magazine/mws_mag/update_overlays() + .=..() + if(!stored_ammo.len) + return //Why bother + + var/x_offset = 5 + var/current = 0 + for(var/B in stored_ammo) + var/obj/item/ammo_casing/mws_batt/batt = B + var/mutable_appearance/cap = mutable_appearance(icon, "[initial(icon_state)]_cap", color = batt.type_color) + cap.pixel_x = current * x_offset //Caps don't need a pixel_y offset + . += cap + if(batt.cell.charge > 0) + var/ratio = CEILING(clamp(batt.cell.charge / batt.cell.maxcharge, 0, 1) * 4, 1) //4 is how many lights we have a sprite for + var/mutable_appearance/charge = mutable_appearance(icon, "[initial(icon_state)]_charge-[ratio]", color = "#29EAF4") //Could use battery color but eh. + charge.pixel_x = current * x_offset + . += charge + + current++ //Increment for offsets + + +// MWS Batteries // +/obj/item/ammo_casing/mws_batt + name = "\'MWS\' microbattery - UNKNOWN" + desc = "A miniature battery for an energy weapon." + icon = 'icons/obj/ammo.dmi' + icon_state = "mws_batt" + slot_flags = SLOT_BELT | SLOT_EARS + throwforce = 1 + + caliber = "mws" + var/type_color = null + var/type_name = null + + var/obj/item/stock_parts/cell/cell + var/cell_type = /obj/item/stock_parts/cell{charge = 600; maxcharge = 600} + + var/e_cost = 100 + projectile_type = /obj/item/projectile/beam + +/obj/item/ammo_casing/mws_batt/Initialize() + . = ..() + pixel_x = rand(-10, 10) + pixel_y = rand(-10, 10) + cell = new cell_type(src) + cell.give(cell.maxcharge) + update_icon() + +/obj/item/ammo_casing/mws_batt/update_overlays() + .=..() + + var/mutable_appearance/ends = mutable_appearance(icon, "[initial(icon_state)]_ends", color = type_color) + . += ends + +/obj/item/ammo_casing/mws_batt/get_cell() + return cell + +/obj/item/ammo_casing/mws_batt/proc/chargeshot() + if(cell.charge >= e_cost) + cell.use(e_cost) + newshot() + return + +// Specific batteries // +/obj/item/ammo_casing/mws_batt/lethal + name = "'MWS' microbattery - LETHAL" + type_color = "#bf3d3d" + type_name = "LETHAL" + projectile_type = /obj/item/projectile/beam + +/obj/item/ammo_casing/mws_batt/stun + name = "'MWS' microbattery - STUN" + type_color = "#0f81bc" + type_name = "STUN" + projectile_type = /obj/item/projectile/beam/disabler + +/obj/item/ammo_casing/mws_batt/xray + name = "'MWS' microbattery - XRAY" + type_color = "#32c025" + type_name = "XRAY" + projectile_type = /obj/item/projectile/beam/xray + +/obj/item/ammo_casing/mws_batt/ion + name = "'MWS' microbattery - ION" + type_color = "#d084d6" + type_name = "ION" + projectile_type = /obj/item/projectile/ion \ No newline at end of file diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index cf9e606ffc..c4909c5583 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -76,17 +76,18 @@ var/datum/action/item_action/toggle_scope_zoom/azoom var/dualwield_spread_mult = 1 //dualwield spread multiplier - + /// Just 'slightly' snowflakey way to modify projectile damage for projectiles fired from this gun. var/projectile_damage_multiplier = 1 + var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds + /obj/item/gun/Initialize() . = ..() - if(pin) - if(no_pin_required) - pin = null - else - pin = new pin(src) + if(no_pin_required) + pin = null + else if(pin) + pin = new pin(src) if(gun_light) alight = new (src) if(zoomable) @@ -127,7 +128,7 @@ zoom(user, FALSE) //we can only stay zoomed in if it's in our hands //yeah and we only unzoom if we're actually zoomed using the gun!! //called after the gun has successfully fired its chambered ammo. -/obj/item/gun/proc/process_chamber() +/obj/item/gun/proc/process_chamber(mob/living/user) return FALSE //check if there's enough ammo/energy/whatever to shoot one time @@ -214,8 +215,9 @@ var/bonus_spread = 0 var/loop_counter = 0 - bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming - if(ishuman(user) && user.a_intent == INTENT_HARM) + if(user) + bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming + if(ishuman(user) && user.a_intent == INTENT_HARM && weapon_weight <= WEAPON_LIGHT) var/mob/living/carbon/human/H = user for(var/obj/item/gun/G in H.held_items) if(G == src || G.weapon_weight >= WEAPON_MEDIUM) @@ -304,7 +306,7 @@ else shoot_with_empty_chamber(user) return - process_chamber() + process_chamber(user) update_icon() SSblackbox.record_feedback("tally", "gun_fired", 1, type) @@ -343,7 +345,7 @@ shoot_with_empty_chamber(user) firing = FALSE return FALSE - process_chamber() + process_chamber(user) update_icon() return TRUE @@ -564,12 +566,7 @@ chambered = null update_icon() -/obj/item/gun/proc/getinaccuracy(mob/living/user) - if(!isliving(user)) - return FALSE - else - var/mob/living/holdingdude = user - if(istype(holdingdude) && (holdingdude.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - return 0 - else - return ((weapon_weight * 25) * inaccuracy_modifier) +/obj/item/gun/proc/getinaccuracy(mob/user) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) + return ((weapon_weight * 25) * inaccuracy_modifier) + return 0 diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index afe2b9ca3e..9e43ec052f 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -313,19 +313,24 @@ else to_chat(user, "[src] is empty!") -// IMPROVISED SHOTGUN // +///////////////////////////// +// IMPROVISED SHOTGUN // +///////////////////////////// /obj/item/gun/ballistic/revolver/doublebarrel/improvised name = "improvised shotgun" desc = "Essentially a tube that aims shotgun shells." + desc = "A shoddy break-action breechloaded shotgun. Its lacklustre construction will probably result in it hurting people less than a normal shotgun." icon_state = "ishotgun" item_state = "shotgun" w_class = WEIGHT_CLASS_BULKY + weapon_weight = WEAPON_MEDIUM force = 10 slot_flags = null mag_type = /obj/item/ammo_box/magazine/internal/shot/improvised sawn_desc = "I'm just here for the gasoline." unique_reskin = null + projectile_damage_multiplier = 0.8 var/slung = FALSE /obj/item/gun/ballistic/revolver/doublebarrel/improvised/attackby(obj/item/A, mob/user, params) @@ -372,3 +377,114 @@ user.emote("scream") user.drop_all_held_items() user.DefaultCombatKnockdown(80) + +// -------------- HoS Modular Weapon System ------------- +// ---------- Code originally from VoreStation ---------- +/obj/item/gun/ballistic/revolver/mws + name = "MWS-01 'Big Iron'" + desc = "Modular Weapons System" + + icon = 'icons/obj/guns/projectile.dmi' + icon_state = "mws" + + fire_sound = 'sound/weapons/Taser.ogg' + + mag_type = /obj/item/ammo_box/magazine/mws_mag + spawnwithmagazine = FALSE + + recoil = 0 + + var/charge_sections = 6 + +/obj/item/gun/ballistic/revolver/mws/examine(mob/user) + . = ..() + . += "Alt-click to remove the magazine." + +/obj/item/gun/ballistic/revolver/mws/shoot_with_empty_chamber(mob/living/user as mob|obj) + process_chamber(user) + if(!chambered || !chambered.BB) + to_chat(user, "*click*") + playsound(src, "gun_dry_fire", 30, 1) + + +/obj/item/gun/ballistic/revolver/mws/process_chamber(mob/living/user) + if(chambered && !chambered.BB) //if BB is null, i.e the shot has been fired... + var/obj/item/ammo_casing/mws_batt/shot = chambered + if(shot.cell.charge >= shot.e_cost) + shot.chargeshot() + else + for(var/B in magazine.stored_ammo) + var/obj/item/ammo_casing/mws_batt/other_batt = B + if(istype(other_batt,shot) && other_batt.cell.charge >= other_batt.e_cost) + switch_to(other_batt, user) + break + update_icon() + +/obj/item/gun/ballistic/revolver/mws/proc/switch_to(obj/item/ammo_casing/mws_batt/new_batt, mob/living/user) + if(ishuman(user)) + if(chambered && new_batt.type == chambered.type) + to_chat(user,"[src] is now using the next [new_batt.type_name] power cell.") + else + to_chat(user,"[src] is now firing [new_batt.type_name].") + + chambered = new_batt + update_icon() + +/obj/item/gun/ballistic/revolver/mws/attack_self(mob/living/user) + if(!chambered) + return + + var/list/stored_ammo = magazine.stored_ammo + + if(stored_ammo.len == 1) + return //silly you. + + //Find an ammotype that ISN'T the same, or exhaust the list and don't change. + var/our_slot = stored_ammo.Find(chambered) + + for(var/index in 1 to stored_ammo.len) + var/true_index = ((our_slot + index - 1) % stored_ammo.len) + 1 // Stupid ONE BASED lists! + var/obj/item/ammo_casing/mws_batt/next_batt = stored_ammo[true_index] + if(chambered != next_batt && !istype(next_batt, chambered.type) && next_batt.cell.charge >= next_batt.e_cost) + switch_to(next_batt, user) + break + +/obj/item/gun/ballistic/revolver/mws/AltClick(mob/living/user) + .=..() + if(magazine) + user.put_in_hands(magazine) + magazine.update_icon() + if(magazine.ammo_count()) + playsound(src, 'sound/weapons/gun_magazine_remove_full.ogg', 70, 1) + else + playsound(src, "gun_remove_empty_magazine", 70, 1) + magazine = null + to_chat(user, "You pull the magazine out of [src].") + if(chambered) + chambered = null + update_icon() + +/obj/item/gun/ballistic/revolver/mws/update_overlays() + .=..() + if(!chambered) + return + + var/obj/item/ammo_casing/mws_batt/batt = chambered + var/batt_color = batt.type_color //Used many times + + //Mode bar + var/image/mode_bar = image(icon, icon_state = "[initial(icon_state)]_type") + mode_bar.color = batt_color + . += mode_bar + + //Barrel color + var/mutable_appearance/barrel_color = mutable_appearance(icon, "[initial(icon_state)]_barrel", color = batt_color) + barrel_color.alpha = 150 + . += barrel_color + + //Charge bar + var/ratio = can_shoot() ? CEILING(clamp(batt.cell.charge / batt.cell.maxcharge, 0, 1) * charge_sections, 1) : 0 + for(var/i = 0, i < ratio, i++) + var/mutable_appearance/charge_bar = mutable_appearance(icon, "[initial(icon_state)]_charge", color = batt_color) + charge_bar.pixel_x = i + . += charge_bar \ No newline at end of file diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index 4894a8d8eb..e438b351b3 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -126,8 +126,9 @@ /obj/item/gun/ballistic/shotgun/boltaction/improvised name = "Makeshift 7.62mm Rifle" icon_state = "ishotgun" + icon_state = "irifle" item_state = "shotgun" - desc = "A large zip gun more or less that takes a single 7.62mm bullet" + desc = "A bolt-action breechloaded rifle that takes 7.62mm bullets." mag_type = /obj/item/ammo_box/magazine/internal/boltaction/improvised can_bayonet = FALSE diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index f8ddcb5aae..bcb074023f 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -77,7 +77,6 @@ var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty") var/datum/action/item_action/zoom_lock_action/zoom_lock_action - var/mob/listeningTo /obj/item/gun/energy/beam_rifle/debug delay = 0 @@ -178,7 +177,6 @@ STOP_PROCESSING(SSfastprocess, src) set_user(null) QDEL_LIST(current_tracers) - listeningTo = null return ..() /obj/item/gun/energy/beam_rifle/proc/aiming_beam(force_update = FALSE) @@ -260,17 +258,12 @@ if(user == current_user) return stop_aiming(current_user) - if(listeningTo) - UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) - listeningTo = null - if(istype(current_user)) - LAZYREMOVE(current_user.mousemove_intercept_objects, src) + if(current_user) + UnregisterSignal(current_user, COMSIG_MOVABLE_MOVED) current_user = null if(istype(user)) current_user = user - LAZYOR(current_user.mousemove_intercept_objects, src) RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move) - listeningTo = user /obj/item/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob) if(aiming) @@ -295,7 +288,7 @@ if(istype(object, /obj/screen) && !istype(object, /obj/screen/click_catcher)) return process_aim() - if(fire_check()) + if(fire_check() && can_trigger_gun(M)) sync_ammo() do_fire(M.client.mouseObject, M, FALSE, M.client.mouseParams, M.zone_selected) stop_aiming() diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm index 8a1db49762..cef730366e 100644 --- a/code/modules/projectiles/pins.dm +++ b/code/modules/projectiles/pins.dm @@ -13,11 +13,16 @@ var/pin_removeable = 0 // Can be replaced by any pin. var/obj/item/gun/gun -/obj/item/firing_pin/New(newloc) - ..() +/obj/item/firing_pin/Initialize(newloc) + . = ..() if(istype(newloc, /obj/item/gun)) gun = newloc +/obj/item/firing_pin/Destroy() + if(gun) + gun.pin = null + return ..() + /obj/item/firing_pin/afterattack(atom/target, mob/user, proximity_flag) . = ..() if(proximity_flag) @@ -224,24 +229,6 @@ suit_requirement = /obj/item/clothing/suit/bluetag tagcolor = "blue" -/obj/item/firing_pin/Destroy() - if(gun) - gun.pin = null - return ..() - -//Station Locked - -/obj/item/firing_pin/away - name = "station locked pin" - desc = "A firing pin that only will fire when off the station." - -/obj/item/firing_pin/away/pin_auth(mob/living/user) - var/area/station_area = get_area(src) - if(!station_area || is_station_level(station_area.z)) - to_chat(user, "The pin beeps, refusing to fire.") - return FALSE - return TRUE - /obj/item/firing_pin/security_level name = "security level firing pin" desc = "A sophisticated firing pin that authorizes operation based on its settings and current security level." @@ -325,3 +312,18 @@ /obj/item/firing_pin/security_level/pin_auth(mob/living/user) return (only_lethals && !(gun.chambered?.harmful)) || ISINRANGE(GLOB.security_level, min_sec_level, max_sec_level) + +// Explorer Firing Pin- Prevents use on station Z-Level, so it's justifiable to give Explorers guns that don't suck. +/obj/item/firing_pin/explorer + name = "outback firing pin" + desc = "A firing pin used by the austrailian defense force, retrofit to prevent weapon discharge on the station." + icon_state = "firing_pin_explorer" + fail_message = "CANNOT FIRE WHILE ON STATION, MATE!" + +// This checks that the user isn't on the station Z-level. +/obj/item/firing_pin/explorer/pin_auth(mob/living/user) + var/turf/station_check = get_turf(user) + if(!station_check||is_station_level(station_check.z)) + to_chat(user, "You cannot use your weapon while on the station!") + return FALSE + return TRUE diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 71aa78da4b..213bc35b52 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -1,6 +1,10 @@ #define MOVES_HITSCAN -1 //Not actually hitscan but close as we get without actual hitscan. #define MUZZLE_EFFECT_PIXEL_INCREMENT 17 //How many pixels to move the muzzle flash up so your character doesn't look like they're shitting out lasers. +/// Minimum projectile pixels to move before it animate()S, below this it's a direct set. +#define MINIMUM_PIXELS_TO_ANIMATE 4 +/// Pixels to instantly travel on firing. +#define PROJECTILE_FIRING_INSTANT_TRAVEL_AMOUNT 16 /obj/item/projectile name = "projectile" @@ -12,7 +16,9 @@ pass_flags = PASSTABLE mouse_opacity = MOUSE_OPACITY_TRANSPARENT movement_type = FLYING + animate_movement = NO_STEPS hitsound = 'sound/weapons/pierce.ogg' + appearance_flags = PIXEL_SCALE var/hitsound_wall = "" resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF @@ -32,14 +38,19 @@ //Fired processing vars var/fired = FALSE //Have we been fired yet var/paused = FALSE //for suspending the projectile midair - var/last_projectile_move = 0 var/time_offset = 0 var/datum/point/vector/trajectory var/trajectory_ignore_forcemove = FALSE //instructs forceMove to NOT reset our trajectory to the new location! + /// "leftover" pixels for Range() calculation as pixel_move() was moved to simulated semi-pixel movement and Range() is in tiles. + var/pixels_range_leftover = 0 + /// "leftover" tick pixels and stuff yeah, so we don't round off things and introducing tracing inaccuracy. + var/pixels_tick_leftover = 0 + + /// Pixels moved per second. + var/pixels_per_second = TILES_TO_PIXELS(12.5) + /// The number of pixels we increment by. THIS IS NOT SPEED, DO NOT TOUCH THIS UNLESS YOU KNOW WHAT YOU ARE DOING. In general, lower values means more linetrace accuracy up to a point at cost of performance. + var/pixel_increment_amount - var/speed = 0.8 //Amount of deciseconds it takes for projectile to travel - /// "leftover" ticks and stuff yeah. hey when are we rewriting projectiles for the eighth time to do something smarter like incrementing x pixels until it meets a goal instead of for(var/i in 1 to required_moves)? - var/tick_moves_leftover = 0 var/Angle = 0 var/original_angle = 0 //Angle at firing var/nondirectional_sprite = FALSE //Set TRUE to prevent projectiles from having their sprites rotated based on firing angle @@ -75,12 +86,16 @@ //Homing var/homing = FALSE var/atom/homing_target - var/homing_turn_speed = 10 //Angle per tick. + /// How fast the projectile turns towards its homing targets, in angle per second. + var/homing_turn_speed = 100 var/homing_inaccuracy_min = 0 //in pixels for these. offsets are set once when setting target. var/homing_inaccuracy_max = 0 var/homing_offset_x = 0 var/homing_offset_y = 0 + /// How many deciseconds are each hitscan movement considered. Used for homing and other things that use seconds for timing rather than ticks. + var/hitscan_movement_decisecond_equivalency = 0.1 + var/ignore_source_check = FALSE var/damage = 10 @@ -88,7 +103,8 @@ var/nodamage = 0 //Determines if the projectile will skip any damage inflictions var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb var/projectile_type = /obj/item/projectile - var/range = 50 //This will de-increment every step. When 0, it will deletze the projectile. + /// Range of the projectile, de-incrementing every step. The projectile deletes itself at 0. This is in tiles. + var/range = 50 var/decayedRange //stores original range var/reflect_range_decrease = 5 //amount of original range that falls off when reflecting, so it doesn't go forever var/is_reflectable = FALSE // Can it be reflected or not? @@ -120,6 +136,10 @@ permutated = list() decayedRange = range +/** + * Artificially modified to be called at around every world.icon_size pixels of movement. + * WARNING: Range() can only be called once per pixel_increment_amount pixels. + */ /obj/item/projectile/proc/Range() range-- if(range <= 0 && loc) @@ -334,14 +354,15 @@ return TRUE return FALSE +/// one move is a tile. /obj/item/projectile/proc/return_predicted_turf_after_moves(moves, forced_angle) //I say predicted because there's no telling that the projectile won't change direction/location in flight. if(!trajectory && isnull(forced_angle) && isnull(Angle)) return FALSE var/datum/point/vector/current = trajectory if(!current) var/turf/T = get_turf(src) - current = new(T.x, T.y, T.z, pixel_x, pixel_y, isnull(forced_angle)? Angle : forced_angle, SSprojectiles.global_pixel_speed) - var/datum/point/vector/v = current.return_vector_after_increments(moves * SSprojectiles.global_iterations_per_move) + current = new(T.x, T.y, T.z, pixel_x, pixel_y, isnull(forced_angle)? Angle : forced_angle, pixel_increment_amount || SSprojectiles.global_pixel_increment_amount) + var/datum/point/vector/v = current.return_vector_after_increments(TILES_TO_PIXELS(moves) / (pixel_increment_amount || SSprojectiles.global_pixel_increment_amount)) return v.return_turf() /obj/item/projectile/proc/return_pathing_turfs_in_moves(moves, forced_angle) @@ -358,16 +379,14 @@ return PROCESS_KILL if(paused || !isturf(loc)) return + var/ds = (SSprojectiles.flags & SS_TICKER)? (wait * world.tick_lag) : wait - var/required_moves = ds / speed - var/leftover = MODULUS(required_moves, 1) - tick_moves_leftover += leftover - required_moves = round(required_moves) - if(tick_moves_leftover > 1) - required_moves += round(tick_moves_leftover) - tick_moves_leftover = MODULUS(tick_moves_leftover, 1) - for(var/i in 1 to required_moves) - pixel_move(1, FALSE) + var/required_pixels = (pixels_per_second * ds * 0.1) + pixels_tick_leftover + if(required_pixels >= pixel_increment_amount) + pixels_tick_leftover = MODULUS(required_pixels, pixel_increment_amount) + pixel_move(FLOOR(required_pixels / pixel_increment_amount, 1), FALSE, ds, SSprojectiles.global_projectile_speed_multiplier) + else + pixels_tick_leftover = required_pixels /obj/item/projectile/proc/fire(angle, atom/direct_target) if(fired_from) @@ -390,7 +409,7 @@ qdel(src) return var/turf/target = locate(clamp(starting + xo, 1, world.maxx), clamp(starting + yo, 1, world.maxy), starting.z) - setAngle(Get_Angle(src, target)) + setAngle(get_projectile_angle(src, target)) original_angle = Angle if(!nondirectional_sprite) var/matrix/M = new @@ -399,14 +418,16 @@ trajectory_ignore_forcemove = TRUE forceMove(starting) trajectory_ignore_forcemove = FALSE - trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, SSprojectiles.global_pixel_speed) - last_projectile_move = world.time + if(isnull(pixel_increment_amount)) + pixel_increment_amount = SSprojectiles.global_pixel_increment_amount + trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, pixel_increment_amount) fired = TRUE if(hitscan) process_hitscan() + return if(!(datum_flags & DF_ISPROCESSING)) START_PROCESSING(SSprojectiles, src) - pixel_move(1, FALSE) //move it now! + pixel_move(round(PROJECTILE_FIRING_INSTANT_TRAVEL_AMOUNT / pixel_increment_amount), FALSE, allow_animation = FALSE) //move it now! /obj/item/projectile/proc/setAngle(new_angle, hitscan_store_segment = TRUE) //wrapper for overrides. Angle = new_angle @@ -451,7 +472,8 @@ else return ..() -/obj/item/projectile/proc/set_pixel_speed(new_speed) +/obj/item/projectile/proc/set_pixel_increment_amount(new_speed) + pixel_increment_amount = new_speed if(trajectory) trajectory.set_speed(new_speed) return TRUE @@ -464,6 +486,7 @@ beam_segments[beam_index] = null //record start. /obj/item/projectile/proc/process_hitscan() + var/ttm = round(world.icon_size / pixel_increment_amount, 1) var/safety = range * 10 record_hitscan_start(RETURN_POINT_VECTOR_INCREMENT(src, Angle, MUZZLE_EFFECT_PIXEL_INCREMENT, 1)) while(loc && !QDELETED(src)) @@ -476,20 +499,33 @@ if(!QDELETED(src)) qdel(src) return //Kill! - pixel_move(1, TRUE) + pixel_move(ttm, TRUE, hitscan_movement_decisecond_equivalency) -/obj/item/projectile/proc/pixel_move(trajectory_multiplier, hitscanning = FALSE) +/** + * The proc to make the projectile go, using a simulated pixel movement line trace. + * Note: deciseconds_equivalent is currently only used for homing, times is the number of times to move pixel_increment_amount. + * Trajectory multiplier directly modifies the factor of pixel_increment_amount to go per time. + * It's complicated, so probably just don'ot mess with this unless you know what you're doing. + */ +/obj/item/projectile/proc/pixel_move(times, hitscanning = FALSE, deciseconds_equivalent = world.tick_lag, trajectory_multiplier = 1, allow_animation = TRUE) if(!loc || !trajectory) return - last_projectile_move = world.time if(!nondirectional_sprite && !hitscanning) var/matrix/M = new M.Turn(Angle) transform = M - if(homing) - process_homing() var/forcemoved = FALSE - for(var/i in 1 to SSprojectiles.global_iterations_per_move) + var/turf/oldloc = loc + var/old_px = pixel_x + var/old_py = pixel_y + for(var/i in 1 to times) + // HOMING START - Too expensive to proccall at this point. + if(homing_target) + // No datum/points, too expensive. + var/angle = closer_angle_difference(Angle, get_projectile_angle(src, homing_target)) + var/max_turn = homing_turn_speed * deciseconds_equivalent * 0.1 + setAngle(Angle + clamp(angle, -max_turn, max_turn)) + // HOMING END trajectory.increment(trajectory_multiplier) var/turf/T = trajectory.return_turf() if(!istype(T)) @@ -509,23 +545,29 @@ pixel_x = trajectory.return_px() pixel_y = trajectory.return_py() else if(T != loc) - step_towards(src, T) + var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 2 + 1 + while(T != loc) + if(!--safety) + CRASH("Projectile took more than pixel incrememnt speed times 2 to get to its location, this is probably something seriously scuffed going on.") + step_towards(src, T) + if(QDELETED(src)) + return + pixels_range_leftover += pixel_increment_amount + if(pixels_range_leftover > world.icon_size) + Range() if(QDELETED(src)) return + pixels_range_leftover -= world.icon_size if(!hitscanning && !forcemoved) - pixel_x = trajectory.return_px() - trajectory.mpx * trajectory_multiplier * SSprojectiles.global_iterations_per_move - pixel_y = trajectory.return_py() - trajectory.mpy * trajectory_multiplier * SSprojectiles.global_iterations_per_move - animate(src, pixel_x = trajectory.return_px(), pixel_y = trajectory.return_py(), time = 1, flags = ANIMATION_END_NOW) - Range() - -/obj/item/projectile/proc/process_homing() //may need speeding up in the future performance wise. - if(!homing_target) - return FALSE - var/datum/point/PT = RETURN_PRECISE_POINT(homing_target) - PT.x += clamp(homing_offset_x, 1, world.maxx) - PT.y += clamp(homing_offset_y, 1, world.maxy) - var/angle = closer_angle_difference(Angle, angle_between_points(RETURN_PRECISE_POINT(src), PT)) - setAngle(Angle + clamp(angle, -homing_turn_speed, homing_turn_speed)) + var/traj_px = round(trajectory.return_px(), 1) + var/traj_py = round(trajectory.return_py(), 1) + if(allow_animation && (pixel_increment_amount * times > MINIMUM_PIXELS_TO_ANIMATE)) + pixel_x = ((oldloc.x - x) * world.icon_size) + old_px + pixel_y = ((oldloc.y - y) * world.icon_size) + old_py + animate(src, pixel_x = traj_px, pixel_y = traj_py, time = 1, flags = ANIMATION_END_NOW) + else + pixel_x = traj_px + pixel_y = traj_py /obj/item/projectile/proc/set_homing_target(atom/A) if(!A || (!isturf(A) && !isturf(A.loc))) @@ -575,7 +617,7 @@ if(targloc || !params) yo = targloc.y - curloc.y xo = targloc.x - curloc.x - setAngle(Get_Angle(src, targloc) + spread) + setAngle(get_projectile_angle(src, targloc) + spread) if(isliving(source) && params) var/list/calculated = calculate_projectile_angle_and_pixel_offsets(source, params) @@ -586,7 +628,7 @@ else if(targloc) yo = targloc.y - curloc.y xo = targloc.x - curloc.x - setAngle(Get_Angle(src, targloc) + spread) + setAngle(get_projectile_angle(src, targloc) + spread) else stack_trace("WARNING: Projectile [type] fired without either mouse parameters, or a target atom to aim at!") qdel(src) @@ -698,3 +740,7 @@ /proc/is_energy_reflectable_projectile(atom/A) var/obj/item/projectile/P = A return istype(P) && P.is_reflectable + +#undef MOVES_HITSCAN +#undef MINIMUM_PIXELS_TO_ANIMATE +#undef MUZZLE_EFFECT_PIXEL_INCREMENT diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index ee081d57d6..2f12f0f69b 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -74,7 +74,7 @@ flag = "energy" hitsound = 'sound/weapons/tap.ogg' eyeblur = 0 - speed = 0.6 + pixels_per_second = TILES_TO_PIXELS(16.667) impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser light_color = LIGHT_COLOR_BLUE tracer_type = /obj/effect/projectile/tracer/disabler diff --git a/code/modules/projectiles/projectile/bullets/ferromagnetic.dm b/code/modules/projectiles/projectile/bullets/ferromagnetic.dm index 2d66e25256..78deff601f 100644 --- a/code/modules/projectiles/projectile/bullets/ferromagnetic.dm +++ b/code/modules/projectiles/projectile/bullets/ferromagnetic.dm @@ -3,7 +3,7 @@ damage = 20 armour_penetration = 20 light_range = 3 - speed = 0.6 + pixels_per_second = TILES_TO_PIXELS(16.667) range = 35 light_color = LIGHT_COLOR_RED @@ -39,7 +39,7 @@ armour_penetration = 20 movement_type = FLYING | UNSTOPPABLE range = 20 - speed = 0.8 + pixels_per_second = TILES_TO_PIXELS(12.5) light_range = 4 light_color = LIGHT_COLOR_RED diff --git a/code/modules/projectiles/projectile/bullets/sniper.dm b/code/modules/projectiles/projectile/bullets/sniper.dm index 5e3ae53806..f69b62a149 100644 --- a/code/modules/projectiles/projectile/bullets/sniper.dm +++ b/code/modules/projectiles/projectile/bullets/sniper.dm @@ -2,7 +2,7 @@ /obj/item/projectile/bullet/p50 name =".50 bullet" - speed = 0.4 + pixels_per_second = TILES_TO_PIXELS(25) damage = 70 knockdown = 100 dismemberment = 50 @@ -43,5 +43,5 @@ /obj/item/projectile/bullet/p50/penetrator/shuttle //Nukeop Shuttle Variety icon_state = "gaussstrong" damage = 25 - speed = 0.3 + pixels_per_second = TILES_TO_PIXELS(33.33) range = 16 diff --git a/code/modules/projectiles/projectile/energy/nuclear_particle.dm b/code/modules/projectiles/projectile/energy/nuclear_particle.dm index e08f806fe5..6cbe258560 100644 --- a/code/modules/projectiles/projectile/energy/nuclear_particle.dm +++ b/code/modules/projectiles/projectile/energy/nuclear_particle.dm @@ -5,7 +5,7 @@ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE flag = "rad" irradiate = 5000 - speed = 0.4 + pixels_per_second = TILES_TO_PIXELS(25) hitsound = 'sound/weapons/emitter2.ogg' impact_type = /obj/effect/projectile/impact/xray var/static/list/particle_colors = list( diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm index e3449a0c1d..83b753e0a3 100644 --- a/code/modules/projectiles/projectile/energy/stun.dm +++ b/code/modules/projectiles/projectile/energy/stun.dm @@ -10,7 +10,7 @@ jitter = 20 hitsound = 'sound/weapons/taserhit.ogg' range = 14 - speed = 0.6 + pixels_per_second = TILES_TO_PIXELS(16.667) tracer_type = /obj/effect/projectile/tracer/stun muzzle_type = /obj/effect/projectile/muzzle/stun impact_type = /obj/effect/projectile/impact/stun diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index dbb1497367..493a02d74c 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -434,7 +434,7 @@ damage = 15 damage_type = BURN nodamage = 0 - speed = 0.3 + pixels_per_second = TILES_TO_PIXELS(33.33) flag = "magic" var/zap_power = 20000 diff --git a/code/modules/projectiles/projectile/special/curse.dm b/code/modules/projectiles/projectile/special/curse.dm index 99aa922622..d967540e6a 100644 --- a/code/modules/projectiles/projectile/special/curse.dm +++ b/code/modules/projectiles/projectile/special/curse.dm @@ -10,7 +10,7 @@ damage_type = BURN damage = 10 knockdown = 20 - speed = 2 + pixels_per_second = TILES_TO_PIXELS(5) range = 16 movement_type = FLYING | UNSTOPPABLE var/datum/beam/arm diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 09ba0762cf..da33f935da 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -23,7 +23,7 @@ resistance_flags = FIRE_PROOF | ACID_PROOF circuit = /obj/item/circuitboard/machine/chem_dispenser var/obj/item/stock_parts/cell/cell - var/powerefficiency = 0.1 + var/powerefficiency = 0.0666666 var/amount = 30 var/recharge_amount = 10 var/recharge_counter = 0 @@ -386,7 +386,7 @@ /obj/machinery/chem_dispenser/RefreshParts() recharge_amount = initial(recharge_amount) - var/newpowereff = 0.0666666 + var/newpowereff = initial(powerefficiency) for(var/obj/item/stock_parts/cell/P in component_parts) cell = P for(var/obj/item/stock_parts/matter_bin/M in component_parts) @@ -719,3 +719,58 @@ component_parts += new /obj/item/stack/sheet/glass(null) component_parts += new /obj/item/stock_parts/cell/bluespace(null) RefreshParts() + +///An unique, less efficient model found in the medbay apothecary room. +/obj/machinery/chem_dispenser/apothecary + name = "apothecary chem dispenser" + desc = "A cheaper chem dispenser meant for small scale medicine production." + icon_state = "minidispenser" + working_state = "minidispenser_working" + nopower_state = "minidispenser_nopower" + circuit = /obj/item/circuitboard/machine/chem_dispenser/apothecary + powerefficiency = 0.0833333 + dispensable_reagents = list( //radium and stable plasma moved to upgrade tier 1 and 2, they've little to do with most medicines anyway. + /datum/reagent/hydrogen, + /datum/reagent/lithium, + /datum/reagent/carbon, + /datum/reagent/nitrogen, + /datum/reagent/oxygen, + /datum/reagent/fluorine, + /datum/reagent/sodium, + /datum/reagent/aluminium, + /datum/reagent/silicon, + /datum/reagent/phosphorus, + /datum/reagent/sulfur, + /datum/reagent/chlorine, + /datum/reagent/potassium, + /datum/reagent/iron, + /datum/reagent/copper, + /datum/reagent/mercury, + /datum/reagent/water, + /datum/reagent/consumable/ethanol, + /datum/reagent/consumable/sugar, + /datum/reagent/toxin/acid, + /datum/reagent/fuel, + /datum/reagent/silver, + /datum/reagent/iodine, + /datum/reagent/bromine + ) + upgrade_reagents = list( + /datum/reagent/oil, + /datum/reagent/ammonia, + /datum/reagent/radium + ) + upgrade_reagents2 = list( + /datum/reagent/acetone, + /datum/reagent/phenol, + /datum/reagent/stable_plasma + ) + upgrade_reagents3 = list( + /datum/reagent/medicine/mine_salve + ) + + emagged_reagents = list( + /datum/reagent/drug/space_drugs, + /datum/reagent/toxin/carpotoxin, + /datum/reagent/medicine/morphine + ) diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index ef4b7f3a53..f1e45d0717 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -559,3 +559,128 @@ var/mob/living/carbon/C = M if(!C.undergoing_cardiac_arrest()) C.set_heartattack(TRUE) + +//aphrodisiac & anaphrodisiac + +/datum/reagent/drug/aphrodisiac + name = "Crocin" + description = "Naturally found in the crocus and gardenia flowers, this drug acts as a natural and safe aphrodisiac." + taste_description = "strawberries" + color = "#FFADFF"//PINK, rgb(255, 173, 255) + can_synth = FALSE + +/datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M) + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) + if((prob(min(current_cycle/2,5)))) + M.emote(pick("moan","blush")) + if(prob(min(current_cycle/4,10))) + var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.") + to_chat(M, "[aroused_message]") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/list/genits = H.adjust_arousal(current_cycle, aphro = TRUE) // redundant but should still be here + for(var/g in genits) + var/obj/item/organ/genital/G = g + to_chat(M, "[G.arousal_verb]!") + ..() + +/datum/reagent/drug/aphrodisiacplus + name = "Hexacrocin" + description = "Chemically condensed form of basic crocin. This aphrodisiac is extremely powerful and addictive in most animals.\ + Addiction withdrawals can cause brain damage and shortness of breath. Overdosage can lead to brain damage and a \ + permanent increase in libido (commonly referred to as 'bimbofication')." + taste_description = "liquid desire" + color = "#FF2BFF"//dark pink + addiction_threshold = 20 + overdose_threshold = 20 + can_synth = FALSE + +/datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M) + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) + if(prob(5)) + if(prob(current_cycle)) + M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn...")) + else + M.emote(pick("moan","blush")) + if(prob(5)) + var/aroused_message + if(current_cycle>25) + aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!") + else + aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.") + to_chat(M, "[aroused_message]") + REMOVE_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/list/genits = H.adjust_arousal(100, aphro = TRUE) // redundant but should still be here + for(var/g in genits) + var/obj/item/organ/genital/G = g + to_chat(M, "[G.arousal_verb]!") + ..() + +/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M) + if(prob(30)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2) + ..() +/datum/reagent/drug/aphrodisiacplus/addiction_act_stage3(mob/living/M) + if(prob(30)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3) + + ..() +/datum/reagent/drug/aphrodisiacplus/addiction_act_stage4(mob/living/M) + if(prob(30)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) + ..() + +/datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M) + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33)) + if(prob(5) && ishuman(M) && M.has_dna() && (M.client?.prefs.cit_toggles & BIMBOFICATION)) + if(!HAS_TRAIT(M,TRAIT_PERMABONER)) + to_chat(M, "Your libido is going haywire!") + ADD_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT) + ..() + +/datum/reagent/drug/anaphrodisiac + name = "Camphor" + description = "Naturally found in some species of evergreen trees, camphor is a waxy substance. When injested by most animals, it acts as an anaphrodisiac\ + , reducing libido and calming them. Non-habit forming and not addictive." + taste_description = "dull bitterness" + taste_mult = 2 + color = "#D9D9D9"//rgb(217, 217, 217) + reagent_state = SOLID + can_synth = FALSE + +/datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M) + if(M && M.client?.prefs.arousable && prob(16)) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/list/genits = H.adjust_arousal(-100, aphro = TRUE) + if(genits.len) + to_chat(M, "You no longer feel aroused.") + ..() + +/datum/reagent/drug/anaphrodisiacplus + name = "Hexacamphor" + description = "Chemically condensed camphor. Causes an extreme reduction in libido and a permanent one if overdosed. Non-addictive." + taste_description = "tranquil celibacy" + color = "#D9D9D9"//rgb(217, 217, 217) + reagent_state = SOLID + overdose_threshold = 20 + can_synth = FALSE + +/datum/reagent/drug/anaphrodisiacplus/on_mob_life(mob/living/M) + if(M && M.client?.prefs.arousable) + REMOVE_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/list/genits = H.adjust_arousal(-100, aphro = TRUE) + if(genits.len) + to_chat(M, "You no longer feel aroused.") + + ..() + +/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M) + if(M && M.client?.prefs.arousable && prob(5)) + to_chat(M, "You feel like you'll never feel aroused again...") + ADD_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT) + ..() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 5fb27bd074..d3ac8fa506 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1735,6 +1735,22 @@ H.facial_hair_style = "Very Long Beard" H.update_hair() +/datum/reagent/baldium + name = "Baldium" + description = "A major cause of hair loss across the world." + reagent_state = LIQUID + color = "#ecb2cf" + taste_description = "bitterness" + +/datum/reagent/baldium/reaction_mob(mob/living/M, method=TOUCH, reac_volume) + if(method == TOUCH || method == VAPOR) + if(M && ishuman(M)) + var/mob/living/carbon/human/H = M + to_chat(H, "Your hair is falling out in clumps!") + H.hair_style = "Bald" + H.facial_hair_style = "Shaved" + H.update_hair() + /datum/reagent/saltpetre name = "Saltpetre" description = "Volatile. Controversial. Third Thing." @@ -2178,3 +2194,93 @@ reagent_state = LIQUID color = "#f7685e" metabolization_rate = REAGENTS_METABOLISM * 0.25 + + +//body bluids +/datum/reagent/consumable/semen + name = "Semen" + description = "Sperm from some animal. Useless for anything but insemination, really." + taste_description = "something salty" + taste_mult = 2 //Not very overpowering flavor + data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null) + reagent_state = LIQUID + color = "#FFFFFF" // rgb: 255, 255, 255 + can_synth = FALSE + nutriment_factor = 0.5 * REAGENTS_METABOLISM + +/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume) + if(!istype(T)) + return + if(reac_volume < 10) + return + + var/obj/effect/decal/cleanable/semen/S = locate() in T + if(!S) + S = new(T) + if(data["blood_DNA"]) + S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) + +/obj/effect/decal/cleanable/semen + name = "semen" + desc = null + gender = PLURAL + density = 0 + layer = ABOVE_NORMAL_TURF_LAYER + icon = 'icons/obj/genitals/effects.dmi' + icon_state = "semen1" + random_icon_states = list("semen1", "semen2", "semen3", "semen4") + +/obj/effect/decal/cleanable/semen/Initialize(mapload) + . = ..() + dir = GLOB.cardinals + add_blood_DNA(list("Non-human DNA" = "A+")) + +/obj/effect/decal/cleanable/semen/replace_decal(obj/effect/decal/cleanable/semen/S) + if(S.blood_DNA) + blood_DNA |= S.blood_DNA + return ..() + +/datum/reagent/consumable/femcum + name = "Female Ejaculate" + description = "Vaginal lubricant found in most mammals and other animals of similar nature. Where you found this is your own business." + taste_description = "something with a tang" // wew coders who haven't eaten out a girl. + taste_mult = 2 + data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null) + reagent_state = LIQUID + color = "#AAAAAA77" + can_synth = FALSE + nutriment_factor = 0.5 * REAGENTS_METABOLISM + +/obj/effect/decal/cleanable/femcum + name = "female ejaculate" + desc = null + gender = PLURAL + density = 0 + layer = ABOVE_NORMAL_TURF_LAYER + icon = 'icons/obj/genitals/effects.dmi' + icon_state = "fem1" + random_icon_states = list("fem1", "fem2", "fem3", "fem4") + blood_state = null + bloodiness = null + +/obj/effect/decal/cleanable/femcum/Initialize(mapload) + . = ..() + dir = GLOB.cardinals + add_blood_DNA(list("Non-human DNA" = "A+")) + +/obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F) + if(F.blood_DNA) + blood_DNA |= F.blood_DNA + return ..() + +/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume) + if(!istype(T)) + return + if(reac_volume < 10) + return + + var/obj/effect/decal/cleanable/femcum/S = locate() in T + if(!S) + S = new(T) + if(data["blood_DNA"]) + S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 3ba883a2c7..02e4a89e1d 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -1019,3 +1019,20 @@ to_chat(M, "[tox_message]") . = 1 ..() + +/datum/reagent/toxin/leadacetate + name = "Lead Acetate" + description = "Used hundreds of years ago as a sweetener, before it was realized that it's incredibly poisonous." + reagent_state = SOLID + color = "#2b2b2b" // rgb: 127, 132, 0 + toxpwr = 0.5 + taste_mult = 1.3 + taste_description = "sugary sweetness" + +/datum/reagent/toxin/leadacetate/on_mob_life(mob/living/carbon/M) + M.adjustOrganLoss(ORGAN_SLOT_EARS,1) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN,1) + if(prob(1)) + to_chat(M, "Ah, what was that? You thought you heard something...") + M.confused += 5 + return ..() diff --git a/code/modules/reagents/chemistry/recipes/drugs.dm b/code/modules/reagents/chemistry/recipes/drugs.dm index 468d29c052..a2b8c27552 100644 --- a/code/modules/reagents/chemistry/recipes/drugs.dm +++ b/code/modules/reagents/chemistry/recipes/drugs.dm @@ -62,3 +62,34 @@ results = list(/datum/reagent/moonsugar = 1, /datum/reagent/medicine/morphine = 2.5) required_temp = 315 //a little above normal body temperature required_reagents = list(/datum/reagent/drug/skooma = 1) +/datum/chemical_reaction/aphro + name = "crocin" + id = /datum/reagent/drug/aphrodisiac + results = list(/datum/reagent/drug/aphrodisiac = 6) + required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/oxygen = 2, /datum/reagent/water = 1) + required_temp = 400 + mix_message = "The mixture boils off a pink vapor..."//The water boils off, leaving the crocin + +/datum/chemical_reaction/aphroplus + name = "hexacrocin" + id = /datum/reagent/drug/aphrodisiacplus + results = list(/datum/reagent/drug/aphrodisiacplus = 1) + required_reagents = list(/datum/reagent/drug/aphrodisiac = 6, /datum/reagent/phenol = 1) + required_temp = 400 + mix_message = "The mixture rapidly condenses and darkens in color..." + +/datum/chemical_reaction/anaphro + name = "camphor" + id = /datum/reagent/drug/anaphrodisiac + results = list(/datum/reagent/drug/anaphrodisiac = 6) + required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/oxygen = 2, /datum/reagent/sulfur = 1) + required_temp = 400 + mix_message = "The mixture boils off a yellow, smelly vapor..."//Sulfur burns off, leaving the camphor + +/datum/chemical_reaction/anaphroplus + name = "pentacamphor" + id = /datum/reagent/drug/anaphrodisiacplus + results = list(/datum/reagent/drug/anaphrodisiacplus = 1) + required_reagents = list(/datum/reagent/drug/aphrodisiac = 5, /datum/reagent/acetone = 1) + required_temp = 300 + mix_message = "The mixture thickens and heats up slighty..." diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index 618ac256e2..df1b57c20b 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -631,6 +631,11 @@ results = list(/datum/reagent/concentrated_barbers_aid = 2) required_reagents = list(/datum/reagent/barbers_aid = 1, /datum/reagent/toxin/mutagen = 1) +/datum/chemical_reaction/baldium + results = list(/datum/reagent/baldium = 1) + required_reagents = list(/datum/reagent/radium = 1, /datum/reagent/toxin/acid = 1, /datum/reagent/lye = 1) + required_temp = 395 + /datum/chemical_reaction/saltpetre name = "saltpetre" id = /datum/reagent/saltpetre diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index b4e954f147..549f4eb48c 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -351,7 +351,7 @@ name = "wooden bucket" desc = "It's a bucket made of wood." icon_state = "bucket_wooden" - custom_materials = null + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 2) slot_flags = NONE item_flags = NO_MAT_REDEMPTION diff --git a/code/modules/reagents/reagent_containers/maunamug.dm b/code/modules/reagents/reagent_containers/maunamug.dm new file mode 100644 index 0000000000..18e6cfa847 --- /dev/null +++ b/code/modules/reagents/reagent_containers/maunamug.dm @@ -0,0 +1,117 @@ +/obj/item/reagent_containers/glass/maunamug + name = "mauna mug" + desc = "A drink served in a classy mug. Now with built-in heating!" + icon = 'icons/obj/mauna_mug.dmi' + icon_state = "maunamug" + spillable = TRUE + reagent_flags = OPENCONTAINER +// fill_icon_state = "maunafilling" +// fill_icon_thresholds = list(25) + var/obj/item/stock_parts/cell/cell + var/open = FALSE + var/on = FALSE + +/obj/item/reagent_containers/glass/maunamug/Initialize(mapload, vol) + . = ..() + cell = new /obj/item/stock_parts/cell(src) + +/obj/item/reagent_containers/glass/maunamug/examine(mob/user) + . = ..() + . += "The status display reads: Current temperature: [reagents.chem_temp]K Current Charge:[cell ? "[cell.charge / cell.maxcharge * 100]%" : "No cell found"]." + if(open) + . += "The battery case is open." + +/obj/item/reagent_containers/glass/maunamug/update_overlays() + . = ..() + if(reagents.total_volume >= 25) + . += mutable_appearance('icons/obj/reagentfillings.dmi', "maunafilling25", color = mix_color_from_reagents(reagents.reagent_list)) + +/obj/item/reagent_containers/glass/maunamug/process() + ..() + if(on && (!cell || cell.charge <= 0)) //Check if we ran out of power + change_power_status(FALSE) + return FALSE + cell.use(10) //Basic cell goes for like 200 seconds, bluespace for 8000 + if(!reagents.total_volume) + return FALSE + var/max_temp = min(500 + (500 * (0.2 * cell.rating)), 1000) // 373 to 1000 + reagents.adjust_thermal_energy(0.8 * cell.maxcharge * reagents.total_volume, max_temp = max_temp) // 4 kelvin every tick on a basic cell. 160k on bluespace + reagents.handle_reactions() + update_icon() + if(reagents.chem_temp >= max_temp) + change_power_status(FALSE) + audible_message("The Mauna Mug lets out a happy beep and turns off!") + playsound(src, 'sound/machines/chime.ogg', 50) + +/obj/item/reagent_containers/glass/maunamug/Destroy() + if(cell) + QDEL_NULL(cell) + STOP_PROCESSING(SSobj, src) + . = ..() + + +/obj/item/reagent_containers/glass/maunamug/attack_self(mob/user) + if(on) + change_power_status(FALSE) + else + if(!cell || cell.charge <= 0) + return FALSE //No power, so don't turn on + change_power_status(TRUE) + +/obj/item/reagent_containers/glass/maunamug/proc/change_power_status(status) + on = status + if(on) + START_PROCESSING(SSobj, src) + else + STOP_PROCESSING(SSobj, src) + update_icon() + +/obj/item/reagent_containers/glass/maunamug/screwdriver_act(mob/living/user, obj/item/I) + . = ..() + open = !open + to_chat(user, "You screw the battery case on [src] [open ? "open" : "closed"] .") + update_icon() + +/obj/item/reagent_containers/glass/maunamug/attackby(obj/item/I, mob/user, params) + add_fingerprint(user) + if(!istype(I, /obj/item/stock_parts/cell)) + return ..() + if(!open) + to_chat(user, "The battery case must be open to insert a power cell!") + return FALSE + if(cell) + to_chat(user, "There is already a power cell inside!") + return FALSE + else if(!user.transferItemToLoc(I, src)) + return + cell = I + user.visible_message("[user] inserts a power cell into [src].", "You insert the power cell into [src].") + update_icon() + +/obj/item/reagent_containers/glass/maunamug/attack_hand(mob/living/user) + if(cell && open) + cell.update_icon() + user.put_in_hands(cell) + cell = null + to_chat(user, "You remove the power cell from [src].") + on = FALSE + update_icon() + return TRUE + return ..() + +/obj/item/reagent_containers/glass/maunamug/update_icon() + ..() + if(open) + if(cell) + icon_state = "maunamug_bat" + else + icon_state = "maunamug_no_bat" + else if(on) + icon_state = "maunamug_on" + else + icon_state = "maunamug" + if(reagents.total_volume && reagents.chem_temp >= 400) + var/intensity = (reagents.chem_temp - 400) * 1 / 600 //Get the opacity of the incandescent overlay. Ranging from 400 to 1000 + var/mutable_appearance/mug_glow = mutable_appearance(icon, "maunamug_incand") + mug_glow.alpha = 255 * intensity + add_overlay(mug_glow) diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index 36e3b0d47e..1247a7abc3 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -22,10 +22,17 @@ if(reagents.total_volume && roundstart) name += " ([reagents.total_volume]u)" - /obj/item/reagent_containers/pill/attack_self(mob/user) return +/obj/item/reagent_containers/pill/get_w_volume() + switch(reagents.total_volume) + if(0 to 9.5) + return 1 + if(9.5 to 25) + return DEFAULT_VOLUME_TINY + else + return DEFAULT_VOLUME_SMALL /obj/item/reagent_containers/pill/attack(mob/M, mob/user, def_zone) if(!canconsume(M, user)) @@ -137,14 +144,14 @@ name = "mannitol pill" desc = "Used to treat brain damage." icon_state = "pill17" - list_reagents = list(/datum/reagent/medicine/mannitol = 50) + list_reagents = list(/datum/reagent/medicine/mannitol = 25) roundstart = 1 /obj/item/reagent_containers/pill/mutadone name = "mutadone pill" desc = "Used to treat genetic damage." icon_state = "pill20" - list_reagents = list(/datum/reagent/medicine/mutadone = 50) + list_reagents = list(/datum/reagent/medicine/mutadone = 25) roundstart = 1 /obj/item/reagent_containers/pill/salicyclic @@ -186,14 +193,14 @@ name = "prussian blue pill" desc = "Used to treat heavy radition poisoning." icon_state = "prussian_blue" - list_reagents = list(/datum/reagent/medicine/prussian_blue = 25, /datum/reagent/water = 10) + list_reagents = list(/datum/reagent/medicine/prussian_blue = 25) roundstart = 1 /obj/item/reagent_containers/pill/mutarad name = "radiation treatment deluxe pill" desc = "Used to treat heavy radition poisoning and genetic defects." icon_state = "anit_rad_fixgene" - list_reagents = list(/datum/reagent/medicine/prussian_blue = 15, /datum/reagent/medicine/potass_iodide = 15, /datum/reagent/medicine/mutadone = 15, /datum/reagent/water = 5) + list_reagents = list(/datum/reagent/medicine/prussian_blue = 10, /datum/reagent/medicine/potass_iodide = 10, /datum/reagent/medicine/mutadone = 5) roundstart = 1 ///////////////////////////////////////// this pill is used only in a legion mob drop @@ -216,7 +223,7 @@ /obj/item/reagent_containers/pill/lsd name = "hallucinogen pill" - list_reagents = list(/datum/reagent/drug/mushroomhallucinogen = 15, /datum/reagent/toxin/mindbreaker = 15) + list_reagents = list(/datum/reagent/drug/mushroomhallucinogen = 12.5, /datum/reagent/toxin/mindbreaker = 12.5) /obj/item/reagent_containers/pill/aranesp diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 9ef08590a8..bc4e214161 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -241,12 +241,6 @@ icon_state = "whitekeg" reagent_id = /datum/reagent/consumable/milk -/obj/structure/reagent_dispensers/keg/semen - name = "keg of semen" - desc = "Dear lord, where did this even come from?" - icon_state = "whitekeg" - reagent_id = /datum/reagent/consumable/semen - /obj/structure/reagent_dispensers/keg/gargle name = "keg of pan galactic gargleblaster" desc = "A keg of... wow that's a long name." diff --git a/code/modules/research/bepis.dm b/code/modules/research/bepis.dm new file mode 100644 index 0000000000..c6ce45f160 --- /dev/null +++ b/code/modules/research/bepis.dm @@ -0,0 +1,270 @@ +//This system is designed to act as an in-between for cargo and science, and the first major money sink in the game outside of just buying things from cargo (As of 10/9/19, anyway). + +//economics defined values, subject to change should anything be too high or low in practice. + +#define MACHINE_OPERATION 100000 +#define MACHINE_OVERLOAD 500000 +#define MAJOR_THRESHOLD 5500 +#define MINOR_THRESHOLD 3500 +#define STANDARD_DEVIATION 1000 + +/obj/machinery/rnd/bepis + name = "\improper B.E.P.I.S. Chamber" + desc = "A high fidelity testing device which unlocks the secrets of the known universe using the two most powerful substances available to man: excessive amounts of electricity and capital." + icon = 'icons/obj/machines/bepis.dmi' + icon_state = "chamber" + density = TRUE + layer = ABOVE_MOB_LAYER + use_power = IDLE_POWER_USE + active_power_usage = 1500 + circuit = /obj/item/circuitboard/machine/bepis + + var/banking_amount = 100 + var/banked_cash = 0 //stored player cash + var/datum/bank_account/account //payer's account. + var/account_name //name of the payer's account. + var/error_cause = null + //Vars related to probability and chance of success for testing + var/major_threshold = MAJOR_THRESHOLD + var/minor_threshold = MINOR_THRESHOLD + var/std = STANDARD_DEVIATION //That's Standard Deviation, what did you think it was? + //Stock part variables + var/power_saver = 1 + var/inaccuracy_percentage = 1.5 + var/positive_cash_offset = 0 + var/negative_cash_offset = 0 + var/minor_rewards = list(/obj/item/stack/circuit_stack/full, //To add a new minor reward, add it here. + /obj/item/airlock_painter/decal, + /obj/item/pen/survival, + /obj/item/circuitboard/machine/sleeper/party, + /obj/item/toy/sprayoncan) + var/static/list/item_list = list() + +/obj/machinery/rnd/bepis/attackby(obj/item/O, mob/user, params) + if(default_deconstruction_screwdriver(user, "chamber_open", "chamber", O)) + update_icon_state() + return + if(default_deconstruction_crowbar(O)) + return + if(!is_operational()) + to_chat(user, "[src] can't accept money when it's not functioning.") + return + if(istype(O, /obj/item/holochip) || istype(O, /obj/item/stack/spacecash)) + var/deposit_value = O.get_item_credit_value() + banked_cash += deposit_value + qdel(O) + say("Deposited [deposit_value] credits into storage.") + update_icon_state() + return + if(istype(O, /obj/item/card/id)) + var/obj/item/card/id/Card = O + if(Card.registered_account) + account = Card.registered_account + account_name = Card.registered_name + say("New account detected. Console Updated.") + else + say("No account detected on card. Aborting.") + return + return ..() + +/obj/machinery/rnd/bepis/RefreshParts() + var/C = 0 + var/M = 0 + var/L = 0 + var/S = 0 + for(var/obj/item/stock_parts/capacitor/Cap in component_parts) + C += ((Cap.rating - 1) * 0.1) + power_saver = 1 - C + for(var/obj/item/stock_parts/manipulator/Manip in component_parts) + M += ((Manip.rating - 1) * 250) + positive_cash_offset = M + for(var/obj/item/stock_parts/micro_laser/Laser in component_parts) + L += ((Laser.rating - 1) * 250) + negative_cash_offset = L + for(var/obj/item/stock_parts/scanning_module/Scan in component_parts) + S += ((Scan.rating - 1) * 0.25) + inaccuracy_percentage = (1.5 - S) + +/obj/machinery/rnd/bepis/proc/depositcash() + var/deposit_value = 0 + deposit_value = banking_amount + if(deposit_value == 0) + update_icon_state() + say("Attempting to deposit 0 credits. Aborting.") + return + deposit_value = clamp(round(deposit_value, 1), 1, 15000) + if(!account) + say("Cannot find user account. Please swipe a valid ID.") + return + if(!account.has_money(deposit_value)) + say("You do not possess enough credits.") + return + account.adjust_money(-deposit_value) //The money vanishes, not paid to any accounts. + SSblackbox.record_feedback("amount", "BEPIS_credits_spent", deposit_value) + banked_cash += deposit_value + use_power(1000 * power_saver) + say("Cash deposit successful. There is [banked_cash] in the chamber.") + update_icon_state() + return + +/obj/machinery/rnd/bepis/proc/withdrawcash() + var/withdraw_value = 0 + withdraw_value = banking_amount + if(withdraw_value > banked_cash) + say("Cannot withdraw more than stored funds. Aborting.") + else + banked_cash -= withdraw_value + new /obj/item/holochip(src.loc, withdraw_value) + say("Withdrawing [withdraw_value] credits from the chamber.") + update_icon_state() + return + +/obj/machinery/rnd/bepis/proc/calcsuccess() + var/turf/dropturf = null + var/gauss_major = 0 + var/gauss_minor = 0 + var/gauss_real = 0 + var/list/turfs = block(locate(x-1,y-1,z),locate(x+1,y+1,z)) //NO MORE DISCS IN WINDOWS + while(length(turfs)) + var/turf/T = pick_n_take(turfs) + if(is_blocked_turf(T, exclude_mobs=TRUE)) + continue + else + dropturf = T + break + if (!dropturf) + dropturf = drop_location() + gauss_major = (gaussian(major_threshold, std) - negative_cash_offset) //This is the randomized profit value that this experiment has to surpass to unlock a tech. + gauss_minor = (gaussian(minor_threshold, std) - negative_cash_offset) //And this is the threshold to instead get a minor prize. + gauss_real = (gaussian(banked_cash, std*inaccuracy_percentage) + positive_cash_offset) //this is the randomized profit value that your experiment expects to give. + say("Real: [gauss_real]. Minor: [gauss_minor]. Major: [gauss_major].") + flick("chamber_flash",src) + update_icon_state() + banked_cash = 0 + if((gauss_real >= gauss_major) && (SSresearch.techweb_nodes_experimental.len > 0)) //Major Success. + say("Experiment concluded with major success. New technology node discovered on technology disc.") + new /obj/item/disk/tech_disk/major(dropturf,1) + if(SSresearch.techweb_nodes_experimental.len == 0) + say("Expended all available experimental technology nodes. Resorting to minor rewards.") + return + if(gauss_real >= gauss_minor) //Minor Success. + var/reward = pick(minor_rewards) + new reward(dropturf) + say("Experiment concluded with partial success. Dispensing compiled research efforts.") + return + if(gauss_real <= -1) //Critical Failure + say("ERROR: CRITICAL MACHIME MALFUNCTI- ON. CURRENCY IS NOT CRASH. CANNOT COMPUTE COMMAND: 'make bucks'") //not a typo, for once. + new /mob/living/simple_animal/deer(dropturf, 1) + use_power(MACHINE_OVERLOAD * power_saver) //To prevent gambling at low cost and also prevent spamming for infinite deer. + return + //Minor Failure + error_cause = pick("attempted to sell grey products to American dominated market.","attempted to sell gray products to British dominated market.","placed wild assumption that PDAs would go out of style.","simulated product #76 damaged brand reputation mortally.","simulated business model resembled 'pyramid scheme' by 98.7%.","product accidently granted override access to all station doors.") + say("Experiment concluded with zero product viability. Cause of error: [error_cause]") + return + +/obj/machinery/rnd/bepis/update_icon_state() + if(panel_open == TRUE) + icon_state = "chamber_open" + return + if((use_power == ACTIVE_POWER_USE) && (banked_cash > 0) && (is_operational())) + icon_state = "chamber_active_loaded" + return + if (((use_power == IDLE_POWER_USE) && (banked_cash > 0)) || (banked_cash > 0) && (!is_operational())) + icon_state = "chamber_loaded" + return + if(use_power == ACTIVE_POWER_USE && is_operational()) + icon_state = "chamber_active" + return + if(((use_power == IDLE_POWER_USE) && (banked_cash == 0)) || (!is_operational())) + icon_state = "chamber" + return + +/obj/machinery/rnd/bepis/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "bepis", name, 500, 480, master_ui, state) + ui.open() + RefreshParts() + +/obj/machinery/rnd/bepis/ui_data(mob/user) + var/list/data = list() + var/powered = FALSE + var/zvalue = (banked_cash - (major_threshold - positive_cash_offset - negative_cash_offset))/(std) + var/std_success = 0 + var/prob_success = 0 + //Admittedly this is messy, but not nearly as messy as the alternative, which is jury-rigging an entire Z-table into the code, or making an adaptive z-table. + var/z = abs(zvalue) + if(z > 0 && z <= 0.5) + std_success = 19.1 + else if(z > 0.5 && z <= 1.0) + std_success = 34.1 + else if(z > 1.0 && z <= 1.5) + std_success = 43.3 + else if(z > 1.5 && z <= 2.0) + std_success = 47.7 + else if(z > 2.0 && z <= 2.5) + std_success = 49.4 + else + std_success = 50 + if(zvalue > 0) + prob_success = 50 + std_success + else if(zvalue == 0) + prob_success = 50 + else + prob_success = 50 - std_success + + if(use_power == ACTIVE_POWER_USE) + powered = TRUE + data["account_owner"] = account_name + data["amount"] = banking_amount + data["stored_cash"] = banked_cash + data["mean_value"] = (major_threshold - positive_cash_offset - negative_cash_offset) + data["error_name"] = error_cause + data["power_saver"] = power_saver + data["accuracy_percentage"] = inaccuracy_percentage * 100 + data["positive_cash_offset"] = positive_cash_offset + data["negative_cash_offset"] = negative_cash_offset + data["manual_power"] = powered ? FALSE : TRUE + data["silicon_check"] = issilicon(user) + data["success_estimate"] = prob_success + return data + +/obj/machinery/rnd/bepis/ui_act(action,params) + if(..()) + return + switch(action) + if("deposit_cash") + if(use_power == IDLE_POWER_USE) + return + depositcash() + if("withdraw_cash") + if(use_power == IDLE_POWER_USE) + return + withdrawcash() + if("begin_experiment") + if(use_power == IDLE_POWER_USE) + return + if(banked_cash == 0) + say("Please deposit funds to begin testing.") + return + calcsuccess() + use_power(MACHINE_OPERATION * power_saver) //This thing should eat your APC battery if you're not careful. + use_power = IDLE_POWER_USE //Machine shuts off after use to prevent spam and look better visually. + update_icon_state() + if("amount") + var/input = text2num(params["amount"]) + if(input) + banking_amount = input + if("toggle_power") + if(use_power == ACTIVE_POWER_USE) + use_power = IDLE_POWER_USE + else + use_power = ACTIVE_POWER_USE + update_icon_state() + if("account_reset") + if(use_power == IDLE_POWER_USE) + return + account_name = "" + account = null + say("Account settings reset.") + . = TRUE diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm index 20a5370793..9cbef4abdd 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm @@ -10,6 +10,7 @@ id = "beanbag_slug" build_type = AUTOLATHE materials = list(/datum/material/iron = 250) + materials = list(/datum/material/iron = 1000) build_path = /obj/item/ammo_casing/shotgun/beanbag category = list("initial", "Security") @@ -73,12 +74,12 @@ build_path = /obj/item/restraints/handcuffs category = list("hacked", "Security") -/datum/design/receiver - name = "Modular Receiver" - id = "receiver" - build_type = AUTOLATHE | NO_PUBLIC_LATHE - materials = list(/datum/material/iron = 15000) - build_path = /obj/item/weaponcrafting/receiver +/datum/design/rifle_receiver + name = "Rifle Receiver" + id = "rifle_receiver" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 40000) + build_path = /obj/item/weaponcrafting/improvised_parts/rifle_receiver category = list("hacked", "Security") /datum/design/shotgun_slug @@ -113,6 +114,10 @@ build_path = /obj/item/ammo_casing/shotgun/incendiary category = list("hacked", "Security") +///////////////// +// Bullets // +///////////////// + /datum/design/riot_dart name = "Foam Riot Dart" id = "riot_dart" diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_tcomms_and_misc.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_tcomms_and_misc.dm index eebeec2c78..ea73df568f 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_tcomms_and_misc.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_tcomms_and_misc.dm @@ -271,4 +271,13 @@ build_type = AUTOLATHE materials = list(/datum/material/iron = 5000, /datum/material/glass = 2000) build_path = /obj/item/vending_refill/custom - category = list("initial", "Misc") \ No newline at end of file + category = list("initial", "Misc") + +/datum/design/trigger_assembly + name = "Trigger Assembly" + id = "trigger_assembly" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 6500, /datum/material/glass = 50) + build_path = /obj/item/weaponcrafting/improvised_parts/trigger_assembly + category = list("initial", "Misc") + diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm index 330dfb8f8a..516c91d426 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm @@ -157,3 +157,11 @@ materials = list(/datum/material/iron = 150, /datum/material/glass = 150) build_path = /obj/item/geiger_counter category = list("initial", "Tools") + +/datum/design/saw + name = "Hand Saw" + id = "handsaw" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 500) + build_path = /obj/item/hatchet/saw + category = list("initial", "Tools") diff --git a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm index 95e5a66099..d12099f7ff 100644 --- a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm +++ b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm @@ -122,3 +122,11 @@ build_path = /obj/item/circuitboard/machine/autolathe/toy departmental_flags = DEPARTMENTAL_FLAG_ALL category = list("Misc. Machinery") + +/datum/design/board/hypnochair + name = "Machine Design (Enhanced Interrogation Chamber)" + desc = "Allows for the construction of circuit boards used to build an Enhanced Interrogation Chamber." + id = "hypnochair" + departmental_flags = DEPARTMENTAL_FLAG_SECURITY + build_path = /obj/item/circuitboard/machine/hypnochair + category = list("Misc. Machinery") diff --git a/code/modules/research/designs/machine_desings/machine_designs_sci.dm b/code/modules/research/designs/machine_desings/machine_designs_sci.dm index 183977b455..59fae9d09b 100644 --- a/code/modules/research/designs/machine_desings/machine_designs_sci.dm +++ b/code/modules/research/designs/machine_desings/machine_designs_sci.dm @@ -66,6 +66,14 @@ category = list("Research Machinery") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE +/datum/design/board/bepis + name = "Machine Design (B.E.P.I.S. Board)" + desc = "The circuit board for a B.E.P.I.S." + id = "bepis" + build_path = /obj/item/circuitboard/machine/bepis + category = list("Research Machinery") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE + /datum/design/board/protolathe name = "Machine Design (Protolathe Board)" desc = "The circuit board for a protolathe." diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index e407277ebf..e9af465c8a 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -206,6 +206,35 @@ category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING +/datum/design/bright_helmet + name = "Workplace-Ready Firefighter Helmet" + desc = "By applying state of the art lighting technology to a fire helmet with industry standard photo-chemical hardening methods, this hardhat will protect you from robust workplace hazards." + id = "bright_helmet" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 4000, /datum/material/glass = 1000, /datum/material/plastic = 3000, /datum/material/silver = 500) + build_path = /obj/item/clothing/head/hardhat/red/upgraded + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_CARGO + +/datum/design/mauna_mug + name = "Mauna Mug" + desc = "This awesome mug will ensure your coffee never stays cold!" + id = "mauna_mug" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 100) + build_path = /obj/item/reagent_containers/glass/maunamug + category = list("Equipment") + +/datum/design/rolling_table + name = "Rolly poly" + desc = "We duct-taped some wheels to the bottom of a table. It's goddamn science alright?" + id = "rolling_table" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 4000) + build_path = /obj/structure/table/rolling + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ALL + /datum/design/portaseeder name = "Portable Seed Extractor" desc = "For the enterprising botanist on the go. Less efficient than the stationary model, it creates one seed per plant." @@ -285,6 +314,25 @@ build_path = /obj/item/vending_refill/donksoft category = list("Equipment") +/datum/design/eng_gloves + name = "Tinkers Gloves" + desc = "Overdesigned engineering gloves that have automated construction subroutines dialed in, allowing for faster construction while worn." + id = "eng_gloves" + build_type = PROTOLATHE + materials = list(/datum/material/iron=2000, /datum/material/silver=1500, /datum/material/gold = 1000) + build_path = /obj/item/clothing/gloves/color/latex/engineering + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/lavarods + name = "Lava-Resistant Metal Rods" + id = "lava_rods" + build_type = PROTOLATHE + materials = list(/datum/material/iron=1000, /datum/material/plasma=500, /datum/material/titanium=2000) + build_path = /obj/item/stack/rods/lava + category = list("initial", "Stock Parts") + departmental_flags = DEPARTMENTAL_FLAG_CARGO | DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + ///////////////////////////////////////// ////////////Janitor Designs////////////// ///////////////////////////////////////// diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm index 2d938bc38c..e500166e76 100644 --- a/code/modules/research/designs/tool_designs.dm +++ b/code/modules/research/designs/tool_designs.dm @@ -72,6 +72,16 @@ category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING +/datum/design/rld_mini + name = "Mini Rapid Light Device (MRLD)" + desc = "A tool that can portable and standing lighting orbs and glowsticks." + id = "rld_mini" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 20000, /datum/material/glass = 10000, /datum/material/plastic = 8000, /datum/material/gold = 2000) + build_path = /obj/item/construction/rld/mini + category = list("Tool Designs") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_CARGO + ///////////////////////////////////////// //////////////Alien Tools//////////////// ///////////////////////////////////////// diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 07679fe1ce..8c934d39a9 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -234,13 +234,13 @@ category = list("Firing Pins") departmental_flags = DEPARTMENTAL_FLAG_SECURITY -/datum/design/pin_away - name = "Station Locked Pin" - desc = "This is a security firing pin which only authorizes users who are off station." - id = "pin_away" +/datum/design/pin_explorer + name = "Outback Firing Pin" + desc = "This firing pin only shoots while ya ain't on station, fair dinkum!" + id = "pin_explorer" build_type = PROTOLATHE - materials = list(/datum/material/iron = 1500, /datum/material/glass = 2000) - build_path = /obj/item/firing_pin/away + materials = list(/datum/material/silver = 1000, /datum/material/gold = 1000, /datum/material/iron = 500) + build_path = /obj/item/firing_pin/explorer category = list("Firing Pins") departmental_flags = DEPARTMENTAL_FLAG_SECURITY @@ -500,3 +500,13 @@ materials = list(MAT_CATEGORY_RIGID = 12000) build_path = /obj/item/melee/cleric_mace category = list("Imported") + +/datum/design/stun_boomerang + name = "OZtek Boomerang" + desc = "Uses reverse flow gravitodynamics to flip its personal gravity back to the thrower mid-flight. Also functions similar to a stun baton." + id = "stun_boomerang" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 10000, /datum/material/glass = 4000, /datum/material/silver = 10000, /datum/material/gold = 2000) + build_path = /obj/item/melee/baton/boomerang + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY diff --git a/code/modules/research/research_disk.dm b/code/modules/research/research_disk.dm index aa781ca06b..a656093d98 100644 --- a/code/modules/research/research_disk.dm +++ b/code/modules/research/research_disk.dm @@ -21,6 +21,16 @@ . = ..() stored_research = new /datum/techweb/admin +/obj/item/disk/tech_disk/major + name = "Reformatted technology disk" + desc = "A disk containing a new, completed tech from the B.E.P.I.S. Upload the disk to an R&D Console to redeem the tech." + icon_state = "rndmajordisk" + custom_materials = list(/datum/material/iron=300, /datum/material/glass=100) + +/obj/item/disk/tech_disk/major/Initialize() + . = ..() + stored_research = new /datum/techweb/bepis + /obj/item/disk/tech_disk/illegal name = "Illegal technology disk" desc = "A technology disk containing schematics for syndicate inspired equipment." diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index ccfcecf66c..503bd8bae7 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -63,6 +63,19 @@ id = "SCIENCE" organization = "Nanotrasen" +/datum/techweb/bepis //Should contain only 1 BEPIS tech selected at random. + id = "EXPERIMENTAL" + organization = "Nanotrasen R&D" + +/datum/techweb/bepis/New() + . = ..() + var/bepis_id = pick(SSresearch.techweb_nodes_experimental) //To add a new tech to the BEPIS, add the ID to this pick list. + var/datum/techweb_node/BN = (SSresearch.techweb_node_by_id(bepis_id)) + hidden_nodes -= BN.id //Has to be removed from hidden nodes + research_node(BN, TRUE, FALSE, FALSE) + update_node_status(BN) + SSresearch.techweb_nodes_experimental -= bepis_id + /datum/techweb/Destroy() researched_nodes = null researched_designs = null @@ -126,17 +139,17 @@ modify_point_list(l) /datum/techweb/proc/copy_research_to(datum/techweb/receiver, unlock_hidden = TRUE) //Adds any missing research to theirs. + if(unlock_hidden) + for(var/i in receiver.hidden_nodes) + CHECK_TICK + if(!hidden_nodes[i]) + receiver.hidden_nodes -= i //We can see it so let them see it too. for(var/i in researched_nodes) CHECK_TICK receiver.research_node_id(i, TRUE, FALSE) for(var/i in researched_designs) CHECK_TICK receiver.add_design_by_id(i) - if(unlock_hidden) - for(var/i in receiver.hidden_nodes) - CHECK_TICK - if(!hidden_nodes[i]) - receiver.hidden_nodes -= i //We can see it so let them see it too. receiver.recalculate_nodes() /datum/techweb/proc/copy() diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm index 6750fa5475..40cc322eed 100644 --- a/code/modules/research/techweb/_techweb_node.dm +++ b/code/modules/research/techweb/_techweb_node.dm @@ -7,6 +7,7 @@ var/display_name = "Errored Node" var/description = "Why are you seeing this?" var/hidden = FALSE //Whether it starts off hidden. + var/experimental = FALSE //If the tech can be randomly granted by the BEPIS as a reward. Meant to be fully given in tech disks, not researched. var/starting_node = FALSE //Whether it's available without any research. var/list/prereq_ids = list() var/list/design_ids = list() @@ -102,6 +103,6 @@ description = "NT default research technologies." // Default research tech, prevents bricking design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", "desttagger", "handlabel", "packagewrap", - "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "paystand", + "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "bepis", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "paystand", "space_heater", "beaker", "large_beaker", "bucket", "xlarge_beaker", "sec_shellclip", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_islug", "sec_dart", "sec_38", "sec_38lethal", "rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass") diff --git a/code/modules/research/techweb/nodes/bepis_nodes.dm b/code/modules/research/techweb/nodes/bepis_nodes.dm new file mode 100644 index 0000000000..0033564274 --- /dev/null +++ b/code/modules/research/techweb/nodes/bepis_nodes.dm @@ -0,0 +1,82 @@ +////////////////////////B.E.P.I.S. Locked Techs//////////////////////// + +/datum/techweb_node/light_apps + id = "light_apps" + display_name = "Illumination Applications" + description = "Applications of lighting and vision technology not originally thought to be commercially viable." + prereq_ids = list("base") + design_ids = list("bright_helmet", "rld_mini") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/aus_security + id = "aus_security" + display_name = "Australicus Security Protocols" + description = "It is said that security in the Australicus sector is tight, so we took some pointers from their equipment. Thankfully, our sector lacks any signs of these, 'dropbears'." + prereq_ids = list("base") + design_ids = list("pin_explorer", "stun_boomerang") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/spec_eng + id = "spec_eng" + display_name = "Specialized Engineering" + description = "Conventional wisdom has deemed these engineering products 'technically' safe, but far too dangerous to traditionally condone." + prereq_ids = list("base") + design_ids = list("lava_rods", "eng_gloves") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/rolling_table + id = "rolling_table" + display_name = "Advanced Wheel Applications" + description = "Adding wheels to things can lead to extremely beneficial outcomes." + prereq_ids = list("base") + design_ids = list("rolling_table") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/Mauna_Mug + id = "mauna_mug" + display_name = "Mauna Mug" + description = "A bored scientist was thinking to himself for very long...and then realized his coffee got cold! He made this invention to solve this extreme problem." + prereq_ids = list("base") + design_ids = list("mauna_mug") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/nanite_replication_protocols + id = "nanite_replication_protocols" + display_name = "Nanite Replication Protocols" + description = "Advanced behaviours that allow nanites to exploit certain circumstances to replicate faster." + prereq_ids = list("nanite_smart") + design_ids = list("kickstart_nanites","factory_nanites","tinker_nanites","offline_nanites","synergy_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/interrogation + id = "interrogation" + display_name = "Enhanced Interrogation Technology" + description = "By cross-referencing several declassified documents from past dictatorial regimes, we were able to develop an incredibly effective interrogation device. \ + Ethical concerns about loss of free will may still apply, according to galactic law." + prereq_ids = list("base") + design_ids = list("hypnochair") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/tackle_advanced + id = "tackle_advanced" + display_name = "Advanced Grapple Technology" + description = "Nanotrasen would like to remind its researching staff that it is never acceptable to \"glomp\" your coworkers, and further \"scientific trials\" on the subject \ + will no longer be accepted in its academic journals." + design_ids = list("tackle_dolphin", "tackle_rocket") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE diff --git a/code/modules/research/techweb/nodes/nanites_nodes.dm b/code/modules/research/techweb/nodes/nanites_nodes.dm index 5fc707d77a..0a860c8938 100644 --- a/code/modules/research/techweb/nodes/nanites_nodes.dm +++ b/code/modules/research/techweb/nodes/nanites_nodes.dm @@ -74,11 +74,3 @@ prereq_ids = list("nanite_harmonic", "alientech") design_ids = list("spreading_nanites","mindcontrol_nanites","mitosis_nanites") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - -/datum/techweb_node/nanite_replication_protocols - id = "nanite_replication_protocols" - display_name = "Nanite Replication Protocols" - description = "Advanced behaviours that allow nanites to exploit certain circumstances to replicate faster." - prereq_ids = list("nanite_smart") - design_ids = list("kickstart_nanites","factory_nanites","tinker_nanites","offline_nanites","synergy_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) diff --git a/code/modules/research/techweb/nodes/weaponry_nodes.dm b/code/modules/research/techweb/nodes/weaponry_nodes.dm index 064f88077a..e17d7e1e7b 100644 --- a/code/modules/research/techweb/nodes/weaponry_nodes.dm +++ b/code/modules/research/techweb/nodes/weaponry_nodes.dm @@ -5,7 +5,7 @@ display_name = "Weapon Development Technology" description = "Our researchers have found new to weaponize just about everything now." prereq_ids = list("engineering") - design_ids = list("pin_testing", "tele_shield", "lasercarbine", "pin_away") + design_ids = list("pin_testing", "tele_shield", "lasercarbine") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) /datum/techweb_node/adv_weaponry diff --git a/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm new file mode 100644 index 0000000000..65530031c0 --- /dev/null +++ b/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm @@ -0,0 +1,247 @@ +//******Decoration objects +//***Bone statues and giant skeleton parts. +/obj/structure/statue/bone + anchored = TRUE + max_integrity = 120 + material_drop_type = /obj/item/stack/sheet/bone + impressiveness = 18 // Carved from the bones of a massive creature, it's going to be a specticle to say the least + layer = ABOVE_ALL_MOB_LAYER + +/obj/structure/statue/bone/rib + name = "collosal rib" + desc = "It's staggering to think that something this big could have lived, let alone died." + oreAmount = 4 + icon = 'icons/obj/statuelarge.dmi' + icon_state = "rib" + +/obj/structure/statue/bone/skull + name = "collosal skull" + desc = "The gaping maw of a dead, titanic monster." + oreAmount = 12 + icon = 'icons/obj/statuelarge.dmi' + icon_state = "skull" + +/obj/structure/statue/bone/skull/half + desc = "The gaping maw of a dead, titanic monster. This one is cracked in half." + oreAmount = 6 + icon = 'icons/obj/statuelarge.dmi' + icon_state = "skull-half" + +//***Wasteland floor and rock turfs here. +/turf/open/floor/plating/asteroid/basalt/wasteland //Like a more fun version of living in Arizona. + name = "cracked earth" + icon = 'icons/turf/floors.dmi' + icon_state = "wasteland" + environment_type = "wasteland" + baseturfs = /turf/open/floor/plating/asteroid/basalt/wasteland + digResult = /obj/item/stack/ore/glass/basalt + initial_gas_mix = LAVALAND_DEFAULT_ATMOS + slowdown = 0.5 + floor_variance = 30 + +/turf/open/floor/plating/asteroid/basalt/wasteland/Initialize() + .=..() + if(prob(floor_variance)) + icon_state = "[environment_type][rand(0,6)]" + +/turf/closed/mineral/strong/wasteland + name = "ancient dry rock" + color = "#B5651D" + environment_type = "wasteland" + turf_type = /turf/open/floor/plating/asteroid/basalt/wasteland + baseturfs = /turf/open/floor/plating/asteroid/basalt/wasteland + smooth_icon = 'icons/turf/walls/rock_wall.dmi' + +/turf/closed/mineral/strong/wasteland/drop_ores() + if(prob(10)) + new /obj/item/stack/ore/iron(src, 1) + new /obj/item/stack/ore/glass(src, 1) + new /obj/effect/decal/remains/human/grave(src, 1) + else + new /obj/item/stack/sheet/bone(src, 1) + +//***Oil well puddles. +/obj/structure/sink/oil_well //You're not going to enjoy bathing in this... + name = "oil well" + desc = "A bubbling pool of oil.This would probably be valuable, had bluespace technology not destroyed the need for fossil fuels 200 years ago." + icon = 'icons/obj/watercloset.dmi' + icon_state = "puddle-oil" + dispensedreagent = /datum/reagent/oil + +/obj/structure/sink/oil_well/Initialize() + .=..() + create_reagents(20) + reagents.add_reagent(dispensedreagent, 20) + +/obj/structure/sink/oil_well/attack_hand(mob/M) + flick("puddle-oil-splash",src) + reagents.reaction(M, TOUCH, 20) //Covers target in 20u of oil. + to_chat(M, "You touch the pool of oil, only to get oil all over yourself. It would be wise to wash this off with water.") + +/obj/structure/sink/oil_well/attackby(obj/item/O, mob/user, params) + flick("puddle-oil-splash",src) + if(O.tool_behaviour == TOOL_SHOVEL && !(flags_1&NODECONSTRUCT_1)) //attempt to deconstruct the puddle with a shovel + to_chat(user, "You fill in the oil well with soil.") + O.play_tool_sound(src) + deconstruct() + return 1 + if(istype(O, /obj/item/reagent_containers)) //Refilling bottles with oil + var/obj/item/reagent_containers/RG = O + if(RG.is_refillable()) + if(!RG.reagents.holder_full()) + RG.reagents.add_reagent(dispensedreagent, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) + to_chat(user, "You fill [RG] from [src].") + return TRUE + to_chat(user, "\The [RG] is full.") + return FALSE + if(user.a_intent != INTENT_HARM) + to_chat(user, "You won't have any luck getting \the [O] out if you drop it in the oil.") + return 1 + else + return ..() + +/obj/structure/sink/oil_well/drop_materials() + new /obj/effect/decal/cleanable/oil(loc) + +//***Grave mounds. +/obj/structure/closet/crate/grave + name = "burial mound" + desc = "An marked patch of soil, showing signs of a burial long ago. You wouldn't disturb a grave... right?" + icon = 'icons/obj/crates.dmi' + icon_state = "grave" + dense_when_open = TRUE + material_drop = /obj/item/stack/ore/glass/basalt + material_drop_amount = 5 + anchorable = FALSE + anchored = TRUE + locked = TRUE + breakout_time = 900 + cutting_tool = /obj/item/shovel + var/lead_tomb = FALSE + var/first_open = FALSE + +/obj/structure/closet/crate/grave/PopulateContents() //GRAVEROBBING IS NOW A FEATURE + ..() + new /obj/effect/decal/remains/human/grave(src) + switch(rand(1,8)) + if(1) + new /obj/item/coin/gold(src) + new /obj/item/storage/wallet(src) + if(2) + new /obj/item/clothing/glasses/meson(src) + if(3) + new /obj/item/coin/silver(src) + new /obj/item/shovel/spade(src) + if(4) + new /obj/item/storage/book/bible/booze(src) + if(5) + new /obj/item/clothing/neck/stethoscope(src) + new /obj/item/scalpel(src) + new /obj/item/hemostat(src) + + if(6) + new /obj/item/reagent_containers/glass/beaker(src) + new /obj/item/clothing/glasses/science(src) + if(7) + new /obj/item/clothing/glasses/sunglasses(src) + new /obj/item/clothing/mask/cigarette/rollie(src) + +/obj/structure/closet/crate/grave/open(mob/living/user, obj/item/S) + if(!opened) + to_chat(user, "The ground here is too hard to dig up with your bare hands. You'll need a shovel.") + else + to_chat(user, "The grave has already been dug up.") + +/obj/structure/closet/crate/grave/tool_interact(obj/item/S, mob/living/carbon/user) + if(user.a_intent == INTENT_HELP) //checks to attempt to dig the grave, must be done on help intent only. + if(!opened) + if(istype(S,cutting_tool) && S.tool_behaviour == TOOL_SHOVEL) + to_chat(user, "You start start to dig open \the [src] with \the [S]...") + if (do_after(user,20, target = src)) + opened = TRUE + locked = TRUE + dump_contents() + update_icon() + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "graverobbing", /datum/mood_event/graverobbing) + if(lead_tomb == TRUE && first_open == TRUE) + user.gain_trauma(/datum/brain_trauma/magic/stalker) + to_chat(user, "Oh no, no no no, THEY'RE EVERYWHERE! EVERY ONE OF THEM IS EVERYWHERE!") + first_open = FALSE + return 1 + return 1 + else + to_chat(user, "You can't dig up a grave with \the [S.name].") + return 1 + else + to_chat(user, "The grave has already been dug up.") + return 1 + + else if((user.a_intent != INTENT_HELP) && opened) //checks to attempt to remove the grave entirely. + if(istype(S,cutting_tool) && S.tool_behaviour == TOOL_SHOVEL) + to_chat(user, "You start to remove \the [src] with \the [S].") + if (do_after(user,15, target = src)) + to_chat(user, "You remove \the [src] completely.") + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "graverobbing", /datum/mood_event/graverobbing) + deconstruct(TRUE) + return 1 + return + +/obj/structure/closet/crate/grave/bust_open() + ..() + opened = TRUE + update_icon() + dump_contents() + return + +/obj/structure/closet/crate/grave/lead_researcher + name = "ominous burial mound" + desc = "Even in a place filled to the brim with graves, this one shows a level of preperation and planning that fills you with dread." + icon = 'icons/obj/crates.dmi' + icon_state = "grave_lead" + lead_tomb = TRUE + first_open = TRUE + +/obj/structure/closet/crate/grave/lead_researcher/PopulateContents() //ADVANCED GRAVEROBBING + ..() + new /obj/effect/decal/cleanable/blood/gibs/old(src) + new /obj/item/book/granter/crafting_recipe/boneyard_notes(src) + +/obj/effect/decal/remains/human/grave + turf_loc_check = FALSE + +/obj/item/book/granter/crafting_recipe/boneyard_notes + name = "The Complete Works of Lavaland Bone Architecture" + desc = "Pried from the lead Archaeologist's cold, dead hands, this seems to explain how ancient bone architecture was erected long ago." + crafting_recipe_types = list(/datum/crafting_recipe/rib, /datum/crafting_recipe/boneshovel, /datum/crafting_recipe/halfskull, /datum/crafting_recipe/skull) + icon = 'icons/obj/library.dmi' + icon_state = "boneworking_learing" + oneuse = FALSE + remarks = list("Who knew you could bend bones that far back?", "I guess that was much easier before the planet heated up...", "So that's how they made those ruins survive the ashstorms. Neat!", "The page is just filled with insane ramblings about some 'legion' thing.", "But why would they need vinegar to polish the bones? And rags too?", "You spend a few moments cleaning dirt and blood off of the page, yeesh.") + + +//***Fluff items for lore/intrigue +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard + name = "posted warning" + desc = "It seems to be smudged with mud and... oil?" + info = "TO WHOM IT MAY CONCERN

This area is property of the Nanotrasen Mining Division.

Trespassing in this area is illegal, highly dangerous, and subject to several NDAs.

Please turn back now, under intergalactic law section 48-R." + +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/rnd_notes + name = "Research Findings: Day 26" + desc = "Huh, this one page looks like it was torn out of a full book. How odd." + icon_state = "docs_part" + info = "Researcher name: B--*--* J--*s.

Detailed findings:Today the camp site's cond-tion has wor--ene*. The ashst--ms keep blocking us off from le-ving the sit* for m-re supplies, and it's lo-king like we're out of pl*sma to p-wer the ge-erat*r. Can't rea-*y study c-*bon *ating with no li--ts, ya know? Da-*y's been going -*f again and ag-*n a-*ut h*w the company's left us to *ie here, but I j-s* keep tell-ng him to stop che*-in* out these damn graves. We m-y b* archaeologists, but -e sho*ld have t-e dec-**cy to know these grav-s are *-l NEW.

The rest of the page is just semantics about carbon dating methods." + +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/mutiny + name = "hastily scribbled note" + desc = "Seems like someone was in a hurry." + info = "Alright, we all know that stuck up son a bitch is just doing this to keep us satisifed. Who the hell does he think he is, taking extra rations? We're OUT OF FOOD, CARL. Tomorrow at noon, we're going to try and take the ship by force. He HAS to be lying about the engine cooling down. He HAS TO BE. I'm tellin ya, with this implant I lifted off that last supply ship, I got the smarts to get us offa this shithole. Keep your knife handy carl." + +/obj/item/paper/fluff/ruins/elephant_graveyard/hypothesis + name = "research document" + desc = "Standard Nanotrasen typeface for important research documents." + info = "Day 9: Tenative Conclusions

While the area appears to be of significant cultural importance to the lizard race, outside of some sparce contact with native wildlife, we're yet to find any exact reasoning for the nature of this phenomenon. It seems that organic life is communally drawn to this planet as though it functions as a final resting place for intelligent life. As per company guidelines, this site shall be given the following classification: 'LZ-0271 - Elephant Graveyard'

Compiled list of Artifact findings (Currently Sent Offsite)
Cultist Blade Fragments: x8
Brass Multiplicative Ore Sample: x105
Syndicate Revolutionary Leader Implant (Broken) x1
Extinct Cortical Borer Tissue Sample x1
Space Carp Fossil x3" + +/obj/item/paper/fluff/ruins/elephant_graveyard/final_message + name = "important looking Note" + desc = "This note is well written, and seems to have been put here so you'd find it." + info = "If you find this... you don't need to know who I am.

You need to leave this place. I dunno what shit they did to me out here, but I don't think I'm going to be making it out of here.

This place... it wears down your psyche. The other researchers out here laughed it off but... They were the first to go.

One by one they started turning on each other. The more they found out, the more they started fighting and arguing...
As I speak now, I had to... I wound up having to put most of my men down. I know what I had to do, and I know there's no way left for me to live with myself.
If anyone ever finds this, just don't touch the graves.

DO NOT. TOUCH. THE GRAVES. Don't be a dumbass, like we all were." diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm index e9f8ff4446..cf3a218d80 100644 --- a/code/modules/surgery/advanced/revival.dm +++ b/code/modules/surgery/advanced/revival.dm @@ -36,7 +36,7 @@ return FALSE if(istype(tool, /obj/item/melee/baton)) var/obj/item/melee/baton/B = tool - if(!B.status) + if(!B.turned_on) to_chat(user, "[B] needs to be active!") return FALSE if(istype(tool, /obj/item/gun/energy)) diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index d9e7012214..f654270df7 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -14,7 +14,6 @@ return FALSE if(HAS_TRAIT(C, TRAIT_NODISMEMBER)) return FALSE - var/obj/item/bodypart/affecting = C.get_bodypart(BODY_ZONE_CHEST) affecting.receive_damage(clamp(brute_dam/2 * affecting.body_damage_coeff, 15, 50), clamp(burn_dam/2 * affecting.body_damage_coeff, 0, 50)) //Damage the chest based on limb's existing damage C.visible_message("[C]'s [src.name] has been violently dismembered!") @@ -44,6 +43,10 @@ throw_at(target_turf, throw_range, throw_speed) return TRUE +/obj/item/bodypart/head/dismember() + if(HAS_TRAIT(owner, TRAIT_NODECAP)) + return FALSE + ..() /obj/item/bodypart/chest/dismember() if(!owner) @@ -53,6 +56,8 @@ return FALSE if(HAS_TRAIT(C, TRAIT_NODISMEMBER)) return FALSE + if(HAS_TRAIT(C, TRAIT_NOGUT)) //Just for not allowing gutting + return FALSE . = list() var/organ_spilled = 0 var/turf/T = get_turf(C) diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 671d31530a..65e53df26f 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -1254,12 +1254,12 @@ if (trigger2 == "speak" || trigger2 == "echo") var/trigger3 = html_decode(stripped_input(user, "Enter the phrase spoken. Abusing this to self antag is bannable.", MAX_MESSAGE_LEN)) E.customTriggers[trigger] = list(trigger2, trigger3) - log_game("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2], to send [trigger3].") + log_reagent("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2], to send [trigger3].") if(findtext(trigger3, "admin")) message_admins("FERMICHEM: [user] maybe be trying to abuse MKUltra by implanting by [H] with [trigger], triggering [trigger2], to send [trigger3].") else E.customTriggers[trigger] = trigger2 - log_game("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2].") + log_reagent("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2].") E.mental_capacity -= 5 addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(E.lewd?"your [E.enthrallGender]":"[E.master]")] whispers you a new trigger."), 5) to_chat(user, "You sucessfully set the trigger word [trigger] in [H]") @@ -1322,7 +1322,7 @@ objective = replacetext(lowertext(objective), "strangle", "meow at") objective = replacetext(lowertext(objective), "suicide", "self-love") message_admins("[H] has been implanted by [user] with the objective [objective].") - log_game("FERMICHEM: [H] has been implanted by [user] with the objective [objective] via MKUltra.") + log_reagent("FERMICHEM: [H] has been implanted by [user] with the objective [objective] via MKUltra.") addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(E.lewd?"Your [E.enthrallGender]":"[E.master]")] whispers you a new objective."), 5) brainwash(H, objective) E.mental_capacity -= 200 @@ -1341,7 +1341,7 @@ var/instill = stripped_input(user, "Instill an emotion in [H].", MAX_MESSAGE_LEN) to_chat(H, "[instill]") to_chat(user, "You sucessfully instill a feeling in [H]") - log_game("FERMICHEM: [H] has been instilled by [user] with [instill] via MKUltra.") + log_reagent("FERMICHEM: [H] has been instilled by [user] with [instill] via MKUltra.") E.cooldown += 1 //RECOGNISE @@ -1455,7 +1455,7 @@ if(message_admins || debug)//Do you want this in? message_admins("[ADMIN_LOOKUPFLW(user)] has said '[log_message]' with a Velvet Voice, affecting [english_list(listeners)], with a power multiplier of [power_multiplier].") - log_game("FERMICHEM: [key_name(user)] ckey: [user.key] has said '[log_message]' with a Velvet Voice, affecting [english_list(listeners)], with a power multiplier of [power_multiplier].") + log_reagent("FERMICHEM: [key_name(user)] ckey: [user.key] has said '[log_message]' with a Velvet Voice, affecting [english_list(listeners)], with a power multiplier of [power_multiplier].") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have spoken with a velvet voice") //SSblackbox.record_feedback("tally", "Velvet_voice", 1, log_message) If this is on, it fills the thing up and OOFs the server diff --git a/code/modules/tgs/LICENSE b/code/modules/tgs/LICENSE new file mode 100644 index 0000000000..221f9e1deb --- /dev/null +++ b/code/modules/tgs/LICENSE @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/code/modules/tgs/README.md b/code/modules/tgs/README.md new file mode 100644 index 0000000000..445cee41f5 --- /dev/null +++ b/code/modules/tgs/README.md @@ -0,0 +1,13 @@ +# DMAPI Internals + +This folder should be placed on it's own inside a codebase that wishes to use the TGS DMAPI. Warranty void if modified. + +- [includes.dm](./includes.dm) is the file that should be included by DM code, it handles including the rest. +- The [core](./core) folder includes all code not directly part of any API version. +- The other versioned folders contain code for the different DMAPI versions. + - [v3210](./v3210) contains the final TGS3 API. + - [v4](./v4) is the legacy DMAPI 4 (Used in TGS 4.0.X versions). + - [v5](./v5) is the current DMAPI version used by TGS4 >=4.1. +- [LICENSE](./LICENSE) is the MIT license for the DMAPI. + +APIs communicate with TGS in two ways. All versions implement TGS -> DM communication using /world/Topic. DM -> TGS communication, called the bridge method, is different for each version. diff --git a/code/modules/tgs/core/README.md b/code/modules/tgs/core/README.md new file mode 100644 index 0000000000..aa3c7a9c9d --- /dev/null +++ b/code/modules/tgs/core/README.md @@ -0,0 +1,8 @@ +# Core DMAPI functions + +This folder contains all DMAPI code not directly involved in an API. + +- [_definitions.dm](./definitions.dm) contains defines needed across DMAPI internals. +- [core.dm](./core.dm) contains the implementations of the `/world/proc/TgsXXX()` procs. Many map directly to the `/datum/tgs_api` functions. It also contains the /datum selection and setup code. +- [datum.dm](./datum.dm) contains the `/datum/tgs_api` declarations that all APIs must implement. +- [tgs_version.dm](./tgs_version.dm) contains the `/datum/tgs_version` definition \ No newline at end of file diff --git a/code/modules/tgs/core/core.dm b/code/modules/tgs/core/core.dm index a74c9bbab2..f75e7837af 100644 --- a/code/modules/tgs/core/core.dm +++ b/code/modules/tgs/core/core.dm @@ -154,30 +154,3 @@ var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) if(api) api.SecurityLevel() - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/core/datum.dm b/code/modules/tgs/core/datum.dm index ccc75fe344..ef6d3a4fe5 100644 --- a/code/modules/tgs/core/datum.dm +++ b/code/modules/tgs/core/datum.dm @@ -55,30 +55,3 @@ TGS_PROTECT_DATUM(/datum/tgs_api) /datum/tgs_api/proc/SecurityLevel() return TGS_UNIMPLEMENTED - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/includes.dm b/code/modules/tgs/includes.dm index b3c1728f34..c803cf7ac2 100644 --- a/code/modules/tgs/includes.dm +++ b/code/modules/tgs/includes.dm @@ -15,30 +15,3 @@ #include "v5\api.dm" #include "v5\commands.dm" #include "v5\undef.dm" - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v3210/README.md b/code/modules/tgs/v3210/README.md new file mode 100644 index 0000000000..f96e7cf3b3 --- /dev/null +++ b/code/modules/tgs/v3210/README.md @@ -0,0 +1,6 @@ +# DMAPI V3 + +This DMAPI implements bridge using file output which TGS monitors for. + +- [api.dm](./api.dm) contains the bulk of the API code. +- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s. diff --git a/code/modules/tgs/v3210/api.dm b/code/modules/tgs/v3210/api.dm index 0fc0076c8b..e0d00ad15d 100644 --- a/code/modules/tgs/v3210/api.dm +++ b/code/modules/tgs/v3210/api.dm @@ -226,30 +226,3 @@ #undef SERVICE_REQUEST_API_VERSION #undef SERVICE_RETURN_SUCCESS - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v3210/commands.dm b/code/modules/tgs/v3210/commands.dm index 5046631981..a1949da444 100644 --- a/code/modules/tgs/v3210/commands.dm +++ b/code/modules/tgs/v3210/commands.dm @@ -19,7 +19,7 @@ TGS_ERROR_LOG("Custom command [command_name] can't be used as it is empty or contains illegal characters!") warned_command_names[command_name] = TRUE continue - + if(command_name_types[command_name]) if(warnings_only) TGS_ERROR_LOG("Custom commands [command_name_types[command_name]] and [stc] have the same name, only [command_name_types[command_name]] will be available!") @@ -44,35 +44,3 @@ user.friendly_name = sender user.mention = sender return stc.Run(user, params) || TRUE - -/* - -#undef SERVICE_JSON_PARAM_HELPTEXT -#undef SERVICE_JSON_PARAM_ADMINONLY -#undef SERVICE_JSON_PARAM_REQUIREDPARAMETERS - -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v4/README.md b/code/modules/tgs/v4/README.md new file mode 100644 index 0000000000..78191447b2 --- /dev/null +++ b/code/modules/tgs/v4/README.md @@ -0,0 +1,6 @@ +# DMAPI V4 + +This DMAPI implements bridge requests using file output which TGS monitors for. It has a safe mode restriction. + +- [api.dm](./api.dm) contains the bulk of the API code. +- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s. diff --git a/code/modules/tgs/v4/api.dm b/code/modules/tgs/v4/api.dm index ba18aab688..1dc98f811e 100644 --- a/code/modules/tgs/v4/api.dm +++ b/code/modules/tgs/v4/api.dm @@ -50,6 +50,10 @@ return new /datum/tgs_version("4.0.0.0") /datum/tgs_api/v4/OnWorldNew(minimum_required_security_level) + if(minimum_required_security_level == TGS_SECURITY_ULTRASAFE) + TGS_WARNING_LOG("V4 DMAPI requires safe security!") + minimum_required_security_level = TGS_SECURITY_SAFE + json_path = world.params[TGS4_PARAM_INFO_JSON] if(!json_path) TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!") @@ -310,30 +314,3 @@ /datum/tgs_api/v4/SecurityLevel() return security_level - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v4/commands.dm b/code/modules/tgs/v4/commands.dm index 1d9951bc04..4ca1500167 100644 --- a/code/modules/tgs/v4/commands.dm +++ b/code/modules/tgs/v4/commands.dm @@ -39,31 +39,3 @@ result = "" return result return "Unknown command: [command]!" - -/* - -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm index 2baf3e12d7..8fd84e19fa 100644 --- a/code/modules/tgs/v5/_defines.dm +++ b/code/modules/tgs/v5/_defines.dm @@ -12,13 +12,14 @@ #define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5 #define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier" +#define DMAPI5_PARAMETER_CUSTOM_COMMANDS "customCommands" + #define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage" #define DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE "commandType" #define DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT "currentPort" #define DMAPI5_BRIDGE_PARAMETER_VERSION "version" #define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage" -#define DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS "customCommands" #define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel" #define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort" @@ -95,30 +96,3 @@ #define DMAPI5_CUSTOM_CHAT_COMMAND_NAME "name" #define DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT "helpText" #define DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY "adminOnly" - -/* -The MIT License - -Copyright (c) 2020 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm index eedefb2877..8ca85faf05 100644 --- a/code/modules/tgs/v5/api.dm +++ b/code/modules/tgs/v5/api.dm @@ -16,7 +16,7 @@ var/list/chat_channels /datum/tgs_api/v5/ApiVersion() - return new /datum/tgs_version("5.1.1") + return new /datum/tgs_version("5.2.1") /datum/tgs_api/v5/OnWorldNew(minimum_required_security_level) server_port = world.params[DMAPI5_PARAM_SERVER_PORT] @@ -24,7 +24,7 @@ var/datum/tgs_version/api_version = ApiVersion() version = null - var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) + var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) if(!istype(bridge_response)) TGS_ERROR_LOG("Failed initial bridge request!") return FALSE @@ -201,17 +201,27 @@ if(DMAPI5_TOPIC_COMMAND_HEARTBEAT) return TopicResponse() if(DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH) + var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] + var/error_message = null + if (new_port != null) + if (!isnum(new_port) || !(new_port > 0)) + error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]" + else + server_port = new_port + var/new_version_string = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION] if (!istext(new_version_string)) - return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]") + if(error_message != null) + error_message += ", " + error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]" + else + var/datum/tgs_version/new_version = new(new_version_string) + if (event_handler) + event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version) - var/datum/tgs_version/new_version = new(new_version_string) - if (event_handler) - event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version) + version = new_version - version = new_version - - return TopicResponse() + return json_encode(list(DMAPI5_RESPONSE_ERROR_MESSAGE = error_message, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) return TopicResponse("Unknown command: [command]") @@ -343,30 +353,3 @@ /datum/tgs_api/v5/SecurityLevel() RequireInitialBridgeResponse() return security_level - -/* -The MIT License - -Copyright (c) 2020 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v5/commands.dm b/code/modules/tgs/v5/commands.dm index 2775157656..6d31dd3422 100644 --- a/code/modules/tgs/v5/commands.dm +++ b/code/modules/tgs/v5/commands.dm @@ -38,31 +38,3 @@ topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = text_response return json_encode(topic_response) return TopicResponse("Unknown custom chat command: [command]!") - -/* - -The MIT License - -Copyright (c) 2020 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v5/undef.dm b/code/modules/tgs/v5/undef.dm index b27e3abe95..34fc481d36 100644 --- a/code/modules/tgs/v5/undef.dm +++ b/code/modules/tgs/v5/undef.dm @@ -12,13 +12,14 @@ #undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND #undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER +#undef DMAPI5_PARAMETER_CUSTOM_COMMANDS + #undef DMAPI5_RESPONSE_ERROR_MESSAGE #undef DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE #undef DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT #undef DMAPI5_BRIDGE_PARAMETER_VERSION #undef DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE -#undef DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS #undef DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL #undef DMAPI5_BRIDGE_RESPONSE_NEW_PORT @@ -95,30 +96,3 @@ #undef DMAPI5_CUSTOM_CHAT_COMMAND_NAME #undef DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT #undef DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY - -/* -The MIT License - -Copyright (c) 2020 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/vending/games.dm b/code/modules/vending/games.dm index efd9aad673..641e52dd13 100644 --- a/code/modules/vending/games.dm +++ b/code/modules/vending/games.dm @@ -6,7 +6,8 @@ products = list(/obj/item/toy/cards/deck = 5, /obj/item/storage/pill_bottle/dice = 10, /obj/item/toy/cards/deck/cas = 3, - /obj/item/toy/cards/deck/cas/black = 3) + /obj/item/toy/cards/deck/cas/black = 3, + /obj/item/toy/cards/deck/unum = 3) contraband = list(/obj/item/dice/fudge = 9) premium = list(/obj/item/melee/skateboard/pro = 3, /obj/item/melee/skateboard/hoverboard = 1) diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm index 03d0bbba45..50cdc32bf6 100644 --- a/code/modules/vore/eating/belly_obj.dm +++ b/code/modules/vore/eating/belly_obj.dm @@ -465,7 +465,7 @@ log_attack("[key_name(owner)] digested [key_name(M)].") // If digested prey is also a pred... anyone inside their bellies gets moved up. - if(is_vore_predator(M)) + if(has_vore_belly(M)) M.release_vore_contents(include_absorbed = TRUE, silent = TRUE) //Drop all items into the belly diff --git a/code/modules/vore/eating/living.dm b/code/modules/vore/eating/living.dm index a7cc316cc3..bffb8b2517 100644 --- a/code/modules/vore/eating/living.dm +++ b/code/modules/vore/eating/living.dm @@ -73,15 +73,9 @@ to_chat(user, "They aren't able to be fed.") to_chat(pred, "[user] tried to feed you themselves, but you aren't voracious enough to be fed.") return - if(!is_vore_predator(pred)) - to_chat(user, "They aren't voracious enough.") - return feed_self_to_grabbed(user, pred) else if(pred == user) //you click yourself - if(!is_vore_predator(src)) - to_chat(user, "You aren't voracious enough.") - return feed_grabbed_to_self(user, prey) else // click someone other than you/prey @@ -93,9 +87,6 @@ to_chat(user, "They aren't able to be fed to someone.") to_chat(prey, "[user] tried to feed you to [pred], but you aren't able to be fed to them.") return - if(!is_vore_predator(pred)) - to_chat(user, "They aren't voracious enough.") - return feed_grabbed_to_other(user, prey, pred) // // Eating procs depending on who clicked what @@ -395,7 +386,7 @@ return taste_message // Check if an object is capable of eating things, based on vore_organs // -/proc/is_vore_predator(var/mob/living/O) +/proc/has_vore_belly(var/mob/living/O) if(istype(O)) if(O.vore_organs.len > 0) return TRUE diff --git a/config/lavaRuinBlacklist.txt b/config/lavaRuinBlacklist.txt index 6d2d2633ce..e86cf42ea0 100644 --- a/config/lavaRuinBlacklist.txt +++ b/config/lavaRuinBlacklist.txt @@ -38,4 +38,5 @@ #_maps/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_swarmer_crash.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_library.dmm -#_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm \ No newline at end of file +#_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm +#_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm \ No newline at end of file diff --git a/html/changelog.html b/html/changelog.html index 3d05d75736..cc419e13fb 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -385,454 +385,6 @@
  • You can now choose your name and color as a holoparasite/guardian/holocarp!
  • fixes lings being able to get mechanical holoparasites
  • - -

    28 March 2020

    -

    Arreksuru and Detective Google updated:

    -
      -
    • new HUDpatches for medical, diagnostic, and mesons.
    • -
    • crafting and de-crafting recipes for new HUDpatches.
    • -
    • silly typo with "singlasses" in one of the crafting recipes for HUDglasses.
    • -
    -

    Arturlang updated:

    -
      -
    • Bloodsuckers can no longer get usable blood from blood tomatoes.
    • -
    • Fixed reagent container transfer amount cycling.
    • -
    -

    Bhijn updated:

    -
      -
    • Clicking an open closet with harm intent no longer attempts to place your currently held item inside, but rather attacks it.
    • -
    -

    Bhijn (original PR by Azarak, sprites by Discord user Smug Asshole Muhreen#5522) updated:

    -
      -
    • Synths, the open source and free-as-in-freedom species by FA user vader-san, have been ported from Skyrat.
    • -
    • Ported VOREStation's synthetic taursprites
    • -
    • Markings that don't match very well with your selected species are now hidden from the markings list by default. You can still use these mismatched markings to create horrendous sparkledog abominations by using the "Show mismatched markings" button ingame.
    • -
    • Body markings who's iconstates don't match their name will now actually render properly.
    • -
    • Limb base icons are no longer hardcoded, should_draw_citadel and should_draw_grayscale have been removed in favor of the species-level `icon_limbs` var and the bodypart-level `base_bp_icon` and `color_src` vars. Downstreams should no longer have to touch bodypart rendering code a whole lot if they want to add custom species. Downstreams that have already added species with digitigrade leg support will have to append species IDs to the digitigrade leg sprites, but aside from that, the migration process to this more modularity-friendly system should be fairly smooth.
    • -
    -

    BlackMajor updated:

    -
      -
    • Adjusted the ash walker camp's storm proofing.
    • -
    • Added a tip about creating areas to the ash walker spawn text.
    • -
    -

    Bumtickley00 updated:

    -
      -
    • Iron sheets build the normal metal table again
    • -
    -

    Crystal9156 updated:

    -
      -
    • Fixes Chocolate Jelly Donut icon
    • -
    -

    Dennok, ported by Hatterhat updated:

    -
      -
    • Lava rivers no longer burn into basalt.
    • -
    • The river generator can now specify baseturfs.
    • -
    -

    Detective-Google updated:

    -
      -
    • absurd dong sizes.
    • -
    • my dumb stupid paramedics
    • -
    • Medical no longer spawns with syringe guns, Medical now spawns with medidart guns.
    • -
    -

    EmeraldSundisk updated:

    -
      -
    • Adds CogStation's shuttles to-be.
    • -
    • Adds the "NES Classic" escape shuttle.
    • -
    • Accounts for the new shuttles.
    • -
    -

    Ghommie updated:

    -
      -
    • Added a few cooldowns to chill nuclear bomb and communications console security level change spam, as well as the emergency shuttle's authorization announcements.
    • -
    • Fixed viruses not working on anthros and some others species.
    • -
    • Made the cogchamp mixing sound less annoying.
    • -
    • Removed makeshift switchblades.
    • -
    • pAIs, drones, monkys and lizards can be worn over the head again.
    • -
    • Fixed cargo passive point generation to not go into decimals.
    • -
    • Syndicate ninjas are slightly less friendly now.
    • -
    • Allowed blobbernauts to drag objects (but not mobs) again.
    • -
    • The examiner circuit now works better for mobs.
    • -
    • Chances are monkeys won't end up gorillizing as quickly after being exposed to a rad storm for a minute or so.
    • -
    • Vampire mesmerize doesn't permanently disable combat mode.
    • -
    • The flying speed slowdown while hurt now actually affects flying mobs and not floating ones.
    • -
    • Joining in as a positronic brain won't break the spawner menu anymore.
    • -
    • Fixed dynamic voting.
    • -
    • The autotransfer subsystem is slightly more modulable now.
    • -
    • Resprited some sprite_accessory icon states.
    • -
    -

    Ghommie (plus a fix originally done by Skogol) updated:

    -
      -
    • Drinks dispensers now only show the container they are holding.
    • -
    • Ghost cafe patrons are warded against a few more events now.
    • -
    • Fixed RnD machineries UI displaying designs' required reagents' typepaths instead of names.
    • -
    -

    Hatterhat updated:

    -
      -
    • Red and blue boxes are now actually red or blue.
    • -
    • Beegions! Like Legions, but with actual bees. As in, the bees from the holodeck sim with the randomly-generated toxic bees.
    • -
    • Mining cyborgs are no longer physically capable of claiming points nor wielding a premium accelerator.
    • -
    • Arrow crafting has been finagled with, preventing fire-hardened arrows from being fire-hardened repeatedly. Or something.
    • -
    • Space hermits (those quirky fellas stuck in a rock with carp surrounding them) now have gravity! But they lost their perpetual generators.
    • -
    • Space hermits now have to mine for their research tech (golem vendor board, ORM board). They have slightly less bad parts, though. And better(?) rocks.
    • -
    -

    InnocentFire made the sprites all thanks to them! updated:

    -
      -
    • All bows now have inhand sprites once again
    • -
    -

    KathrinBailey updated:

    -
      -
    • Nine new posters!
    • -
    • Shower curtains can be crafted.
    • -
    • New sofas!
    • -
    • Green and purple comfy chairs to the crafting menu to fit green and purple carpets.
    • -
    • Shower curtains now let you see through them once open, and don't once closed.
    • -
    -

    Kraseo updated:

    -
      -
    • If you have the powersink objective, you will now receive a free beacon.
    • -
    • Lavaland flora have more traits now, to encourage harvesting and sending these off to the botanists.
    • -
    • Napalm will now properly remove weeds from a tray if the plant in it has the fireproof gene.
    • -
    • Gangs no longer get soporific rounds for their sniper rifles.
    • -
    • Syndicate Contracts. Use the new contract uplink to select a contract, and bring the assigned target dead or alive to the designated drop off. Call for the extraction pod and send them off for your TC payment, with much higher rewards for keeping them alive. A high risk, high reward choice for a traitor who wants a real challenge.
    • -
    • New 20 TC contract kit - supplies you with your contractor loadout and uplink.
    • -
    • Targets successfully extracted will be held for ransom by the Syndicate after their use to them is fulfilled. Central command covers the cost, but they'll be taking a cut out of station funds to offset their loss...
    • -
    • Adds a third random item, as well as a small guide on using the contract kit. Also added new possible items that can appear.
    • -
    • Supplied space suit in the contract kit is now an improved variant on the normal Syndicate version.
    • -
    • TC payouts adjusted to be a bit more fair to the contractor. Total payout can never be below a certain threshold.
    • -
    • Broken dropoff locations work again, and general bugfixes.
    • -
    • Contract kit comes with a contractor baton - a unique, lightly electrified weapon to help complete your contracts.
    • -
    • Finalized payment system for contracts; much more balanced for contractors. No more extremely low paying contract sets.
    • -
    • Generated contracts will all have unique targets, no more duplicates.
    • -
    • Extraction droppod explosion has been removed, it'll only damage the tile it lands on.
    • -
    • Extraction pods get sent to the jail immediately again.
    • -
    • Refactored classic_baton code.
    • -
    • Contractor Hub. A unique store for contractors to buy items with Contractor Rep, with two Rep being given when completing a contract.
    • -
    • Contractor pinpointer, available through the Hub. A very inaccurate pinpointer that ignores suit sensors.
    • -
    • Call reinforcements, available through the Hub. Limited to a one-time buy for a contractor, you can purchase an agent to be sent down to help in your mission. Role is polled to ghosts.
    • -
    • Blackout, available through the Hub. Disable station power for a small duration - an expensive, but powerful option of getting into secure areas.
    • -
    • Fulton extraction, available through the Hub. Purchase a fulton extraction kit to help move your targets across the station for those difficult dropoffs.
    • -
    • Assigning yourself to another tablet will give you another contract set.
    • -
    • Contractors can now reroll their contracts a small number of times.
    • -
    • Brand new sprites! A redesign of the specialist space suit, and the kit's own unique tablet. Done by Mey Ha Zah.
    • -
    • Displays contract target jobs under their name.
    • -
    • New locations, such as maintenance, are now possible dropoff locations.
    • -
    • Contractor kit pop cap reduced from 20 to 15.
    • -
    • You can no longer get haunted 8balls from contractor kits.
    • -
    • Pods and shuttles should no longer be valid dropoff locations.
    • -
    • Contract tablets will no longer break when one of your contracts is deleted from the world.
    • -
    • Baton inhands for the right hand now shows the right direction.
    • -
    • Mice don't chew on wires anymore while they're on your person.
    • -
    • Bloodsucker heart theft objective now completes successfully.
    • -
    • Blacklists turret protected areas, the toxins test range, asteroid ruins, and solars from being valid dropoff locations for contracts.
    • -
    -

    Linzolle updated:

    -
      -
    • pacifists can no longer meatspike living things
    • -
    • flypeople being unable to gain nutrition from eating vomit
    • -
    • targetting mouth on help intent now properly nose boops
    • -
    • cmo hypokit now holds the same amount of items as normal kits
    • -
    -

    Moonlit Protector updated:

    -
      -
    • Introducing the 'Heroic Beacon', standing vigil over service the curator can assume one three different historic heroes, each determining their equipment and emergent playstyle to suit the player; a beacon can be found in the curator's backpack upon spawning
    • -
    • Become the Braveheart, a fierce scottish warrior armed with a ceremonial claymore, spraycan, kilt and a disregard for underwear with the scottish themed hero pack.
    • -
    • A unique mention is the "First man on the Moon" heroic pack, with a two piece space worthy suit, air tank & a GPS for recreating a key spessfaring moment in history.
    • -
    • The Curadrobe has been stripped & refilled full of helpful library supplies, including varieties of pens and glasses including the jamjar's.
    • -
    • The curator's explorer equipment & whip has been moved into the 'Courageous Tomb Raider' heroic pack; removed from the backpack & the Curavend respectively.
    • -
    -

    MrJWhit updated:

    -
      -
    • Added minor station things
    • -
    • re balanced r-walls
    • -
    • Evens both sides of the gas containers TEG with reinforced windows
    • -
    • Removed egun in every head locker, replaces RPD with air pump in science, fixes a computer in sec, moves hand teleporter, and removes decals under lockers.
    • -
    -

    MrPerson updated:

    -
      -
    • Solar panels will visually rotate a lot more smoothly instead of being locked to only 8 directions.
    • -
    • Timed solar tracking is in degrees per minute. You're still not gonna use it though.
    • -
    -

    Naksu updated:

    -
      -
    • Time based free rerolls
    • -
    • Refactored Blobs
    • -
    • Blob rerolls now give the blob 4 different options to choose from, rather than forcing a single random one.
    • -
    -

    NecromancerAnne and goldnharl updated:

    -
      -
    • Sprite cleanups and animations for energy guns.
    • -
    -

    NecromancerAnne and zawo and zeroisthebiggay and carlarctg updated:

    -
      -
    • The Infiltrator Bundle, an armor kit for 3TC. Murder people in style!
    • -
    • Some pajamas for nukies to get plenty of bed rest.
    • -
    • halved firefight carry delay with latex or nitrile gloves
    • -
    • headset upgrade is cheaper
    • -
    -

    Owai-Seek updated:

    -
      -
    • Butter Bear
    • -
    • Crab Burger, Bisque, Crab Rangoon, French Onion Soup, Empowered Burger, Chicken Nugget box.
    • -
    • +++ Spider Eggs to Exotic Meat crate. --- Bacon from Exotic Meat crate.
    • -
    • Tweaked Crab Recipes
    • -
    • Butter Bear aka Terrygold
    • -
    • Food Crafting is now 5 deciseconds instead of 30.
    • -
    -

    Putnam updated:

    -
      -
    • Swarmers, portal storm, wormholes are now controlled by dynamic.
    • -
    • Dynamic-controlled events can now have a minimum start time.
    • -
    • Threatening meteors are more common (though still have pretty strict requirements)
    • -
    • Different storytellers now balance around different expected players-per-antag; default was 5, now intrigue/story/random have 7 and calm has 10.
    • -
    • Clown ops is now available as a roundstart antag in dynamic.
    • -
    • Sentient disease and revenant are now in the event pool rather than the antag pool (with the logic that they're both completely useless and unfun to play if people are actually playing against them).
    • -
    • A new formulation of extended was added to the storytellers; no antags, but still spending threat on events.
    • -
    • Fixed a runtime in dynamic due to my misunderstanding pickweightAllowZero
    • -
    • Made conversion storyteller 0-weight-by-default.
    • -
    -

    Putnam3145 updated:

    -
      -
    • Salbutamol causes jittering now.
    • -
    • Made lickable pref save
    • -
    • Traitor classes for traitors: a new way for traitors to have objectives assigned.
    • -
    • Actually made things work as intended.
    • -
    • Removed a redundant turf melting check from the supermatter.
    • -
    • Removed "realistic tcomms lag"
    • -
    • Removed some particularly bad flavor objectives.
    • -
    • Power sink objective is 10x as easy to get
    • -
    • Processing objectives now properly stop once won
    • -
    • MKUltra no longer explodes into lovegas when it fermi explodes, instead causing a regular ol' fireball.
    • -
    • Eigenstasium OD flavor text less restrictive
    • -
    • Dynamic voting should work absent of a config.
    • -
    • Autotransfer vote now requires actual transfer votes to transfer.
    • -
    • More dynamic fixes
    • -
    • Server-run votes aren't subject to vote cooldown
    • -
    • Mass hallucination can better be admemed
    • -
    • Waffle co objective rewritten to make more clear it's not a murderbone objective
    • -
    • CTF spawns, random animals and possessed blades can now be pinged for ghost roles.
    • -
    • A bunch of polls now work with ghost role eligible non-observers.
    • -
    • Removes superfluous line in supermatter processing.
    • -
    • Power sink objective processing now makes sense.
    • -
    -

    Qustinnus/floyd, Ghommie updated:

    -
      -
    • To save costs, Nanotrasen has removed the emergency battery ejection systems in modular computers. We realized saving the batteries isn't really important.
    • -
    • You can squash spiderlings with your bare hands now.
    • -
    • Being deafened properly stops jukebox music from playing.
    • -
    • admin multicam toggles no longer tells everyone but only admins and AIs
    • -
    -

    Ragolution updated:

    -
      -
    • All winter coats and hoods might be different if slightly from one a other.
    • -
    • Adjusted Bartender's Drink Flinging print message to not include name of target turf and save immersion.
    • -
    -

    Seris02 updated:

    -
      -
    • tg genetics
    • -
    • illegal technology
    • -
    • rebalanced rising bass's buttom actions from repulse to side kick
    • -
    • projectiles and rising bass and items and rising bass
    • -
    • a very specific fix with tails and wagging
    • -
    • duffel bags of holding
    • -
    • quirk blacklist fixing
    • -
    • robotics console button swapping
    • -
    • fixed thieving gloves not pickpocketing fast
    • -
    • mentor de/rementor button
    • -
    • mentor !msg
    • -
    • bloodsuckers being unable to accept genes
    • -
    • removes xray from the gene pool
    • -
    -

    Skoglol updated:

    -
      -
    • Fixed gibber exploit.
    • -
    -

    Timberpoes updated:

    -
      -
    • Shuttle countdowns once again read like "01:05" instead of "01: 5".
    • -
    -

    Trilbyspaceclone updated:

    -
      -
    • Three new arm implants, shield for sec, janitor and service
    • -
    • Two new legion drop. Assistant and Bee-Activist
    • -
    • Three new posters have been issued to the printing press
    • -
    • Well contruction, grubs to ash walker home, more seeds for ash walkers.
    • -
    • Wooden buckets can be made from 2 planks of wood, Tower caps also can be used on a fire to make coal
    • -
    • Makes all ashwalker round start seeds 5 yield and 50 harvest so that they can get good crops in rather then failing after 1 harvest
    • -
    • arrow crafting has been fixed
    • -
    • Blobs now can store 250 points.
    • -
    • Alien bar stool is no longer bronze
    • -
    • 28 days log changlogs have been added well 56+ day old changlogs have been removed
    • -
    • Added sunglasses that are able to be huds AND prescription
    • -
    • Prescription sunglasses and crafting of each new type for - Diagnostic, Med and Sec
    • -
    • Diagnostic Sunglasses
    • -
    • Blackists Prescription HUDs from sunglasses crafting
    • -
    • Cotton/Durathread now stack to 80 bundles
    • -
    • Medical hardsuits now have a Medi-Hud built into its helm
    • -
    • Removed old unused Techweb Node selling
    • -
    • Corrects snowcones names and a pixle. Corrects Space Wind snowcone as well
    • -
    • Arrow crafting has been fixed... Again...
    • -
    • Soidifaction of and uranium can be done as well as making new bluespace shards
    • -
    • Xeno and Fountain Hall will no longer spawn more then once
    • -
    • Makes the game want to spawn in more then one tumor maybe
    • -
    • Number of paper work in the crate "freelance paperwork" is half
    • -
    • A few cases were something their is unneeded copy past replaced with many 1 in spawns
    • -
    • Potass Iodide has been fitted into standered borgs as well as medical ones. Upgraded hypos now have Prussian Blue as well.
    • -
    • Syndi borgs Potass Iodide has been swapped for Prussian Blue
    • -
    • No longer can you get the The End and Russian Flask without being the donator
    • -
    • Pipes are small now
    • -
    • Edaggers now enbed as intended
    • -
    • The sleeper agents can be outfitted with some larger then normal sunglasses for 1TC in Badass category
    • -
    • The Syndi Medical borg has been outfitted with the newest and latest ~~Stolen~~ MediCo Gear on the market
    • -
    • Ninjas may be asked to steal the CMO's smart drapes
    • -
    • Hyper Cell steal goal is upgraded to a bluespace cell, as well as the BoH goal now wants a type of BoH rather then the normal default one.
    • -
    • Gutlunches have gotten teeth now and will eat legs, arms, and organs! - Tho are picky and will not eat the brain just laying about!
    • -
    -

    Useroth updated:

    -
      -
    • contractor tablets spawned with invalid icon_state
    • -
    -

    Xantholne updated:

    -
      -
    • Bumbles is now actually in every station's hydroponics.
    • -
    • Bumbles will now actually rest, sit up, and buzz
    • -
    -

    YakumoChen updated:

    -
      -
    • Nekomata (double cat) tails.
    • -
    • 2CAT LMAO
    • -
    • Mining base looks more natural where it's spawned.
    • -
    • Templates Headers will now correctly use the Citadel Official Wiki Link
    • -
    -

    Yenwodyah updated:

    -
      -
    • Bear traps and bolas apply slowdown correctly again
    • -
    • Recycler doesn't delete people in mechs, cardboard boxes, spells, etc. anymore.
    • -
    -

    actioninja, ninjanomnom updated:

    -
      -
    • Being fat is no longer lessened by flying.
    • -
    • The slowdown from grabbing someone no longer applies when you're floating.
    • -
    -

    bunny232 updated:

    -
      -
    • Box bar now has a lightswitch.
    • -
    • fixes several piping issues around box station
    • -
    • moved a scrubber and vent down 5 pixels
    • -
    • Box station captain office now has a standard issue renault
    • -
    • Box bridge now actually has the air distro connected
    • -
    -

    dapnee updated:

    -
      -
    • Lambdastation and it's accompanying files
    • -
    • Robotic's APC, a few missing buttons (bridge shutters and crematorium), paramedic has spawn locations now, two rapid cable deployers to engineering
    • -
    • Renamed some doors and edited engineering to be a bit more open in one spot
    • -
    • a few APCs with bad area tags, access on maintenance doors fixed, engine APC is now connected to the grid instead of power created by the engine
    • -
    • the two syringe guns in medical were removed
    • -
    • couple gas masks around atmos
    • -
    • direction on turbine plasma pressure tank, cloning actually has a cloning console now
    • -
    -

    floyd updated:

    -
      -
    • Everything made from glass in the game has a little more tegridy and doesnt break from a single punch.
    • -
    -

    kappa-sama updated:

    -
      -
    • removed laptops giving slowdown when open
    • -
    • removed (mostly aesthetic) requirement to become hulk
    • -
    • changed add to remove on crit
    • -
    • a super combat shotgun that loads and fires 2 shells at a time
    • -
    • replaces bubblegum's blood contract drop with the super shotgun
    • -
    • 60 seconds instead of 120 for firebreath
    • -
    -

    keronshb updated:

    -
      -
    • blobs now receive a 50% cost refund on attacks that don't spread
    • -
    • reflector blobs are considerably tougher
    • -
    • fixed an integrity
    • -
    • attempting to turn a damaged strong blob into a reflector blob now refunds points
    • -
    • also fixes blob node camera jump (from another PR)
    • -
    -

    kevinz000 updated:

    -
      -
    • Mobility flags are here. Fixed some edge cases with xeno hardstuns and similar stuff like warden's shotgun hardstuns and yeah.
    • -
    • Security now has riot quarterstaves in their lethal shotgun locker.
    • -
    • Pushing is no longer free space movement.
    • -
    • You can now right click to point the tip of some sharp tipped weapons at people.
    • -
    • compact defibs have 10k cells again
    • -
    • music max characters per line is now 150 instead of 50.
    • -
    • storage no longer closes while being dragged
    • -
    • disabler taser alt fire shots are faster and have a 14 tile range now
    • -
    • HoS taser now only applies tased effect for 1 second and warden's pump action stun blaster no longer applies it at all.
    • -
    • Nanite adrenals have been nerfed.
    • -
    • Ninja stungloves nerfed 49 stamina to 25 (so they're basically just better than stunbatons).
    • -
    • Batons now also trigger disarm behavior in disarm intent and not just on right click.
    • -
    • combat mode/sprint/resisting lying down/attempting to crawl under all refactored, added combat/sprint mode lockouts, being locked out of combat mode no longer disables it and allows right click interactions etc etc
    • -
    • hands free actions no longer check mobility and only consciousness.
    • -
    • Minimaps, accessible via a button on OOC.
    • -
    • unnecessary blindness post-unconsciouss has been fixed with a hack that's almost as garbage as the code that caused it in the first place.
    • -
    • synthflesh and rezadone now take total amounts of both applied and existing reagents rather than only existing and only applied respectively.
    • -
    • reverts bubblegum bloodling swarming.
    • -
    • Beam rifles shot count 10 --> 5 and can no longer pierce. Also renders properly for reflections against blobs and some other things.
    • -
    • being stunned no longer stops an ai from undeploying from a shell.
    • -
    • beam rifles are less terrible code
    • -
    • slowdown on items should now be set by set_slowdown().
    • -
    • hypereutactic blades properly slow down their wielders when being used and vv-editing an item's slowdown will once again properly update someone's slowdown to take the new value into account.
    • -
    • stunprods knockdown again.
    • -
    -

    monster860 updated:

    -
      -
    • You can now moan in soft crit
    • -
    • Use Ctrl-Shift-direction key to shift your characters position. Use for ERP.
    • -
    -

    necromanceranne updated:

    -
      -
    • Ports New Sleeping Carp
    • -
    • Ports the martial arts refactors, which includes things like moving martial into the martial subfolder and renaming it _martial, and cleans up human_defense rising bass/sleeping carp exclusive code.
    • -
    • Particle Defender is now a much more sane weapon.
    • -
    • Tasers are no longer ignoring stimulants.
    • -
    • Blood beam can't create harvesters out of mech pilots.
    • -
    • Some minor fixes to fakedeath and a tg fix port.
    • -
    • Bleeding out all your blood from getting love tapped by a toolbox.
    • -
    • Diagnostic HUDSunglasses are better than ever!
    • -
    • Sprite fixes I hope
    • -
    • You can no longer acquire stun bullets in the .45 calibre. You can get the 30 damage version out of the autolathe instead.
    • -
    • KITCHEN GUN (TM) is a lot stronger. Cleaning bullets are a whole 40 damage!
    • -
    • Fixed turrets not allowing their guns to be recovered.
    • -
    • Altered the plastitanium rapier from a perfect AP but weaker esword equivalent to a more unique sleep inducing melee weapon.
    • -
    • Touched up all the relevant sprites.
    • -
    • Nightvision goggles are nerfed all-round. Flashes have actual use against people using nightvision, as do flashbangs.
    • -
    • Syndicate nuclear agents get to live peacefully knowing their eyes are well protected by their special night vision goggles. Spider clan also get these goggles.
    • -
    -

    raspyosu updated:

    -
      -
    • some flavor text for lunge, cloak
    • -
    • mesmerize, cloak functionality/requirements
    • -
    • mesmerize, lunge, cloak
    • -
    • lunge telegraph sound
    • -
    • mesmerized status icon flavor text
    • -
    • cloak sometimes not restoring initial move intent
    • -
    • mesmerize (line of sight checking system and remove progress bar)
    • -
    • nerf: lunge, mesmerize
    • -
    -

    spookydonut updated:

    -
      -
    • adds selective duplicate component mode
    • -
    -

    wesoda25 updated:

    -
      -
    • You no longer hit fermenting barrels when taking reagents from them
    • -
    -

    zeroisthebiggay updated:

    -
      -
    • kilo shuttle less bad
    • -
    • tauric contractor space suits
    • -
    • ghost hud and nv defaults on
    • -
    • syndicate elite hardsuit helmet doesnt hide masks anymore
    • -
    • syndicate contractor helmets are no longer secretly lead
    • -
    • Space Fashion has discovered a new way to wear bandannas. With some simple minor adjustments and ties, bandannas can be made into fashionable neckerchiefs!
    • -
    • Box Station has gotten a brand new brig. Go and check it out and discover all the quirky little soulbits.
    • -
    • box brig miscellaneous issues
    • -
    • box station hos office
    • -
    GoonStation 13 Development Team diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 0731583733..0c4784553c 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi index 3860fa4b7e..856fe2149a 100644 Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi index 7902487873..3613488027 100644 Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ diff --git a/icons/mob/inhands/equipment/mining_lefthand.dmi b/icons/mob/inhands/equipment/mining_lefthand.dmi index e902690c37..7496aba625 100644 Binary files a/icons/mob/inhands/equipment/mining_lefthand.dmi and b/icons/mob/inhands/equipment/mining_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/mining_righthand.dmi b/icons/mob/inhands/equipment/mining_righthand.dmi index dacf9be078..de3d11978a 100644 Binary files a/icons/mob/inhands/equipment/mining_righthand.dmi and b/icons/mob/inhands/equipment/mining_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/security_lefthand.dmi b/icons/mob/inhands/equipment/security_lefthand.dmi index d5b32d7c37..47447f80d0 100644 Binary files a/icons/mob/inhands/equipment/security_lefthand.dmi and b/icons/mob/inhands/equipment/security_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/security_righthand.dmi b/icons/mob/inhands/equipment/security_righthand.dmi index 1c8c9b0dfb..79aab1c5cd 100644 Binary files a/icons/mob/inhands/equipment/security_righthand.dmi and b/icons/mob/inhands/equipment/security_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 1cd090a3e9..19738ed490 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 24c9a2d777..9589e338e1 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/mutant_bodyparts.dmi b/icons/mob/mutant_bodyparts.dmi index 9c531a3df2..1334ce9e0e 100644 Binary files a/icons/mob/mutant_bodyparts.dmi and b/icons/mob/mutant_bodyparts.dmi differ diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index e0b02d2adc..c75afde4cc 100644 Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index 1169888b34..95ae326f1e 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 2a6ce77f38..535ae0d241 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index a19627b8ea..1768d8a1c6 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/crates.dmi b/icons/obj/crates.dmi index 532324fcf4..a1bc443efb 100644 Binary files a/icons/obj/crates.dmi and b/icons/obj/crates.dmi differ diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi index f66767292c..c280ee786f 100644 Binary files a/icons/obj/decals.dmi and b/icons/obj/decals.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 2cc3b784f4..f2a8328717 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/doors/shutters.dmi b/icons/obj/doors/shutters.dmi index 6f10860cfa..816d1f94f9 100644 Binary files a/icons/obj/doors/shutters.dmi and b/icons/obj/doors/shutters.dmi differ diff --git a/icons/obj/doors/shutters_radiation.dmi b/icons/obj/doors/shutters_radiation.dmi index 36d232b197..657b613b0c 100644 Binary files a/icons/obj/doors/shutters_radiation.dmi and b/icons/obj/doors/shutters_radiation.dmi differ diff --git a/icons/obj/doors/shutters_window.dmi b/icons/obj/doors/shutters_window.dmi index 20197593c1..c99790c6cf 100644 Binary files a/icons/obj/doors/shutters_window.dmi and b/icons/obj/doors/shutters_window.dmi differ diff --git a/icons/obj/guns/gun_parts.dmi b/icons/obj/guns/gun_parts.dmi new file mode 100644 index 0000000000..8e3168769d Binary files /dev/null and b/icons/obj/guns/gun_parts.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index 79045ac92b..5c8fab82e8 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index 58083f5f6d..c95e6e5cb7 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi index be12ab5f8b..727d69b1e3 100644 Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ diff --git a/icons/obj/machines/bepis.dmi b/icons/obj/machines/bepis.dmi new file mode 100644 index 0000000000..f348c2e1b0 Binary files /dev/null and b/icons/obj/machines/bepis.dmi differ diff --git a/icons/obj/mauna_mug.dmi b/icons/obj/mauna_mug.dmi new file mode 100644 index 0000000000..fd576072fd Binary files /dev/null and b/icons/obj/mauna_mug.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index 20ffbdbe06..43bc9c48aa 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi index 5ad6c1cb3b..03b7a9e44f 100644 Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/reagentfillings.dmi index 3d5a825f27..f07928741d 100644 Binary files a/icons/obj/reagentfillings.dmi and b/icons/obj/reagentfillings.dmi differ diff --git a/icons/obj/smooth_structures/rollingtable.dmi b/icons/obj/smooth_structures/rollingtable.dmi new file mode 100644 index 0000000000..9e559a75d9 Binary files /dev/null and b/icons/obj/smooth_structures/rollingtable.dmi differ diff --git a/icons/obj/stack_objects.dmi b/icons/obj/stack_objects.dmi index 5b0c05d43d..d327dc8988 100644 Binary files a/icons/obj/stack_objects.dmi and b/icons/obj/stack_objects.dmi differ diff --git a/icons/obj/statuelarge.dmi b/icons/obj/statuelarge.dmi index e45afb8db8..e627a883cb 100644 Binary files a/icons/obj/statuelarge.dmi and b/icons/obj/statuelarge.dmi differ diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi index 6a2bb343df..0ff7d4a607 100644 Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index 698c1f7a34..e8106905b7 100644 Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ diff --git a/icons/obj/watercloset.dmi b/icons/obj/watercloset.dmi index 5670b9e839..4a299f29dd 100644 Binary files a/icons/obj/watercloset.dmi and b/icons/obj/watercloset.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index d24efa0625..dbd5aaa960 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/modular_citadel/code/_onclick/hud/screen_objects.dm b/modular_citadel/code/_onclick/hud/screen_objects.dm index 2101a6045f..017f7f3485 100644 --- a/modular_citadel/code/_onclick/hud/screen_objects.dm +++ b/modular_citadel/code/_onclick/hud/screen_objects.dm @@ -1,63 +1,22 @@ -/obj/screen/restbutton - name = "rest" - icon = 'modular_citadel/icons/ui/screen_midnight.dmi' - icon_state = "rest" - -/obj/screen/restbutton/Click() - if(isliving(usr)) - var/mob/living/theuser = usr - theuser.lay_down() - -/obj/screen/combattoggle - name = "toggle combat mode" - icon = 'modular_citadel/icons/ui/screen_midnight.dmi' - icon_state = "combat_off" - var/mutable_appearance/flashy - -/obj/screen/combattoggle/Click() - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - C.user_toggle_intentional_combat_mode() - -/obj/screen/combattoggle/update_icon_state() - var/mob/living/carbon/user = hud?.mymob - if(!istype(user)) - return - if((user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - icon_state = "combat" - else if(HAS_TRAIT(user, TRAIT_COMBAT_MODE_LOCKED)) - icon_state = "combat_locked" - else - icon_state = "combat_off" - -/obj/screen/combattoggle/update_overlays() - . = ..() - var/mob/living/carbon/user = hud?.mymob - if(!istype(user) || !user.client) - return - - if((user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && user.client.prefs.hud_toggle_flash) - if(!flashy) - flashy = mutable_appearance('icons/mob/screen_gen.dmi', "togglefull_flash") - if(flashy.color != user.client.prefs.hud_toggle_color) - flashy.color = user.client.prefs.hud_toggle_color - . += flashy //TODO - beg lummox jr for the ability to force mutable appearances or images to be created rendering from their first frame of animation rather than being based entirely around the client's frame count - /obj/screen/voretoggle name = "toggle vore mode" icon = 'modular_citadel/icons/ui/screen_midnight.dmi' icon_state = "nom_off" /obj/screen/voretoggle/Click() - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - C.toggle_vore_mode() + if(usr != hud.mymob) + return + var/mob/living/carbon/C = usr + if(SEND_SIGNAL(usr, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) + to_chat(usr, "Disable combat mode first.") + return + C.toggle_vore_mode() /obj/screen/voretoggle/update_icon_state() var/mob/living/carbon/user = hud?.mymob if(!istype(user)) return - if(user.voremode && !(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(user.voremode) icon_state = "nom" else icon_state = "nom_off" diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 62fe30f2d7..57cbdb6beb 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -10,7 +10,7 @@ alert_type = null /datum/status_effect/chem/SGDF/on_apply() - log_game("FERMICHEM: SGDF status appied on [owner], ID: [owner.key]") + log_reagent("FERMICHEM: SGDF status appied on [owner], ID: [owner.key]") fermi_Clone = owner return ..() @@ -24,7 +24,7 @@ ..() /datum/status_effect/chem/SGDF/on_remove() - log_game("FERMICHEM: SGDF mind shift applied. [owner] is now playing as their clone and should not have memories after their clone split (look up SGDF status applied). ID: [owner.key]") + log_reagent("FERMICHEM: SGDF mind shift applied. [owner] is now playing as their clone and should not have memories after their clone split (look up SGDF status applied). ID: [owner.key]") originalmind.transfer_to(fermi_Clone) to_chat(owner, "Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. Curiously, you find that you memories are blank after you ingested the synthetic serum, leaving you to wonder where the other you is.") fermi_Clone = null @@ -40,7 +40,7 @@ var/last_checked_size //used to prevent potential cpu waste from happening every tick. /datum/status_effect/chem/breast_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now. - log_game("FERMICHEM: [owner]'s breasts has reached comical sizes. ID: [owner.key]") + log_reagent("FERMICHEM: [owner]'s breasts has reached comical sizes. ID: [owner.key]") var/mob/living/carbon/human/H = owner var/message = FALSE if(H.w_uniform) @@ -91,7 +91,7 @@ ..() /datum/status_effect/chem/breast_enlarger/on_remove() - log_game("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]") + log_reagent("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]") to_chat(owner, "Your expansive chest has become a more managable size, liberating your movements.") owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/breast_hypertrophy) sizeMoveMod(1) @@ -114,7 +114,7 @@ var/last_checked_size //used to prevent potential cpu waste, just like the above. /datum/status_effect/chem/penis_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now. - log_game("FERMICHEM: [owner]'s dick has reached comical sizes. ID: [owner.key]") + log_reagent("FERMICHEM: [owner]'s dick has reached comical sizes. ID: [owner.key]") var/mob/living/carbon/human/H = owner var/message = FALSE if(H.w_uniform) @@ -162,7 +162,7 @@ ..() /datum/status_effect/chem/penis_enlarger/on_remove() - log_game("FERMICHEM: [owner]'s dick has reduced to an acceptable size. ID: [owner.key]") + log_reagent("FERMICHEM: [owner]'s dick has reduced to an acceptable size. ID: [owner.key]") owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/penis_hypertrophy) owner.ResetBloodVol() return ..() @@ -189,7 +189,7 @@ var/mob/living/simple_animal/astral/G = new(get_turf(M.loc)) owner.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. to_chat(G, "[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") - log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") + log_reagent("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") originalmind.transfer_to(original) /datum/status_effect/chem/astral_insurance/on_remove() //God damnit get them home! @@ -198,7 +198,7 @@ var/mob/living/simple_animal/astral/G = new(get_turf(owner)) owner.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. to_chat(G, "[owner]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") - log_game("FERMICHEM: [owner]'s possesser has been booted out into a astral ghost!") + log_reagent("FERMICHEM: [owner]'s possesser has been booted out into a astral ghost!") originalmind.transfer_to(original) return ..() @@ -272,7 +272,7 @@ var/message = "[(lewd ? "I am a good pet for [enthrallGender]." : "[master] is a really inspirational person!")]" SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "enthrall", /datum/mood_event/enthrall, message) to_chat(owner, "You feel inexplicably drawn towards [master], their words having a demonstrable effect on you. It seems the closer you are to them, the stronger the effect is. However you aren't fully swayed yet and can resist their effects by repeatedly resisting as much as you can!") - log_game("FERMICHEM: MKULTRA: Status applied on [owner] ckey: [owner.key] with a master of [master] ckey: [enthrallID].") + log_reagent("FERMICHEM: MKULTRA: Status applied on [owner] ckey: [owner.key] with a master of [master] ckey: [enthrallID].") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Enthrall attempts") return ..() @@ -303,7 +303,7 @@ switch(phase) if(-1)//fully removed SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "enthrall") - log_game("FERMICHEM: MKULTRA: Status REMOVED from [owner] ckey: [owner.key] with a master of [master] ckey: [enthrallID].") + log_reagent("FERMICHEM: MKULTRA: Status REMOVED from [owner] ckey: [owner.key] with a master of [master] ckey: [enthrallID].") owner.remove_status_effect(src) return if(0)// sleeper agent @@ -344,7 +344,7 @@ else to_chat(owner, "You are unable to put up a resistance any longer, and now are under the influence of [master]. However you find that in your intoxicated state you are unable to resort to violence. Equally you are unable to commit suicide, even if ordered to, as you cannot follow [master] in death. ") to_chat(master, "Your [(lewd?"pet":"follower")] [owner] appears to have fully fallen under your sway.") - log_game("FERMICHEM: MKULTRA: Status on [owner] ckey: [owner.key] has been fully entrhalled (state 3) with a master of [master] ckey: [enthrallID].") + log_reagent("FERMICHEM: MKULTRA: Status on [owner] ckey: [owner.key] has been fully entrhalled (state 3) with a master of [master] ckey: [enthrallID].") SSblackbox.record_feedback("tally", "fermi_chem", 1, "thralls fully enthralled.") else if (resistanceTally > 200) enthrallTally *= 0.5 @@ -616,14 +616,14 @@ var/cached_trigger = lowertext(trigger) if (findtext(raw_message, cached_trigger))//if trigger1 is the message cTriggered = 5 //Stops triggerparties and as a result, stops servercrashes. - log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been triggered with [cached_trigger] from [hearing_args[HEARING_SPEAKER]] saying: \"[hearing_args[HEARING_MESSAGE]]\". (their master being [master] ckey: [enthrallID].)") + log_reagent("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been triggered with [cached_trigger] from [hearing_args[HEARING_SPEAKER]] saying: \"[hearing_args[HEARING_MESSAGE]]\". (their master being [master] ckey: [enthrallID].)") //Speak (Forces player to talk) if (lowertext(customTriggers[trigger][1]) == "speak")//trigger2 var/saytext = "Your mouth moves on it's own before you can even catch it." addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "[saytext]"), 5) addtimer(CALLBACK(C, /atom/movable/proc/say, "[customTriggers[trigger][2]]"), 5) - log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been forced to say: \"[customTriggers[trigger][2]]\" from previous trigger.") + log_reagent("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been forced to say: \"[customTriggers[trigger][2]]\" from previous trigger.") //Echo (repeats message!) allows customisation, but won't display var calls! Defaults to hypnophrase. @@ -671,7 +671,7 @@ var/mob/living/carbon/human/o = owner o.apply_status_effect(/datum/status_effect/trance, 200, TRUE) tranceTime = 50 - log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been tranced from previous trigger.") + log_reagent("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been tranced from previous trigger.") return diff --git a/modular_citadel/code/modules/admin/chat_commands.dm b/modular_citadel/code/modules/admin/chat_commands.dm deleted file mode 100644 index ddac7b5953..0000000000 --- a/modular_citadel/code/modules/admin/chat_commands.dm +++ /dev/null @@ -1,46 +0,0 @@ -/datum/tgs_chat_command/wheelofsalt - name = "wheelofsalt" - help_text = "What are Citadel Station 13 players salting about today? Spin the wheel and find out!" - -/datum/tgs_chat_command/wheelofsalt/Run(datum/tgs_chat_user/sender, params) - var/saltresult = "The wheel of salt [pick("clatters","screams","vibrates","clanks","resonates","groans","moans","squeaks","emits a[pick(" god-forsaken"," lewd"," creepy"," generic","n orgasmic"," demonic")] [pick("airhorn","bike horn","trumpet","clown","latex","vore","dog","laughing")] noise")] as it spins violently... And it seems the salt of the day is the " - var/saltprimarysubject = "[pick("combat","medical","grab","furry","wall","orgasm","cat","ERP","lizard","dog","latex","vision cone","atmospherics","table","chem","vore","dogborg","Skylar Lineman","Mekhi Anderson","Peppermint","rework","cum","dick","cockvore","Medihound","sleeper","belly sleeper","door wires","flightsuit","coder privilege","Developer abuse","ban reason","github self merge","red panda","beret","male catgirl","powergame","hexacrocin","Discord server","Clitadel","Cargonia","Solarian Republic","Main and RP merger","bluespace","salt","chem dispenser theft","Botany","moth","BWOINK","anal vore","stamina","Mason Jakops","mining","noodle","milf","Lavaland","Necropolis","Ashwalker","Chase Redtail","Drew Mint","Pavel Marsk","Joker Amari","Durgit","chaplain","Antag","nanite","Syndicate","Nar-Sie","Ratvar","Cult","maint","Foam-Force","AI","cyborg","ghost","clockwork","cyberpunk","vaporwave","Clown","Leon Beech","Mime","security","research","Megafauna","Bubblegum","Ash Drake","Legion","Colossus","White Shuttle","Changeling","Cowboy","Space Ninja","Poly","Revolutionary","Skyrim","forbidden fruits","xenomorph","blob","Nuclear Operative","crossdressing")]" - var/saltsecondarysubject = "[pick("rework","changes","r34","ban","removal","addition","leak","proposal","fanart","introduction","tabling","ERP","bikeshedding","crossdressing","sprites","semen keg","argument","theft","nerf","screeching","salt","creampie","lewding","murder","kissing","marriage","replacement","fucking","ship","netflix adaptation","dance","remaster","system","voyeur","decoration","pre-order","bukkake","seduction","worship","gangbang","handholding")]" - if(prob(10)) - saltresult += "@here for your salt, all day every day" - if(prob(1)) - saltresult += " @everyone gets some salt this time too" - else - saltresult += "[saltprimarysubject] [saltsecondarysubject]" - return "[saltresult]!" - -/datum/tgs_chat_command/valentine - name = "valentine" - help_text = "Get a random flirt line." - -/datum/tgs_chat_command/valentine/Run(datum/tgs_chat_user/sender, params) - return "[pick(GLOB.flirts)]" - -/datum/tgs_chat_command/despacito - name = "despacito" //someone please high effort this sometime and make it a full on ytdl search - help_text = "This is so sad." - -/datum/tgs_chat_command/despacito/Run() - return "https://www.youtube.com/watch?v=kJQP7kiw5Fk" - -/datum/tgs_chat_command/poly - name = "poly" - help_text = "The Lewder, more applicable Poly speak for Citadel Station 13." - var/list/speech_buffer - -/datum/tgs_chat_command/poly/Run() - LAZYINITLIST(speech_buffer) //I figure this is just safe to do for everything at this point - if(length(speech_buffer)) //Let's not look up the whole json EVERY TIME, just the first time. - return "[pick(speech_buffer)]" - else - var/json_file = file("data/npc_saves/Poly.json") - if(!fexists(json_file)) - return "**BAWWWWWK!** LEAVE THE HEADSET! ***BAWKKKKK!!***" - var/list/json = json_decode(file2text(json_file)) - speech_buffer = json["phrases"] - return "[pick(speech_buffer)]" diff --git a/modular_citadel/code/modules/client/client_defines.dm b/modular_citadel/code/modules/client/client_defines.dm deleted file mode 100644 index d816b15d1d..0000000000 --- a/modular_citadel/code/modules/client/client_defines.dm +++ /dev/null @@ -1,2 +0,0 @@ -/client - var/cryo_warned = -3000//when was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns diff --git a/modular_citadel/code/modules/mob/living/carbon/carbon.dm b/modular_citadel/code/modules/mob/living/carbon/carbon.dm index 0532f59afa..3a683ca2ff 100644 --- a/modular_citadel/code/modules/mob/living/carbon/carbon.dm +++ b/modular_citadel/code/modules/mob/living/carbon/carbon.dm @@ -1,29 +1,16 @@ /mob/living/carbon - var/lastmousedir - var/wrongdirmovedelay - //oh no vore time var/voremode = FALSE /mob/living/carbon/proc/toggle_vore_mode() + if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_TOGGLED)) + return FALSE //let's not override the main draw of the game these days voremode = !voremode var/obj/screen/voretoggle/T = locate() in hud_used?.static_inventory T?.update_icon_state() - if(combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) - return FALSE //let's not override the main draw of the game these days - SEND_SIGNAL(src, COMSIG_VORE_TOGGLED, src, voremode) return TRUE -/mob/living/carbon/Move(atom/newloc, direct = 0) - . = ..() - wrongdirmovedelay = FALSE - if((combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && client && lastmousedir) - if(lastmousedir != dir) - wrongdirmovedelay = TRUE - setDir(lastmousedir, ismousemovement = TRUE) - -/mob/living/carbon/onMouseMove(object, location, control, params) - if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - return - face_atom(object, TRUE) - lastmousedir = dir +/mob/living/carbon/proc/disable_vore_mode() + voremode = FALSE + var/obj/screen/voretoggle/T = locate() in hud_used?.static_inventory + T?.update_icon_state() diff --git a/modular_citadel/code/modules/mob/living/living.dm b/modular_citadel/code/modules/mob/living/living.dm index 3baab2ad86..01867e9dcc 100644 --- a/modular_citadel/code/modules/mob/living/living.dm +++ b/modular_citadel/code/modules/mob/living/living.dm @@ -37,7 +37,7 @@ if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && total_health >= STAMINA_CRIT && !stat) to_chat(src, "You're too exhausted to keep going...") set_resting(TRUE, FALSE, FALSE) - disable_intentional_combat_mode(TRUE, FALSE) + SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE) ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_HARD_STAMCRIT) filters += CIT_FILTER_STAMINACRIT update_mobility() diff --git a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm index bcc156a22e..03a124e306 100644 --- a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm +++ b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm @@ -178,7 +178,7 @@ name = "positron blast" damage = 80 range = 14 - speed = 0.6 + pixels_per_second = TILES_TO_PIXELS(16.667) icon_state = "disablerslug" /obj/item/projectile/beam/pump diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm index d3daad7964..f66c0289b6 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm @@ -171,10 +171,10 @@ Creating a chem with a low purity will make you permanently fall in love with so E.enthrallGender = creatorGender E.master = get_mob_by_key(creatorID) to_chat(M, "Your addled, plastic, mind bends under the chemical influence of a new [(E.lewd?"master":"leader")]. Your highest priority is now to stay by [creatorName]'s side, following and aiding them at all costs.") //THIS SHOULD ONLY EVER APPEAR IF YOU MINDBREAK YOURSELF AND THEN GET INJECTED FROM SOMEONE ELSE. - log_game("FERMICHEM: Narcissist [M] ckey: [M.key] been rebound to [creatorName], ID: [creatorID]") + log_reagent("FERMICHEM: Narcissist [M] ckey: [M.key] been rebound to [creatorName], ID: [creatorID]") return if((M.ckey == creatorID) && (creatorName == M.real_name)) //same name AND same player - same instance of the player. (should work for clones?) - log_game("FERMICHEM: [M] ckey: [M.key] has been given velvetspeech") + log_reagent("FERMICHEM: [M] ckey: [M.key] has been given velvetspeech") var/obj/item/organ/vocal_cords/Vc = M.getorganslot(ORGAN_SLOT_VOICE) var/obj/item/organ/vocal_cords/nVc = new /obj/item/organ/vocal_cords/velvet if(Vc) @@ -183,9 +183,9 @@ Creating a chem with a low purity will make you permanently fall in love with so qdel(Vc) to_chat(M, "You feel your vocal chords tingle you speak in a more charasmatic and sultry tone.") else - log_game("FERMICHEM: MKUltra: [creatorName], [creatorID], is enthralling [M.name], [M.ckey]") + log_reagent("FERMICHEM: MKUltra: [creatorName], [creatorID], is enthralling [M.name], [M.ckey]") M.apply_status_effect(/datum/status_effect/chem/enthrall) - log_game("FERMICHEM: [M] ckey: [M.key] has taken MKUltra") + log_reagent("FERMICHEM: [M] ckey: [M.key] has taken MKUltra") /datum/reagent/fermi/enthrall/on_mob_life(mob/living/carbon/M) . = ..() @@ -251,7 +251,7 @@ Creating a chem with a low purity will make you permanently fall in love with so to_chat(M, "Your mind shatters under the volume of the mild altering chem inside of you, breaking all will and thought completely. Instead the only force driving you now is the instinctual desire to obey and follow [creatorName]. Your highest priority is now to stay by their side and protect them at all costs.") else to_chat(M, "The might volume of chemicals in your system overwhelms your mind, and you suddenly agree with what [creatorName] has been saying. Your highest priority is now to stay by their side and protect them at all costs.") - log_game("FERMICHEM: [M] ckey: [M.key] has been mindbroken for [creatorName] ckey: [creatorID]") + log_reagent("FERMICHEM: [M] ckey: [M.key] has been mindbroken for [creatorName] ckey: [creatorID]") M.slurring = 100 M.confused = 100 E.phase = 4 @@ -289,7 +289,7 @@ Creating a chem with a low purity will make you permanently fall in love with so M.apply_status_effect(STATUS_EFFECT_INLOVE, love) lewd = (M.client?.prefs.cit_toggles & HYPNO) && (love.client?.prefs.cit_toggles & HYPNO) to_chat(M, "[(lewd?"":"")][(lewd?"You develop a sudden crush on [love], your heart beginning to race as you look upon them with new eyes.":"You suddenly feel like making friends with [love].")] You feel strangely drawn towards them.") - log_game("FERMICHEM: [M] ckey: [M.key] has temporarily bonded with [love] ckey: [love.key]") + log_reagent("FERMICHEM: [M] ckey: [M.key] has temporarily bonded with [love] ckey: [love.key]") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have bonded") else if(get_dist(M, love) < 8) @@ -314,7 +314,7 @@ Creating a chem with a low purity will make you permanently fall in love with so SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "InLove") SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "MissingLove") to_chat(M, "[(lewd?"":"")]Your feelings for [love] suddenly vanish!") - log_game("FERMICHEM: [M] ckey: [M.key] is no longer in temp bond") + log_reagent("FERMICHEM: [M] ckey: [M.key] is no longer in temp bond") ..() /datum/reagent/fermi/proc/FallInLove(mob/living/carbon/Lover, mob/living/carbon/Love) @@ -331,7 +331,7 @@ Creating a chem with a low purity will make you permanently fall in love with so Lover.apply_status_effect(STATUS_EFFECT_INLOVE, Love) forge_valentines_objective(Lover, Love, TRUE) SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have become infatuated.") - log_game("FERMICHEM: [Lover] ckey: [Lover.key] has been chemically made to fall for [Love] ckey: [Love.key]") + log_reagent("FERMICHEM: [Lover] ckey: [Lover.key] has been chemically made to fall for [Love] ckey: [Love.key]") return //For addiction see chem.dm diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm index 51b13f8c55..37ec1ee69f 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm @@ -64,7 +64,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if(pollStarted == FALSE) pollStarted = TRUE candies = pollGhostCandidates("Do you want and agree to play as a clone of [M], respect their character and not engage in ERP without permission from the original?", ignore_category = POLL_IGNORE_CLONE) - log_game("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.") + log_reagent("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.") if(20 to INFINITY) if(LAZYLEN(candies) && playerClone == FALSE) //If there's candidates, clone the person and put them in there! to_chat(M, "The cells reach a critical micelle concentration, nucleating rapidly within your body!") @@ -82,7 +82,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if(C2.key && C2) C2.transfer_ckey(SM, FALSE) message_admins("Ghost candidate found! [C2] key [C2.key] is becoming a clone of [M] key: [M.key] (They agreed to respect the character they're becoming, and agreed to not ERP without express permission from the original.)") - log_game("FERMICHEM: [M] ckey: [M.key] is creating a clone, controlled by [C2]") + log_reagent("FERMICHEM: [M] ckey: [M.key] is creating a clone, controlled by [C2]") break else candies -= C2 @@ -97,16 +97,16 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING var/obj/item/organ/zombie_infection/ZI = M.getorganslot(ORGAN_SLOT_ZOMBIE) ZI.Remove() ZI.Insert(SM) - log_game("FERMICHEM: [M] ckey: [M.key]'s zombie_infection has been transferred to their clone") + log_reagent("FERMICHEM: [M] ckey: [M.key]'s zombie_infection has been transferred to their clone") to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with your original, a perfect clone of your origin.") if(prob(50)) to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original.") - log_game("FERMICHEM: [SM] ckey: [SM.key]'s is not bound by [M] ckey [M.key]'s will, and is free to determine their own goals, while respecting and acting as their origin.") + log_reagent("FERMICHEM: [SM] ckey: [SM.key]'s is not bound by [M] ckey [M.key]'s will, and is free to determine their own goals, while respecting and acting as their origin.") else to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.") - log_game("FERMICHEM: [SM] ckey: [SM.key]'s is bound by [M] ckey [M.key]'s objectives, and is encouraged to help them complete them.") + log_reagent("FERMICHEM: [SM] ckey: [SM.key]'s is bound by [M] ckey [M.key]'s objectives, and is encouraged to help them complete them.") to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") M.visible_message("[M] suddenly shudders, and splits into two identical twins!") @@ -124,7 +124,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING //Transfer remaining reagent to clone. I think around 30u will make a healthy clone, otherwise they'll have clone damage, blood loss, brain damage and hunger. SM.reagents.add_reagent(/datum/reagent/fermi/SDGFheal, volume) M.reagents.remove_reagent(type, volume) - log_game("FERMICHEM: [volume]u of SDGFheal has been transferred to the clone") + log_reagent("FERMICHEM: [volume]u of SDGFheal has been transferred to the clone") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Sentient clones made") return ..() @@ -135,7 +135,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if(21) to_chat(M, "The cells fail to catalyse around a nucleation event, instead merging with your cells.") //This stuff is hard enough to make to rob a user of some benefit. Shouldn't replace Rezadone as it requires the user to not only risk making a player controlled clone, but also requires them to have split in two (which also requires 30u of SGDF). REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) - log_game("FERMICHEM: [M] ckey: [M.key] is being healed by SDGF") + log_reagent("FERMICHEM: [M] ckey: [M.key] is being healed by SDGF") if(22 to INFINITY) M.adjustCloneLoss(-1, 0) M.adjustBruteLoss(-1, 0) @@ -182,7 +182,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING S.originalmind = M.mind S.status_set = TRUE - log_game("FERMICHEM: [M] ckey: [M.key] has created a mindless clone of themselves") + log_reagent("FERMICHEM: [M] ckey: [M.key] has created a mindless clone of themselves") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Braindead clones made") if(87 to INFINITY) M.reagents.remove_reagent(type, volume)//removes SGDF on completion. Has to do it this way because of how i've coded it. If some madlab gets over 1k of SDGF, they can have the clone healing. @@ -349,7 +349,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING ZI.real_name = M.real_name//Give your offspring a big old kiss. ZI.name = M.real_name ZI.desc = "[M]'s clone, gone horribly wrong." - log_game("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying zombie instead") + log_reagent("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying zombie instead") M.reagents.remove_reagent(type, 20) else//easier to deal with @@ -362,7 +362,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING S.rabid = 1//Make them an angery boi M.reagents.remove_reagent(type, volume) to_chat(M, "A large glob of the tumour suddenly splits itself from your body. You feel grossed out and slimey...") - log_game("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying teratoma instead") + log_reagent("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying teratoma instead") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Zombie clones made!") if(87 to INFINITY) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm index 8348569fbb..bdc599a5e2 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm @@ -67,7 +67,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die M.alpha = 255 if(current_cycle == 0) originalmind = M.mind - log_game("FERMICHEM: [M] ckey: [M.key] became an astral ghost") + log_reagent("FERMICHEM: [M] ckey: [M.key] became an astral ghost") origin = M if (G == null) G = new(get_turf(M.loc)) @@ -100,29 +100,25 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die ..() /datum/reagent/fermi/astral/on_mob_delete(mob/living/carbon/M) - if(!G) - if(M.mind) - var/mob/living/simple_animal/astral/G2 = new(get_turf(M.loc)) - M.mind.transfer_to(G2)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. - to_chat(G, "[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") - log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") - if(!G2.mind) - qdel(G2) - originalmind.transfer_to(M) - else if(G.mind) - G.mind.transfer_to(origin) - qdel(G) + if(!(G?.mind)) + if(!G) + qdel(G) + return ..() + if(M.mind) //Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. + var/mob/living/simple_animal/astral/G2 = new(get_turf(M)) + M.mind.transfer_to(G2) + to_chat(G2, "[M]'s conciousness snaps back to them as [M.p_their()] astrogen runs out, kicking your projected mind out!'") + log_reagent("FERMICHEM: [G2.mind.name] has been booted out of [M] as their original mind came back as the Astrogen reagent ran out!") + G.mind.transfer_to(origin) + qdel(G) if(overdosed) to_chat(M, "The high volume of astrogen you just took causes you to black out momentarily as your mind snaps back to your body.") M.Sleeping(sleepytime, 0) antiGenetics = 255 - if(G)//just in case - qdel(G) - log_game("FERMICHEM: [M] has astrally returned to their body!") + log_reagent("FERMICHEM: [M] has astrally returned to their body!") if(M.mind && M.mind == originalmind) M.remove_status_effect(/datum/status_effect/chem/astral_insurance) - //AS.Remove(M) - ..() + return ..() //Okay so, this might seem a bit too good, but my counterargument is that it'll likely take all round to eventually kill you this way, then you have to be revived without a body. It takes approximately 50-80 minutes to die from this. /datum/reagent/fermi/astral/addiction_act_stage1(mob/living/carbon/M) @@ -137,7 +133,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die to_chat(M, "You notice your body starting to disappear, maybe you took too much Astrogen...?") M.alpha-- antiGenetics-- - log_game("FERMICHEM: [M] ckey: [M.key] has become addicted to Astrogen") + log_reagent("FERMICHEM: [M] ckey: [M.key] has become addicted to Astrogen") if(220) to_chat(M, "Your addiction is only getting worse as your body disappears. Maybe you should get some more, and fast?") M.alpha-- @@ -172,5 +168,5 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die message_admins("[M] (ckey: [M.ckey]) has become one with the universe, and have continuous memories thoughout their lives should they find a way to come back to life (such as an inteligence potion, midround antag, ghost role).") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Astral obliterations") qdel(M) //Approx 60minutes till death from initial addiction - log_game("FERMICHEM: [M] ckey: [M.key] has been obliterated from Astrogen addiction") + log_reagent("FERMICHEM: [M] ckey: [M.key] has been obliterated from Astrogen addiction") ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm index 1500d52b25..40077cd02a 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm @@ -37,7 +37,7 @@ //Main functions /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/M) //Teleports to chemistry! if(current_cycle == 0) - log_game("FERMICHEM: [M] ckey: [M.key] took eigenstasium") + log_reagent("FERMICHEM: [M] ckey: [M.key] took eigenstasium") //make hologram at return point Eigenstate = new(loc) @@ -55,7 +55,7 @@ if(cached_purity > 0.9) //Teleports you home if it's pure enough if(!location_created && data) //Just in case location_created = data["location_created"] - log_game("FERMICHEM: [M] ckey: [M.key] returned to [location_created] using eigenstasium") + log_reagent("FERMICHEM: [M] ckey: [M.key] returned to [location_created] using eigenstasium") do_sparks(5,FALSE,M) do_teleport(M, location_created, 0, asoundin = 'sound/effects/phasein.ogg') do_sparks(5,FALSE,M) @@ -78,7 +78,7 @@ /datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly . = ..() to_chat(M, "Oh god, you feel like your wavefunction is about to tear.") - log_game("FERMICHEM: [M] ckey: [M.key] has overdosed on eigenstasium") + log_reagent("FERMICHEM: [M] ckey: [M.key] has overdosed on eigenstasium") M.Jitter(20) metabolization_rate += 0.5 //So you're not stuck forever teleporting. @@ -92,7 +92,7 @@ /datum/reagent/fermi/eigenstate/addiction_act_stage1(mob/living/M) //Welcome to Fermis' wild ride. if(addiction_stage == 1) to_chat(M, "Your wavefunction feels like it's been ripped in half. You feel empty inside.") - log_game("FERMICHEM: [M] ckey: [M.key] has become addicted to eigenstasium") + log_reagent("FERMICHEM: [M] ckey: [M.key] has become addicted to eigenstasium") M.Jitter(10) M.adjust_nutrition(-M.nutrition/15) ..() @@ -158,7 +158,7 @@ M.DefaultCombatKnockdown(100) to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself.") M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE) - log_game("FERMICHEM: [M] ckey: [M.key] has become an alternative universe version of themselves.") + log_reagent("FERMICHEM: [M] ckey: [M.key] has become an alternative universe version of themselves.") M.reagents.remove_all_type(/datum/reagent, 100, 0, 1) /* for(var/datum/mood_event/Me in M) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 8a3a648863..82efabc4e2 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -156,7 +156,7 @@ to_chat(M, "You feel your tongue.... unfluffify...?") M.say("Pleh!") else - log_game("FERMICHEM: [M] ckey: [M.key]'s tongue has been made permanent") + log_reagent("FERMICHEM: [M] ckey: [M.key]'s tongue has been made permanent") /////////////////////////////////////////////////////////////////////////////////////////////// @@ -374,7 +374,7 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) catto.color = "#[H.dna.features["mcolor"]]" catto.pseudo_death = TRUE H.forceMove(catto) - log_game("FERMICHEM: [H] ckey: [H.key] has been made into a cute catto.") + log_reagent("FERMICHEM: [H] ckey: [H.key] has been made into a cute catto.") SSblackbox.record_feedback("tally", "fermi_chem", 1, "cats") if(H.InCritical()) perma = TRUE @@ -408,7 +408,7 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) H.say("*wag")//force update sprites. to_chat(H, "[words]") qdel(catto) - log_game("FERMICHEM: [H] ckey: [H.key] has returned to normal") + log_reagent("FERMICHEM: [H] ckey: [H.key] has returned to normal") /datum/reagent/fermi/secretcatchem/reaction_mob(var/mob/living/L) @@ -417,7 +417,7 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) if(catto.origin) var/mob/living/carbon/human/H = catto.origin H.stat = CONSCIOUS - log_game("FERMICHEM: [catto] ckey: [catto.key] has returned to normal.") + log_reagent("FERMICHEM: [catto] ckey: [catto.key] has returned to normal.") to_chat(catto, "Your body shifts back to normal!") H.forceMove(catto.loc) catto.mind.transfer_to(H) diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm deleted file mode 100644 index 17de8c806d..0000000000 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ /dev/null @@ -1,246 +0,0 @@ -//body bluids -/datum/reagent/consumable/semen - name = "Semen" - description = "Sperm from some animal. Useless for anything but insemination, really." - taste_description = "something salty" - taste_mult = 2 //Not very overpowering flavor - data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null) - reagent_state = LIQUID - color = "#FFFFFF" // rgb: 255, 255, 255 - can_synth = FALSE - nutriment_factor = 0.5 * REAGENTS_METABOLISM - -/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume) - if(!istype(T)) - return - if(reac_volume < 10) - return - - var/obj/effect/decal/cleanable/semen/S = locate() in T - if(!S) - S = new(T) - if(data["blood_DNA"]) - S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) - -/obj/effect/decal/cleanable/semen - name = "semen" - desc = null - gender = PLURAL - density = 0 - layer = ABOVE_NORMAL_TURF_LAYER - icon = 'icons/obj/genitals/effects.dmi' - icon_state = "semen1" - random_icon_states = list("semen1", "semen2", "semen3", "semen4") - -/obj/effect/decal/cleanable/semen/Initialize(mapload) - . = ..() - dir = GLOB.cardinals - add_blood_DNA(list("Non-human DNA" = "A+")) - -/obj/effect/decal/cleanable/semen/replace_decal(obj/effect/decal/cleanable/semen/S) - if(S.blood_DNA) - blood_DNA |= S.blood_DNA - return ..() - -/datum/reagent/consumable/femcum - name = "Female Ejaculate" - description = "Vaginal lubricant found in most mammals and other animals of similar nature. Where you found this is your own business." - taste_description = "something with a tang" // wew coders who haven't eaten out a girl. - taste_mult = 2 - data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null) - reagent_state = LIQUID - color = "#AAAAAA77" - can_synth = FALSE - nutriment_factor = 0.5 * REAGENTS_METABOLISM - -/obj/effect/decal/cleanable/femcum - name = "female ejaculate" - desc = null - gender = PLURAL - density = 0 - layer = ABOVE_NORMAL_TURF_LAYER - icon = 'icons/obj/genitals/effects.dmi' - icon_state = "fem1" - random_icon_states = list("fem1", "fem2", "fem3", "fem4") - blood_state = null - bloodiness = null - -/obj/effect/decal/cleanable/femcum/Initialize(mapload) - . = ..() - dir = GLOB.cardinals - add_blood_DNA(list("Non-human DNA" = "A+")) - -/obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F) - if(F.blood_DNA) - blood_DNA |= F.blood_DNA - return ..() - -/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume) - if(!istype(T)) - return - if(reac_volume < 10) - return - - var/obj/effect/decal/cleanable/femcum/S = locate() in T - if(!S) - S = new(T) - if(data["blood_DNA"]) - S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) - -//aphrodisiac & anaphrodisiac - -/datum/reagent/drug/aphrodisiac - name = "Crocin" - description = "Naturally found in the crocus and gardenia flowers, this drug acts as a natural and safe aphrodisiac." - taste_description = "strawberries" - color = "#FFADFF"//PINK, rgb(255, 173, 255) - can_synth = FALSE - -/datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M) - if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) - if((prob(min(current_cycle/2,5)))) - M.emote(pick("moan","blush")) - if(prob(min(current_cycle/4,10))) - var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.") - to_chat(M, "[aroused_message]") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/genits = H.adjust_arousal(current_cycle, aphro = TRUE) // redundant but should still be here - for(var/g in genits) - var/obj/item/organ/genital/G = g - to_chat(M, "[G.arousal_verb]!") - ..() - -/datum/reagent/drug/aphrodisiacplus - name = "Hexacrocin" - description = "Chemically condensed form of basic crocin. This aphrodisiac is extremely powerful and addictive in most animals.\ - Addiction withdrawals can cause brain damage and shortness of breath. Overdosage can lead to brain damage and a \ - permanent increase in libido (commonly referred to as 'bimbofication')." - taste_description = "liquid desire" - color = "#FF2BFF"//dark pink - addiction_threshold = 20 - overdose_threshold = 20 - can_synth = FALSE - -/datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M) - if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) - if(prob(5)) - if(prob(current_cycle)) - M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn...")) - else - M.emote(pick("moan","blush")) - if(prob(5)) - var/aroused_message - if(current_cycle>25) - aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!") - else - aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.") - to_chat(M, "[aroused_message]") - REMOVE_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/genits = H.adjust_arousal(100, aphro = TRUE) // redundant but should still be here - for(var/g in genits) - var/obj/item/organ/genital/G = g - to_chat(M, "[G.arousal_verb]!") - ..() - -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2) - ..() -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage3(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3) - - ..() -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage4(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) - ..() - -/datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M) - if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33)) - if(prob(5) && ishuman(M) && M.has_dna() && (M.client?.prefs.cit_toggles & BIMBOFICATION)) - if(!HAS_TRAIT(M,TRAIT_PERMABONER)) - to_chat(M, "Your libido is going haywire!") - ADD_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT) - ..() - -/datum/reagent/drug/anaphrodisiac - name = "Camphor" - description = "Naturally found in some species of evergreen trees, camphor is a waxy substance. When injested by most animals, it acts as an anaphrodisiac\ - , reducing libido and calming them. Non-habit forming and not addictive." - taste_description = "dull bitterness" - taste_mult = 2 - color = "#D9D9D9"//rgb(217, 217, 217) - reagent_state = SOLID - can_synth = FALSE - -/datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M) - if(M && M.client?.prefs.arousable && prob(16)) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/genits = H.adjust_arousal(-100, aphro = TRUE) - if(genits.len) - to_chat(M, "You no longer feel aroused.") - ..() - -/datum/reagent/drug/anaphrodisiacplus - name = "Hexacamphor" - description = "Chemically condensed camphor. Causes an extreme reduction in libido and a permanent one if overdosed. Non-addictive." - taste_description = "tranquil celibacy" - color = "#D9D9D9"//rgb(217, 217, 217) - reagent_state = SOLID - overdose_threshold = 20 - can_synth = FALSE - -/datum/reagent/drug/anaphrodisiacplus/on_mob_life(mob/living/M) - if(M && M.client?.prefs.arousable) - REMOVE_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/genits = H.adjust_arousal(-100, aphro = TRUE) - if(genits.len) - to_chat(M, "You no longer feel aroused.") - - ..() - -/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M) - if(M && M.client?.prefs.arousable && prob(5)) - to_chat(M, "You feel like you'll never feel aroused again...") - ADD_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT) - ..() - -//recipes -/datum/chemical_reaction/aphro - name = "crocin" - id = /datum/reagent/drug/aphrodisiac - results = list(/datum/reagent/drug/aphrodisiac = 6) - required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/oxygen = 2, /datum/reagent/water = 1) - required_temp = 400 - mix_message = "The mixture boils off a pink vapor..."//The water boils off, leaving the crocin - -/datum/chemical_reaction/aphroplus - name = "hexacrocin" - id = /datum/reagent/drug/aphrodisiacplus - results = list(/datum/reagent/drug/aphrodisiacplus = 1) - required_reagents = list(/datum/reagent/drug/aphrodisiac = 6, /datum/reagent/phenol = 1) - required_temp = 400 - mix_message = "The mixture rapidly condenses and darkens in color..." - -/datum/chemical_reaction/anaphro - name = "camphor" - id = /datum/reagent/drug/anaphrodisiac - results = list(/datum/reagent/drug/anaphrodisiac = 6) - required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/oxygen = 2, /datum/reagent/sulfur = 1) - required_temp = 400 - mix_message = "The mixture boils off a yellow, smelly vapor..."//Sulfur burns off, leaving the camphor - -/datum/chemical_reaction/anaphroplus - name = "pentacamphor" - id = /datum/reagent/drug/anaphrodisiacplus - results = list(/datum/reagent/drug/anaphrodisiacplus = 1) - required_reagents = list(/datum/reagent/drug/aphrodisiac = 5, /datum/reagent/acetone = 1) - required_temp = 300 - mix_message = "The mixture thickens and heats up slighty..." diff --git a/modular_citadel/icons/ui/screen_midnight.dmi b/modular_citadel/icons/ui/screen_midnight.dmi index a730c591ba..fc446a411c 100644 Binary files a/modular_citadel/icons/ui/screen_midnight.dmi and b/modular_citadel/icons/ui/screen_midnight.dmi differ diff --git a/modular_citadel/icons/ui/screen_operative.dmi b/modular_citadel/icons/ui/screen_operative.dmi index cb08f08ceb..9383b94718 100644 Binary files a/modular_citadel/icons/ui/screen_operative.dmi and b/modular_citadel/icons/ui/screen_operative.dmi differ diff --git a/modular_citadel/icons/ui/screen_plasmafire.dmi b/modular_citadel/icons/ui/screen_plasmafire.dmi index 5f8cd9d93c..97e577c7bd 100644 Binary files a/modular_citadel/icons/ui/screen_plasmafire.dmi and b/modular_citadel/icons/ui/screen_plasmafire.dmi differ diff --git a/modular_citadel/icons/ui/screen_slimecore.dmi b/modular_citadel/icons/ui/screen_slimecore.dmi index f2f0c88782..8f45ff3f76 100644 Binary files a/modular_citadel/icons/ui/screen_slimecore.dmi and b/modular_citadel/icons/ui/screen_slimecore.dmi differ diff --git a/strings/tips.txt b/strings/tips.txt index 0176420dd3..b135692778 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -37,6 +37,7 @@ As a Medical Doctor, treating plasmamen is not impossible! Salbutamol stops them As a Medical Doctor, you can point your penlight at people to create a medical hologram. This lets them know that you're coming to treat them. As a Medical Doctor, you can extract implants by holding an empty implant case in your offhand while performing the extraction step. As a Medical Doctor, clone scanning people will implant them with a health tracker that displays their vitals in the clone records. Useful to check on crew members that didn't activate suit sensors! +As a Medical Doctor, medical gauze stops bleeding as well as heals 5 brute damage, this even works on the dead! Make sure to always have some gauze on you to stop bleeding before dragging someone. As a Chemist, there are dozens of chemicals that can heal, and even more that can cause harm. Experiment! As a Chemist, some chemicals can only be synthesized by heating up the contents in the chemical heater. As a Chemist, you will be expected to supply crew with certain chemicals. For example, clonexadone and mannitol for the cryo tubes, unstable mutagen and saltpetre for botany as well as healing pills and patches for the front desk. @@ -264,7 +265,12 @@ As a Devil, as long as you control at least one other soul, you will automatical At which time a Devil's nameth is spake on the tongue of man, the Devil may appeareth. You can swap floor tiles by holding a crowbar in one hand and a stack of tiles in the other. When hacking doors, cutting and mending the "test light wire" will restore power to the door. +When hacking, remote singulars pluse when attached to a wire and pinged. This can allow you to hack things or set traps from far away. When crafting most items, you can either manually combine parts or use the crafting menu. Suit storage units not only remove blood and dirt from clothing, but also radiation! Remote devices will work when used through cameras. For example: Bluespace RPEDs and door remotes. Laser pointers can be upgraded by replacing its micro laser with a better one from RnD! Use a screwdriver on it to remove the old laser. Upgrading the laser pointer gives you better odds of stunning a cyborg, and even blinding people with sunglasses. +Being out of combat mode makes makes you deal less damage to people and objects when attacking. +Resting makes you deal less damage to people and objects when attacking. +You do not regenerate as much stamina while in combat mode. Resting (being on the ground) makes you regenerate stamina faster. +Remember to be in combat mode while in combat, as otherwise you will be penalized by taking more incoming damage and dealing less damage to your adversary. diff --git a/tgstation.dme b/tgstation.dme index e54d164852..0fe28e926d 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -137,6 +137,7 @@ #include "code\__HELPERS\_lists.dm" #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" +#include "code\__HELPERS\angles.dm" #include "code\__HELPERS\areas.dm" #include "code\__HELPERS\AStar.dm" #include "code\__HELPERS\cmp.dm" @@ -381,6 +382,7 @@ #include "code\datums\brain_damage\brain_trauma.dm" #include "code\datums\brain_damage\hypnosis.dm" #include "code\datums\brain_damage\imaginary_friend.dm" +#include "code\datums\brain_damage\magic.dm" #include "code\datums\brain_damage\mild.dm" #include "code\datums\brain_damage\phobia.dm" #include "code\datums\brain_damage\severe.dm" @@ -389,22 +391,20 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\armor_plate.dm" -#include "code\datums\components\art.dm" #include "code\datums\components\bane.dm" #include "code\datums\components\bouncy.dm" #include "code\datums\components\butchering.dm" #include "code\datums\components\caltrop.dm" #include "code\datums\components\chasm.dm" +#include "code\datums\components\combat_mode.dm" #include "code\datums\components\construction.dm" #include "code\datums\components\decal.dm" #include "code\datums\components\dejavu.dm" #include "code\datums\components\earprotection.dm" #include "code\datums\components\edit_complainer.dm" -#include "code\datums\components\empprotection.dm" #include "code\datums\components\explodable.dm" #include "code\datums\components\field_of_vision.dm" #include "code\datums\components\footstep.dm" -#include "code\datums\components\forced_gravity.dm" #include "code\datums\components\identification.dm" #include "code\datums\components\igniter.dm" #include "code\datums\components\infective.dm" @@ -439,7 +439,6 @@ #include "code\datums\components\summoning.dm" #include "code\datums\components\swarming.dm" #include "code\datums\components\tackle.dm" -#include "code\datums\components\tactical.dm" #include "code\datums\components\thermite.dm" #include "code\datums\components\uplink.dm" #include "code\datums\components\virtual_reality.dm" @@ -526,13 +525,17 @@ #include "code\datums\diseases\advance\symptoms\weight.dm" #include "code\datums\diseases\advance\symptoms\youth.dm" #include "code\datums\elements\_element.dm" +#include "code\datums\elements\art.dm" +#include "code\datums\elements\beauty.dm" #include "code\datums\elements\cleaning.dm" #include "code\datums\elements\dusts_on_catatonia.dm" #include "code\datums\elements\dusts_on_leaving_area.dm" #include "code\datums\elements\dwarfism.dm" #include "code\datums\elements\earhealing.dm" +#include "code\datums\elements\empprotection.dm" #include "code\datums\elements\firestacker.dm" #include "code\datums\elements\flavor_text.dm" +#include "code\datums\elements\forced_gravity.dm" #include "code\datums\elements\ghost_role_eligibility.dm" #include "code\datums\elements\mob_holder.dm" #include "code\datums\elements\polychromic.dm" @@ -542,6 +545,7 @@ #include "code\datums\elements\squish.dm" #include "code\datums\elements\swimming.dm" #include "code\datums\elements\sword_point.dm" +#include "code\datums\elements\tactical.dm" #include "code\datums\elements\update_icon_blocker.dm" #include "code\datums\elements\update_icon_updates_onmob.dm" #include "code\datums\elements\wuv.dm" @@ -732,6 +736,7 @@ #include "code\game\machinery\gulag_teleporter.dm" #include "code\game\machinery\harvester.dm" #include "code\game\machinery\hologram.dm" +#include "code\game\machinery\hypnochair.dm" #include "code\game\machinery\igniter.dm" #include "code\game\machinery\iv_drip.dm" #include "code\game\machinery\launch_pad.dm" @@ -1022,6 +1027,7 @@ #include "code\game\objects\items\devices\multitool.dm" #include "code\game\objects\items\devices\paicard.dm" #include "code\game\objects\items\devices\pipe_painter.dm" +#include "code\game\objects\items\devices\polycircuit.dm" #include "code\game\objects\items\devices\powersink.dm" #include "code\game\objects\items\devices\pressureplates.dm" #include "code\game\objects\items\devices\quantum_keycard.dm" @@ -1117,6 +1123,7 @@ #include "code\game\objects\items\tanks\tanks.dm" #include "code\game\objects\items\tanks\watertank.dm" #include "code\game\objects\items\tools\crowbar.dm" +#include "code\game\objects\items\tools\saw.dm" #include "code\game\objects\items\tools\screwdriver.dm" #include "code\game\objects\items\tools\weldingtool.dm" #include "code\game\objects\items\tools\wirecutters.dm" @@ -1995,6 +2002,7 @@ #include "code\modules\food_and_drinks\recipes\tablecraft\recipes_soup.dm" #include "code\modules\food_and_drinks\recipes\tablecraft\recipes_spaghetti.dm" #include "code\modules\games\cas.dm" +#include "code\modules\games\unum.dm" #include "code\modules\goonchat\browserOutput.dm" #include "code\modules\holiday\easter.dm" #include "code\modules\holiday\holidays.dm" @@ -2311,7 +2319,6 @@ #include "code\modules\mob\living\life.dm" #include "code\modules\mob\living\living.dm" #include "code\modules\mob\living\living_block.dm" -#include "code\modules\mob\living\living_combat.dm" #include "code\modules\mob\living\living_defense.dm" #include "code\modules\mob\living\living_defines.dm" #include "code\modules\mob\living\living_mobility.dm" @@ -2334,7 +2341,6 @@ #include "code\modules\mob\living\brain\say.dm" #include "code\modules\mob\living\brain\status_procs.dm" #include "code\modules\mob\living\carbon\carbon.dm" -#include "code\modules\mob\living\carbon\carbon_combat.dm" #include "code\modules\mob\living\carbon\carbon_defense.dm" #include "code\modules\mob\living\carbon\carbon_defines.dm" #include "code\modules\mob\living\carbon\carbon_movement.dm" @@ -2955,6 +2961,7 @@ #include "code\modules\reagents\reagent_containers\glass.dm" #include "code\modules\reagents\reagent_containers\hypospray.dm" #include "code\modules\reagents\reagent_containers\hypovial.dm" +#include "code\modules\reagents\reagent_containers\maunamug.dm" #include "code\modules\reagents\reagent_containers\medspray.dm" #include "code\modules\reagents\reagent_containers\patch.dm" #include "code\modules\reagents\reagent_containers\pill.dm" @@ -2972,6 +2979,7 @@ #include "code\modules\recycling\disposal\outlet.dm" #include "code\modules\recycling\disposal\pipe.dm" #include "code\modules\recycling\disposal\pipe_sorting.dm" +#include "code\modules\research\bepis.dm" #include "code\modules\research\designs.dm" #include "code\modules\research\destructive_analyzer.dm" #include "code\modules\research\experimentor.dm" @@ -3054,6 +3062,7 @@ #include "code\modules\research\techweb\_techweb.dm" #include "code\modules\research\techweb\_techweb_node.dm" #include "code\modules\research\techweb\nodes\alien_nodes.dm" +#include "code\modules\research\techweb\nodes\bepis_nodes.dm" #include "code\modules\research\techweb\nodes\biotech_nodes.dm" #include "code\modules\research\techweb\nodes\bluespace_nodes.dm" #include "code\modules\research\techweb\nodes\computer_hud_nodes.dm" @@ -3091,6 +3100,7 @@ #include "code\modules\ruins\icemoonruin_code\library.dm" #include "code\modules\ruins\lavalandruin_code\alien_nest.dm" #include "code\modules\ruins\lavalandruin_code\biodome_clown_planet.dm" +#include "code\modules\ruins\lavalandruin_code\elephantgraveyard.dm" #include "code\modules\ruins\lavalandruin_code\pizzaparty.dm" #include "code\modules\ruins\lavalandruin_code\puzzle.dm" #include "code\modules\ruins\lavalandruin_code\sloth.dm" @@ -3356,10 +3366,8 @@ #include "modular_citadel\code\datums\status_effects\chems.dm" #include "modular_citadel\code\game\objects\cit_screenshake.dm" #include "modular_citadel\code\game\objects\effects\temporary_visuals\souldeath.dm" -#include "modular_citadel\code\modules\admin\chat_commands.dm" #include "modular_citadel\code\modules\admin\holder2.dm" #include "modular_citadel\code\modules\admin\secrets.dm" -#include "modular_citadel\code\modules\client\client_defines.dm" #include "modular_citadel\code\modules\client\client_procs.dm" #include "modular_citadel\code\modules\client\preferences_savefile.dm" #include "modular_citadel\code\modules\client\preferences_toggles.dm" @@ -3426,5 +3434,4 @@ #include "modular_citadel\code\modules\reagents\chemistry\recipes\fermi.dm" #include "modular_citadel\code\modules\reagents\objects\clothes.dm" #include "modular_citadel\code\modules\reagents\objects\items.dm" -#include "modular_citadel\code\modules\reagents\reagents\cit_reagents.dm" // END_INCLUDE diff --git a/tgui-next/packages/tgui/interfaces/AirlockElectronics.js b/tgui-next/packages/tgui/interfaces/AirlockElectronics.js new file mode 100644 index 0000000000..f42afd1de2 --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/AirlockElectronics.js @@ -0,0 +1,138 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button, LabeledList, Section, Tabs } from '../components'; + +export const AirlockElectronics = props => { + const { act, data } = useBackend(props); + const regions = data.regions || []; + + const diffMap = { + 0: { + icon: 'times-circle', + }, + 1: { + icon: 'stop-circle', + }, + 2: { + icon: 'check-circle', + }, + }; + + const checkAccessIcon = accesses => { + let oneAccess = false; + let oneInaccess = false; + + accesses.forEach(element => { + if (element.req) { + oneAccess = true; + } + else { + oneInaccess = true; + } + }); + + if (!oneAccess && oneInaccess) { + return 0; + } + else if (oneAccess && oneInaccess) { + return 1; + } + else { + return 2; + } + }; + + return ( + +
    + + +
    +
    + + + {regions.map(region => { + const { name } = region; + const accesses = region.accesses || []; + const icon = diffMap[checkAccessIcon(accesses)].icon; + return ( + + {() => accesses.map(access => ( + +
    +
    + ); +}; diff --git a/tgui-next/packages/tgui/interfaces/Bepis.js b/tgui-next/packages/tgui/interfaces/Bepis.js new file mode 100644 index 0000000000..993af415dc --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/Bepis.js @@ -0,0 +1,112 @@ +import { multiline } from 'common/string'; +import { Fragment } from 'inferno'; +import { act } from '../byond'; +import { Section, LabeledList, Button, NumberInput, Box, Grid } from '../components'; + +export const Bepis = props => { + const { state } = props; + const { config, data } = state; + const { ref } = config; + const { + amount, + } = data; + return ( +
    +
    act(ref, 'toggle_power')} /> + )}> + All you need to know about the B.E.P.I.S. and you! + The B.E.P.I.S. performs hundreds of tests a second + using electrical and financial resources to invent + new products, or discover new technologies otherwise + overlooked for being too risky or too niche to produce! +
    +
    act(ref, 'account_reset')} /> + )}> + Console is currently being operated + by {data.account_owner ? data.account_owner : 'no one'}. +
    + + +
    + + + {data.stored_cash} + + + {data.accuracy_percentage}% + + + {data.positive_cash_offset} + + + {data.negative_cash_offset} + + + act(ref, 'amount', { + amount: value, + })} /> + + +
    + +
    + + + + ); +}; diff --git a/tgui-next/packages/tgui/interfaces/HypnoChair.js b/tgui-next/packages/tgui/interfaces/HypnoChair.js new file mode 100644 index 0000000000..00ef2e819d --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/HypnoChair.js @@ -0,0 +1,77 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Button, Icon, Input, LabeledList, Section } from '../components'; + +export const HypnoChair = props => { + const { act, data } = useBackend(props); + return ( + +
    + The Enhanced Interrogation Chamber is designed to induce a deep-rooted + trance trigger into the subject. Once the procedure is complete, + by using the implanted trigger phrase, the authorities are able to + ensure immediate and complete obedience and truthfulness. +
    +
    + + + {data.occupant.name ? data.occupant.name : 'No Occupant'} + + {!!data.occupied && ( + + {data.occupant.stat === 0 + ? 'Conscious' + : data.occupant.stat === 1 + ? 'Unconcious' + : 'Dead'} + + )} + +
    +
    + + +
    +
    + ); +};