diff --git a/SpacemanDMM.toml b/SpacemanDMM.toml new file mode 100644 index 0000000000..b827472254 --- /dev/null +++ b/SpacemanDMM.toml @@ -0,0 +1,2 @@ +[langserver] +dreamchecker = true diff --git a/_maps/RandomRuins/SpaceRuins/spacehermit.dmm b/_maps/RandomRuins/SpaceRuins/spacehermit.dmm index 8113c586ff..dd7e700146 100644 --- a/_maps/RandomRuins/SpaceRuins/spacehermit.dmm +++ b/_maps/RandomRuins/SpaceRuins/spacehermit.dmm @@ -145,9 +145,6 @@ "aE" = ( /turf/open/floor/plating/asteroid/airless, /area/ruin/powered) -"aF" = ( -/turf/open/floor/plating/asteroid, -/area/ruin/powered) "aG" = ( /obj/structure/sink/puddle, /turf/open/floor/plating/asteroid, @@ -241,7 +238,7 @@ /turf/closed/mineral/random/low_chance/earth_like, /area/ruin/powered) "bb" = ( -/turf/closed/mineral/random/earth_like, +/turf/closed/mineral/random/no_caves/earth_like, /area/ruin/powered) "bc" = ( /obj/item/circuitboard/machine/circuit_imprinter, @@ -1137,7 +1134,7 @@ ao ao ak af -aF +am bb bb bb @@ -1189,7 +1186,7 @@ an an ae ae -aF +am bb bb bb @@ -1223,8 +1220,8 @@ bb bb bb ba -aF -aF +am +am ba ba ba @@ -1241,7 +1238,7 @@ ar af at at -aF +am bb fp bb @@ -1275,10 +1272,10 @@ bb bb bb ad -aF -aF -aF -aF +am +am +am +am ba aH aJ @@ -1286,13 +1283,13 @@ aL bb bb aT -aF -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am +am aR bb bb @@ -1328,23 +1325,23 @@ bb bb ad au -aF +am aB -aF -aF -aF -aF -aF +am +am +am +am +am ba bb -aF -aF -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am +am +am bg bb fp @@ -1384,19 +1381,19 @@ bs aC bC WH -aF -aF -aF +am +am +am ba bb bb -aF -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am +am bb bb bb @@ -1432,23 +1429,23 @@ bb bb ad ax -aF +am aD -aF -aF -aF -aF +am +am +am +am bb bb bb aU bd -aF -aF +am +am bl bm -aF -aF +am +am bb bb bb @@ -1484,20 +1481,20 @@ bb bb ad ay -aF -aF -aF +am +am +am aG -aF -aF +am +am bb bb ba av be -aF -aF -aF +am +am +am bn bo bo @@ -1535,24 +1532,24 @@ bb bb bb ba -aF -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am +am bb bb bb bc bf -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am br bb bb @@ -1590,22 +1587,22 @@ bb bb bb bb -aF -aF -aF -aF -aF +am +am +am +am +am bb bb -aF -aF -aF -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am +am +am +am bb bb bb @@ -1642,21 +1639,21 @@ bb bb bb bb -aF -aF -aF -aF -aF +am +am +am +am +am aN -aF -aF -aF -aF +am +am +am +am aR -aF -aF -aF -aF +am +am +am +am bb bb fp @@ -1695,22 +1692,22 @@ bb bb bb ba -aF -aF -aF +am +am +am ba ba -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am +am +am +am +am +am ba ba ba @@ -1752,16 +1749,16 @@ ba aK ba ba -aF -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am +am bp -aF -aF +am +am aR ba ba @@ -1805,15 +1802,15 @@ ba fp ba aP -aF -aF -aF -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am +am +am +am aR ba ba @@ -1858,15 +1855,15 @@ ba ba aQ aP -aF -aF +am +am aR -aF -aF -aF -aF +am +am +am +am bb -aF +am ba ba aZ @@ -1910,12 +1907,12 @@ ba ba ba ba -aF -aF -aF -aF +am +am +am +am aP -aF +am bg bb bb @@ -1962,12 +1959,12 @@ bb bb ba ba -aF -aF -aF -aF -aF -aF +am +am +am +am +am +am aS bb fp @@ -2015,11 +2012,11 @@ bb bb ba bg -aF -aF -aF -aF -aF +am +am +am +am +am aS bb fp @@ -2066,12 +2063,12 @@ bb bb fp ba -aF -aF +am +am bj -aF -aF -aF +am +am +am aS fp bb @@ -2120,9 +2117,9 @@ ba ba aS bi -aF -aF -aF +am +am +am aS aS bb @@ -2171,10 +2168,10 @@ ba aZ ba aS -aF -aF -aF -aF +am +am +am +am aS aS ba diff --git a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm index 69b56946f2..209feb82e3 100644 --- a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm +++ b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm @@ -2688,7 +2688,7 @@ /obj/structure/window/reinforced{ dir = 1 }, -/obj/structure/piano{ +/obj/structure/musician/piano{ icon_state = "piano" }, /turf/open/floor/plasteel/grimy, diff --git a/_maps/RandomRuins/SpaceRuins/vaporwave.dmm b/_maps/RandomRuins/SpaceRuins/vaporwave.dmm index 75adc455b0..a1b2271d96 100644 --- a/_maps/RandomRuins/SpaceRuins/vaporwave.dmm +++ b/_maps/RandomRuins/SpaceRuins/vaporwave.dmm @@ -28,7 +28,7 @@ /turf/open/floor/holofloor/beach, /area/ruin/space/has_grav/powered/aesthetic) "i" = ( -/obj/structure/piano, +/obj/structure/musician/piano, /obj/structure/window{ dir = 8 }, diff --git a/_maps/RandomZLevels/Cabin.dmm b/_maps/RandomZLevels/Cabin.dmm index 4d07c02565..a0862213a2 100644 --- a/_maps/RandomZLevels/Cabin.dmm +++ b/_maps/RandomZLevels/Cabin.dmm @@ -713,7 +713,7 @@ /turf/open/floor/wood, /area/awaymission/cabin) "cz" = ( -/obj/structure/piano, +/obj/structure/musician/piano, /turf/open/floor/wood, /area/awaymission/cabin) "cA" = ( diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm index e9d592c107..c84acf0131 100644 --- a/_maps/RandomZLevels/caves.dmm +++ b/_maps/RandomZLevels/caves.dmm @@ -924,8 +924,8 @@ /area/awaymission/caves/BMP_asteroid/level_two) "cK" = ( /obj/structure/sign/warning/securearea{ - desc = "A warning sign which reads 'HOLY SHIT NIGGA WHAT ARE YOU DOING'."; - name = "\improper HOLY SHIT NIGGA WHAT ARE YOU DOING" + desc = "A warning sign which reads 'HOLY SHIT DUDE WHAT ARE YOU DOING'."; + name = "\improper HOLY SHIT DUDE WHAT ARE YOU DOING" }, /turf/closed/wall, /area/awaymission/caves/BMP_asteroid/level_two) diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index 0a08edb9b2..d85c8b12d6 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -761,7 +761,7 @@ }, /area/awaymission/moonoutpost19/syndicate) "bF" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/high_loot{ dir = 1 }, /turf/open/floor/plasteel/freezer{ @@ -4121,7 +4121,7 @@ }, /area/awaymission/moonoutpost19/research) "hP" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/high_loot{ dir = 4 }, /obj/effect/decal/cleanable/dirt, @@ -4473,7 +4473,7 @@ }, /area/awaymission/moonoutpost19/research) "iw" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/high_loot{ dir = 4 }, /obj/machinery/light/small{ @@ -4764,7 +4764,7 @@ }, /area/awaymission/moonoutpost19/arrivals) "iZ" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/high_loot{ dir = 1 }, /turf/open/floor/plasteel/freezer{ diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm index c24bf45f81..a40066df4f 100644 --- a/_maps/RandomZLevels/snowdin.dmm +++ b/_maps/RandomZLevels/snowdin.dmm @@ -5939,7 +5939,7 @@ /turf/open/floor/plasteel, /area/awaymission/snowdin/post/garage) "mD" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/high_loot{ dir = 1 }, /obj/machinery/light/small, @@ -8796,7 +8796,7 @@ /turf/open/floor/plasteel/showroomfloor, /area/awaymission/snowdin/post/cavern2) "tk" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/high_loot{ dir = 1 }, /turf/open/floor/plasteel/showroomfloor, @@ -9643,7 +9643,7 @@ /turf/open/floor/plasteel/showroomfloor, /area/awaymission/snowdin/post/cavern1) "vE" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/high_loot{ dir = 1 }, /turf/open/floor/plasteel/showroomfloor, diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 086067a6fb..ab83534102 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -1337,7 +1337,7 @@ /turf/open/floor/plasteel, /area/security/prison) "adf" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/prison{ dir = 1 }, /turf/open/floor/plasteel/freezer, @@ -11677,7 +11677,7 @@ /turf/open/floor/plating, /area/maintenance/starboard/fore) "aAs" = ( -/obj/structure/piano{ +/obj/structure/musician/piano{ icon_state = "piano" }, /turf/open/floor/plating, @@ -13056,7 +13056,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/cryopod) "aDL" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/structure/mirror{ @@ -13944,7 +13944,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/storage/eva) "aGk" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/structure/mirror{ @@ -21467,7 +21467,7 @@ /turf/open/floor/plating, /area/maintenance/port) "aZt" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/structure/mirror{ @@ -44066,7 +44066,6 @@ /area/science/misc_lab) "cbe" = ( /obj/structure/table/reinforced, -/obj/item/integrated_electronics/analyzer, /obj/item/integrated_electronics/debugger, /obj/item/integrated_electronics/wirer, /turf/open/floor/plasteel/white, @@ -55621,7 +55620,7 @@ }, /area/crew_quarters/theatre) "iTU" = ( -/obj/structure/piano{ +/obj/structure/musician/piano{ icon_state = "piano" }, /turf/open/floor/wood, @@ -56804,7 +56803,7 @@ /turf/open/floor/plating, /area/security/main) "myh" = ( -/obj/structure/piano, +/obj/structure/musician/piano, /obj/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/wood, @@ -57483,7 +57482,7 @@ /turf/open/floor/wood, /area/crew_quarters/bar) "oIW" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /turf/open/floor/mineral/titanium/blue, @@ -60606,7 +60605,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/pool) "ycd" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/structure/mirror{ diff --git a/_maps/map_files/CogStation/job_changes.dm b/_maps/map_files/CogStation/job_changes.dm new file mode 100644 index 0000000000..8b1e3e9172 --- /dev/null +++ b/_maps/map_files/CogStation/job_changes.dm @@ -0,0 +1,29 @@ +#define JOB_MODIFICATION_MAP_NAME "CogStation" + +//Medical +/datum/job/scientist/New() + ..() + MAP_JOB_CHECK + access += ACCESS_CHEMISTRY + minimal_access += ACCESS_CHEMISTRY + +//Science + +/datum/job/roboticist/New() + ..() + MAP_JOB_CHECK + access += list(ACCESS_MEDICAL, ACCESS_MORGUE) + minimal_access += list(ACCESS_MEDICAL, ACCESS_MORGUE) + +//Civilian +/datum/job/clown/New() + ..() + MAP_JOB_CHECK + access += ACCESS_MAINT_TUNNELS + minimal_access += ACCESS_MAINT_TUNNELS + +/datum/job/mime/New() + ..() + MAP_JOB_CHECK + access += ACCESS_MAINT_TUNNELS + minimal_access += ACCESS_MAINT_TUNNELS \ No newline at end of file diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 82ac8604ef..9a738f12ee 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -12048,7 +12048,7 @@ "aAm" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/vomit/old, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/newscaster{ @@ -12059,7 +12059,7 @@ /area/crew_quarters/toilet/auxiliary) "aAn" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/newscaster{ @@ -12071,7 +12071,7 @@ /area/crew_quarters/toilet/auxiliary) "aAo" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/newscaster{ @@ -19681,7 +19681,7 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "aNx" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/prison{ dir = 4 }, /obj/machinery/light/small{ @@ -26182,7 +26182,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/bar/atrium) "aWX" = ( -/obj/structure/piano{ +/obj/structure/musician/piano{ icon_state = "piano" }, /obj/machinery/airalarm{ @@ -59858,6 +59858,7 @@ /area/crew_quarters/heads/captain) "bXh" = ( /obj/structure/toilet{ + contents = newlist(/obj/item/toy/snappop/phoenix); dir = 4 }, /obj/machinery/light{ @@ -82141,7 +82142,7 @@ "cIa" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/vomit/old, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/newscaster{ @@ -82152,7 +82153,7 @@ /area/crew_quarters/toilet/restrooms) "cIb" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/newscaster{ @@ -82164,7 +82165,7 @@ /area/crew_quarters/toilet/restrooms) "cIc" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/newscaster{ @@ -89653,7 +89654,7 @@ }, /area/medical/storage) "cUP" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/effect/decal/cleanable/dirt, @@ -115313,7 +115314,7 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/structure/piano, +/obj/structure/musician/piano, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/crew_quarters/theatre/abandoned) @@ -116756,7 +116757,7 @@ /turf/open/floor/plasteel, /area/maintenance/port/aft) "dPN" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/effect/decal/cleanable/dirt, @@ -126145,7 +126146,6 @@ /area/quartermaster/storage) "hic" = ( /obj/structure/table/reinforced, -/obj/item/integrated_electronics/analyzer, /obj/item/integrated_electronics/debugger, /obj/item/integrated_electronics/wirer, /turf/open/floor/plasteel/white/side{ @@ -127144,7 +127144,6 @@ /area/ai_monitored/turret_protected/aisat_interior) "qhc" = ( /obj/structure/table/reinforced, -/obj/item/integrated_electronics/analyzer, /obj/item/integrated_electronics/debugger, /obj/item/integrated_electronics/wirer, /turf/open/floor/plasteel/white/side{ diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index 446fe3e519..abdf574918 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -19002,7 +19002,7 @@ "aEK" = ( /obj/structure/sign/poster/contraband/random, /turf/closed/wall/rust, -/area/hallway/secondary/entry) +/area/security/vacantoffice) "aEL" = ( /obj/machinery/door/airlock/maintenance{ req_access_txt = "12" @@ -21544,6 +21544,9 @@ pixel_x = -26 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "aIZ" = ( @@ -33904,7 +33907,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/item/integrated_electronics/analyzer, /obj/machinery/computer/security/telescreen/circuitry{ pixel_y = 30 }, @@ -56558,7 +56560,7 @@ pixel_x = -12; pixel_y = 2 }, -/obj/structure/toilet{ +/obj/structure/toilet/secret/prison{ pixel_y = 16 }, /obj/effect/turf_decal/tile/neutral{ @@ -56908,7 +56910,7 @@ /area/hallway/primary/central) "bKT" = ( /obj/effect/turf_decal/box, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/structure/mirror{ @@ -56941,7 +56943,7 @@ /area/crew_quarters/toilet/restrooms) "bKU" = ( /obj/effect/turf_decal/box, -/obj/structure/toilet{ +//obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/structure/mirror{ @@ -59908,7 +59910,7 @@ pixel_x = -12; pixel_y = 2 }, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 16 }, /obj/effect/turf_decal/tile/neutral{ @@ -62405,7 +62407,7 @@ name = "EMERGENCY STORAGE" }, /turf/closed/wall, -/area/hallway/secondary/entry) +/area/security/vacantoffice) "bSM" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/external{ @@ -62669,6 +62671,9 @@ pixel_x = -23 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "bTf" = ( @@ -62869,17 +62874,23 @@ /turf/closed/wall/rust, /area/hallway/secondary/exit/departure_lounge) "bTy" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/decal/cleanable/dirt, -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "2-4" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) +/turf/open/floor/plasteel, +/area/hallway/secondary/exit/departure_lounge) "bTz" = ( /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral, @@ -62934,6 +62945,9 @@ /obj/effect/turf_decal/tile/neutral, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bTE" = ( @@ -62988,7 +63002,7 @@ pixel_x = -12; pixel_y = 2 }, -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 16 }, /obj/effect/turf_decal/tile/neutral{ @@ -63096,6 +63110,9 @@ c_tag = "Arrivals Dock"; name = "shuttle camera" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ + dir = 10 + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bTO" = ( @@ -63168,17 +63185,17 @@ /turf/open/floor/plasteel/dark, /area/hallway/secondary/exit/departure_lounge) "bTS" = ( -/obj/docking_port/stationary{ - dir = 8; - dwidth = 3; - height = 5; - id = "commonmining_home"; - name = "SS13: Common Mining Dock"; - roundstart_template = /datum/map_template/shuttle/mining_common/meta; - width = 7 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, -/turf/open/floor/plating, -/area/hallway/secondary/entry) +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/wood, +/area/security/vacantoffice) "bTT" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 @@ -63287,8 +63304,11 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ - dir = 6 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer1{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "4-8" }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) @@ -63398,12 +63418,8 @@ /turf/open/floor/plasteel/showroomfloor, /area/security/warden) "bUl" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-8" - }, -/turf/open/floor/plating, -/area/hallway/secondary/entry) +/turf/closed/wall, +/area/security/vacantoffice) "bUm" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -63464,9 +63480,8 @@ /turf/open/floor/plasteel/dark, /area/hallway/secondary/exit/departure_lounge) "bUt" = ( -/obj/structure/sign/warning/electricshock, /turf/closed/wall/rust, -/area/hallway/secondary/entry) +/area/security/vacantoffice) "bUu" = ( /obj/structure/cable{ icon_state = "1-2" @@ -64674,11 +64689,21 @@ }, /area/maintenance/starboard/aft) "bWn" = ( -/obj/machinery/door/airlock/external{ - name = "Common Mining Dock" +/obj/machinery/door/airlock/maintenance{ + name = "Vacant Office" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/door/firedoor, /turf/open/floor/plasteel, -/area/hallway/secondary/entry) +/area/security/vacantoffice) "bWo" = ( /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ @@ -64718,6 +64743,15 @@ /area/security/warden) "bWq" = ( /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "2-8" + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bWr" = ( @@ -64799,17 +64833,8 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bWx" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/computer/shuttle/mining/common{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/hallway/secondary/entry) +/turf/closed/wall, +/area/security/vacantoffice) "bWy" = ( /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ @@ -65052,15 +65077,18 @@ dir = 4; pixel_x = -23 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 - }, /obj/effect/turf_decal/tile/blue{ dir = 8 }, /obj/effect/turf_decal/tile/red{ dir = 1 }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-4" + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bWV" = ( @@ -65105,6 +65133,9 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bWY" = ( @@ -65133,6 +65164,9 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ dir = 9 }, +/obj/structure/cable{ + icon_state = "1-8" + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bXa" = ( @@ -65289,6 +65323,9 @@ }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "bXo" = ( @@ -65367,6 +65404,9 @@ dir = 8 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "bXv" = ( @@ -65786,6 +65826,9 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ dir = 8 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bXY" = ( @@ -66680,6 +66723,9 @@ }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bZk" = ( @@ -67429,6 +67475,9 @@ /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer1{ dir = 1 }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "cal" = ( @@ -67587,7 +67636,7 @@ "cav" = ( /obj/structure/sign/poster/contraband/random, /turf/closed/wall, -/area/hallway/secondary/entry) +/area/security/vacantoffice) "caw" = ( /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -67848,6 +67897,10 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "caP" = ( @@ -67855,6 +67908,9 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ + dir = 5 + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "caQ" = ( @@ -70240,9 +70296,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "2-4" - }, /turf/open/floor/plating{ icon_state = "platingdmg1" }, @@ -74728,6 +74781,9 @@ }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel/dark, /area/hallway/secondary/entry) "cmk" = ( @@ -81480,8 +81536,18 @@ /turf/open/floor/plasteel/dark, /area/maintenance/port) "cyG" = ( -/turf/open/floor/plating, -/area/hallway/secondary/entry) +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/power/apc{ + areastring = "/area/security/vacant"; + name = "Vacant Office APC"; + pixel_y = 24 + }, +/obj/structure/table/wood, +/obj/item/flashlight/lamp/green, +/turf/open/floor/wood, +/area/security/vacantoffice) "cyI" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/sink/kitchen{ @@ -85332,6 +85398,9 @@ "cJp" = ( /obj/effect/turf_decal/tile/red, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ + dir = 10 + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "cJq" = ( @@ -87185,9 +87254,22 @@ "cZm" = ( /turf/closed/wall/rust, /area/security/prison) +"dbY" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1{ + dir = 1 + }, +/obj/structure/chair/stool, +/turf/open/floor/wood{ + icon_state = "wood-broken" + }, +/area/security/vacantoffice) "dis" = ( /turf/closed/wall/r_wall/rust, /area/bridge) +"dlg" = ( +/obj/machinery/light, +/turf/open/floor/wood, +/area/security/vacantoffice) "dxq" = ( /obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral{ @@ -87242,6 +87324,14 @@ icon_state = "panelscorched" }, /area/maintenance/starboard/fore) +"eaJ" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/airalarm/directional/west, +/obj/item/twohanded/required/kirbyplants/dead, +/turf/open/floor/wood, +/area/security/vacantoffice) "elZ" = ( /obj/machinery/status_display/evac, /turf/closed/wall/rust, @@ -87338,6 +87428,11 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"fkk" = ( +/turf/open/floor/wood{ + icon_state = "wood-broken6" + }, +/area/security/vacantoffice) "fyr" = ( /obj/machinery/light{ dir = 4 @@ -87362,6 +87457,11 @@ dir = 8 }, /area/hallway/primary/fore) +"gmF" = ( +/turf/open/floor/wood{ + icon_state = "wood-broken" + }, +/area/security/vacantoffice) "gnA" = ( /obj/machinery/airalarm{ dir = 1; @@ -87428,9 +87528,20 @@ /obj/structure/sign/departments/evac, /turf/closed/wall/rust, /area/hallway/secondary/exit/departure_lounge) +"gKu" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/wood, +/area/security/vacantoffice) "gMU" = ( /turf/closed/wall/r_wall/rust, /area/ai_monitored/turret_protected/ai_upload) +"gPA" = ( +/turf/open/floor/wood{ + icon_state = "wood-broken3" + }, +/area/security/vacantoffice) "hgW" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/structure/chair/stool, @@ -87452,6 +87563,12 @@ "hAb" = ( /turf/closed/wall/r_wall/rust, /area/security/courtroom) +"hDh" = ( +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/structure/closet/cardboard, +/obj/effect/spawner/bundle/costume/maid, +/turf/open/floor/wood, +/area/security/vacantoffice) "hNk" = ( /turf/closed/wall/r_wall/rust, /area/security/prison) @@ -87660,17 +87777,12 @@ /turf/closed/mineral/random/labormineral, /area/space/nearstation) "jQY" = ( -/obj/structure/cable{ - icon_state = "1-2" +/obj/structure/table/wood, +/obj/item/paper_bin, +/turf/open/floor/wood{ + icon_state = "wood-broken4" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/decal/cleanable/dirt, -/obj/structure/disposalpipe/segment, -/obj/item/clothing/under/costume/maid, -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/maintenance/starboard/aft) +/area/security/vacantoffice) "jRw" = ( /obj/structure/sign/poster/official/high_class_martini, /turf/closed/wall/r_wall, @@ -87753,6 +87865,18 @@ }, /turf/open/floor/wood, /area/maintenance/port/fore) +"jUX" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ + dir = 6 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/wood, +/area/security/vacantoffice) "jUZ" = ( /obj/item/poster/random_contraband, /obj/item/poster/random_contraband, @@ -87773,6 +87897,10 @@ "khA" = ( /turf/closed/wall/rust, /area/construction/mining/aux_base) +"koc" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1, +/turf/open/floor/wood, +/area/security/vacantoffice) "krJ" = ( /turf/closed/wall/rust, /area/hallway/secondary/exit/departure_lounge) @@ -87794,6 +87922,12 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plating, /area/maintenance/port/fore) +"kzw" = ( +/obj/structure/chair/office/dark{ + dir = 8 + }, +/turf/open/floor/wood, +/area/security/vacantoffice) "kIJ" = ( /turf/open/floor/wood{ icon_state = "wood-broken7" @@ -87803,6 +87937,11 @@ /obj/structure/sign/nanotrasen, /turf/closed/wall, /area/maintenance/port/fore) +"kXo" = ( +/obj/structure/table/wood/poker, +/obj/item/toy/cards/deck, +/turf/open/floor/wood, +/area/security/vacantoffice) "leX" = ( /obj/structure/chair/stool, /turf/open/floor/wood{ @@ -87883,6 +88022,17 @@ }, /turf/open/floor/plasteel/dark, /area/science/research) +"mKp" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -24 + }, +/obj/structure/table/wood, +/turf/open/floor/wood, +/area/security/vacantoffice) "mLN" = ( /obj/effect/decal/cleanable/dirt, /turf/closed/mineral/random/labormineral, @@ -87953,6 +88103,19 @@ }, /turf/open/space/basic, /area/hallway/secondary/entry) +"oUc" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/table/wood, +/obj/item/folder/paperwork, +/turf/open/floor/wood, +/area/security/vacantoffice) +"ppP" = ( +/turf/open/floor/wood{ + icon_state = "wood-broken7" + }, +/area/security/vacantoffice) "pCe" = ( /obj/effect/decal/cleanable/glass, /turf/open/floor/plating/asteroid/airless, @@ -88190,12 +88353,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/fore) "uqy" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/turf/open/floor/plating{ - icon_state = "platingdmg1" +/obj/machinery/light{ + dir = 1 }, -/area/maintenance/starboard/aft) +/turf/open/floor/wood, +/area/security/vacantoffice) "uxQ" = ( /obj/effect/decal/cleanable/ash, /turf/closed/mineral/random/labormineral, @@ -88203,9 +88365,20 @@ "uzR" = ( /turf/closed/wall/rust, /area/storage/primary) +"uGi" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/wood, +/area/security/vacantoffice) +"uRM" = ( +/turf/open/floor/wood, +/area/security/vacantoffice) "uWo" = ( /turf/closed/wall/rust, /area/security/checkpoint/medical) +"vle" = ( +/obj/structure/festivus, +/turf/open/floor/wood, +/area/security/vacantoffice) "vmu" = ( /obj/structure/table/wood, /obj/effect/turf_decal/tile/neutral{ @@ -88231,6 +88404,10 @@ /mob/living/simple_animal/pet/bumbles, /turf/open/floor/plasteel, /area/hydroponics) +"wiK" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/turf/open/floor/wood, +/area/security/vacantoffice) "wmX" = ( /turf/closed/wall/rust, /area/quartermaster/qm) @@ -88328,6 +88505,10 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel/dark, /area/security/prison) +"ykB" = ( +/obj/structure/chair/stool, +/turf/open/floor/wood, +/area/security/vacantoffice) (1,1,1) = {" aaa @@ -125762,7 +125943,7 @@ bOl bSJ bSI ukP -uqy +bGr bEg bAT bOC @@ -126016,10 +126197,10 @@ bNw bTP bUu bWh -bTy +cax cxB ceN -jQY +chZ cxB cjE bXb @@ -126270,15 +126451,15 @@ bOA bOH bSH bNw -bSr +bWx aEK -bSd -bUl -bSd -bUl -bSr bUt -bSd +bWx +bUt +bWx +bWx +bUt +bUt bXj ckS bUu @@ -126527,15 +126708,15 @@ bNM tYn aVM bNx -bSr +bWx cyG -cyG -cyG -cyG -cyG -cyG -cyG -bSr +mKp +oUc +eaJ +uRM +uRM +vle +bWx bXz ccB cgb @@ -126785,14 +126966,14 @@ bZW bWw bTq bSL -cyG -cyG -cyG -cyG -cyG -cyG -cyG -bSr +jQY +kzw +gmF +gKu +uRM +uRM +uRM +bWx bEg bEg bEg @@ -127041,15 +127222,15 @@ cad bhY car bTr -bSr -cyG -cyG -cyG -cyG -cyG -cyG -cyG -bSr +bWx +uqy +wiK +uGi +jUX +koc +dbY +dlg +bWx bYf ceU cgI @@ -127299,14 +127480,14 @@ bQQ bSN bTs cav -cyG -cyG -cyG -cyG -cyG -cyG -cyG -bSr +uRM +fkk +ppP +bTS +ykB +kXo +ykB +bWx bPJ bUN hxn @@ -127555,15 +127736,15 @@ bTk bXL bXx bPe -bSd -cyG -cyG -cyG +bUt +hDh +uRM +uRM bTS -cyG -cyG -cyG -bSr +uRM +ykB +gPA +bWx bPJ bQa hxn @@ -127815,12 +127996,12 @@ bTv krJ krJ krJ -bPe +bOc bWn bWx -bSr +bWx bSL -bSr +bWx bSr cgx hxn @@ -129096,7 +129277,7 @@ bMO bOR cak aIY -cmD +bTy bTe bXu bXn diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm index f761cee126..a307026453 100644 --- a/_maps/map_files/LambdaStation/lambda.dmm +++ b/_maps/map_files/LambdaStation/lambda.dmm @@ -1556,7 +1556,6 @@ dir = 8 }, /obj/structure/table, -/obj/item/integrated_electronics/analyzer, /obj/item/integrated_circuit_printer, /turf/open/floor/plasteel/dark, /area/science/nanite) @@ -3033,7 +3032,7 @@ /turf/open/floor/plasteel, /area/security/prison) "agR" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/prison{ dir = 8 }, /turf/open/floor/plasteel/freezer, @@ -30338,7 +30337,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/bar/atrium) "bbF" = ( -/obj/structure/piano, +/obj/structure/musician/piano, /obj/structure/window/reinforced{ dir = 8 }, @@ -59988,7 +59987,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "ccw" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/machinery/light/small{ @@ -60523,7 +60522,7 @@ /turf/open/floor/plating, /area/maintenance/fore) "cdE" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/effect/landmark/blobstart, @@ -60557,7 +60556,7 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet) "cdH" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/light/small{ @@ -62828,7 +62827,7 @@ }, /area/maintenance/aft) "ciL" = ( -/obj/structure/piano, +/obj/structure/musician/piano, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -83922,7 +83921,7 @@ /turf/open/floor/plating, /area/maintenance/port/fore) "cXf" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/light/small{ diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index a08aaf094f..9294516092 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -1028,7 +1028,7 @@ /obj/machinery/light/small{ dir = 4 }, -/obj/structure/toilet{ +/obj/structure/toilet/secret/prison{ dir = 4 }, /turf/open/floor/plasteel/freezer, @@ -15496,7 +15496,7 @@ }, /area/maintenance/fore) "aDP" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 8 }, /obj/machinery/light/small{ @@ -16890,7 +16890,7 @@ /turf/open/floor/plating, /area/maintenance/fore) "aGz" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 8 }, /obj/machinery/light/small{ @@ -18173,7 +18173,7 @@ /turf/open/floor/plating, /area/maintenance/fore) "aJa" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 8 }, /obj/machinery/light/small{ @@ -18200,7 +18200,7 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/restrooms) "aJc" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/machinery/light/small{ @@ -32280,7 +32280,7 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/captain/private) "bkL" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 13 }, /obj/machinery/light, @@ -40361,7 +40361,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/toilet/auxiliary) "bBp" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 8 }, /obj/machinery/light/small{ @@ -41832,7 +41832,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/toilet/auxiliary) "bEv" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 8 }, /obj/machinery/light/small{ @@ -43537,7 +43537,7 @@ /turf/open/floor/plating, /area/crew_quarters/toilet/auxiliary) "bHQ" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 8 }, /obj/machinery/light/small{ @@ -79574,7 +79574,7 @@ /turf/closed/wall, /area/crew_quarters/bar) "dhU" = ( -/obj/structure/piano, +/obj/structure/musician/piano, /obj/structure/window/reinforced{ dir = 8 }, @@ -81886,7 +81886,6 @@ /area/maintenance/aft) "gRS" = ( /obj/structure/table/reinforced, -/obj/item/integrated_electronics/analyzer, /obj/item/integrated_circuit_printer, /turf/open/floor/plasteel/white, /area/science/circuit) @@ -82471,7 +82470,6 @@ /turf/open/floor/plasteel/white, /area/science/circuit) "ohj" = ( -/obj/item/integrated_electronics/analyzer, /obj/item/integrated_electronics/debugger, /obj/item/integrated_electronics/wirer, /obj/structure/table/reinforced, diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index 2ca3c3deee..9f79e3ecba 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -11768,7 +11768,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/theatre) "atY" = ( -/obj/structure/piano{ +/obj/structure/musician/piano{ icon_state = "piano" }, /obj/machinery/light{ @@ -26358,7 +26358,6 @@ dir = 8 }, /obj/item/integrated_circuit_printer, -/obj/item/integrated_electronics/analyzer, /obj/item/integrated_electronics/debugger, /obj/item/integrated_electronics/wirer, /obj/effect/turf_decal/tile/neutral, diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index fc5f6e9778..0ccbf1623b 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -2285,7 +2285,7 @@ /turf/open/floor/plasteel, /area/security/prison) "ahb" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/prison{ dir = 8 }, /turf/open/floor/plasteel/freezer, @@ -9106,7 +9106,7 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/heads/captain) "avK" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /turf/open/floor/plasteel/freezer, @@ -14667,7 +14667,7 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/restrooms) "aIl" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 8 }, /obj/machinery/light/small{ @@ -16490,7 +16490,7 @@ /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/cafeteria/lunchroom) "aNc" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /obj/effect/landmark/start/assistant, @@ -21324,7 +21324,7 @@ "aYm" = ( /obj/structure/closet/crate/wooden/toy, /obj/item/lipstick/random, -/obj/item/clothing/gloves/color/rainbow/clown, +/obj/item/clothing/gloves/color/rainbow, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -27443,7 +27443,6 @@ /area/science/explab) "bmZ" = ( /obj/structure/table/reinforced, -/obj/item/integrated_electronics/analyzer, /obj/machinery/magnetic_controller{ autolink = 1; pixel_x = -28; @@ -43015,7 +43014,7 @@ /area/maintenance/department/engine) "bUb" = ( /obj/structure/grille/broken, -/obj/structure/piano, +/obj/structure/musician/piano, /turf/open/floor/plating, /area/maintenance/department/engine) "bUc" = ( @@ -47393,7 +47392,7 @@ /turf/open/floor/plasteel/grimy, /area/chapel/main/monastery) "cgO" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 8 }, /obj/machinery/light/small{ @@ -47734,7 +47733,7 @@ /turf/open/floor/plasteel/grimy, /area/chapel/main/monastery) "ciq" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ pixel_y = 8 }, /turf/open/floor/plasteel/showroomfloor, @@ -55939,7 +55938,7 @@ /turf/open/floor/carpet, /area/chapel/office) "kgR" = ( -/obj/structure/toilet{ +/obj/structure/toilet/secret/low_loot{ dir = 4 }, /turf/open/floor/plating, @@ -58271,7 +58270,7 @@ /turf/open/floor/plating, /area/chapel/office) "plA" = ( -/obj/structure/piano, +/obj/structure/musician/piano, /turf/open/floor/plasteel/dark, /area/maintenance/department/crew_quarters/dorms) "pmB" = ( @@ -60715,7 +60714,6 @@ /area/maintenance/department/crew_quarters/dorms) "vmG" = ( /obj/structure/table/reinforced, -/obj/item/integrated_electronics/analyzer, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index daff5e51ad..c9b81cefd9 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -14420,7 +14420,7 @@ /obj/machinery/light{ dir = 8 }, -/obj/structure/piano, +/obj/structure/musician/piano, /turf/open/indestructible/hotelwood, /area/centcom/holding) "Hk" = ( diff --git a/_maps/shuttles/emergency_bar.dmm b/_maps/shuttles/emergency_bar.dmm index 7c14d9ebd0..7bc7de9bf1 100644 --- a/_maps/shuttles/emergency_bar.dmm +++ b/_maps/shuttles/emergency_bar.dmm @@ -197,7 +197,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "aF" = ( -/obj/structure/piano{ +/obj/structure/musician/piano{ icon_state = "piano" }, /turf/open/floor/plasteel/grimy, diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index be0a4d0f59..14c78f90d0 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -114,12 +114,17 @@ //slowdown when in softcrit #define SOFTCRIT_ADD_SLOWDOWN 6 -//Attack types for checking shields/hit reactions -#define MELEE_ATTACK 1 -#define UNARMED_ATTACK 2 -#define PROJECTILE_ATTACK 3 -#define THROWN_PROJECTILE_ATTACK 4 -#define LEAP_ATTACK 5 +/// Attack types for check_block()/run_block(). Flags, combinable. +/// Attack was melee, whether or not armed. +#define ATTACK_TYPE_MELEE (1<<0) +/// Attack was with a gun or something that should count as a gun (but not if a gun shouldn't count for a gun, crazy right?) +#define ATTACK_TYPE_PROJECTILE (1<<1) +/// Attack was unarmed.. this usually means hand to hand combat. +#define ATTACK_TYPE_UNARMED (1<<2) +/// Attack was a thrown atom hitting the victim. +#define ATTACK_TYPE_THROWN (1<<3) +/// Attack was a bodyslam/leap/tackle. See: Xenomorph leap tackles. +#define ATTACK_TYPE_TACKLE (1<<4) //attack visual effects #define ATTACK_EFFECT_PUNCH "punch" @@ -252,4 +257,53 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default. #define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs. +/// Bitflags for check_block() and handle_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS. +/// Attack was not blocked +#define BLOCK_NONE NONE +/// Attack was blocked, do not do damage. THIS FLAG MUST BE THERE FOR DAMAGE/EFFECT PREVENTION! +#define BLOCK_SUCCESS (1<<1) +/// The below are for "metadata" on "how" the attack was blocked. + +/// Attack was and should be redirected according to list argument REDIRECT_METHOD (NOTE: the SHOULD here is important, as it says "the thing blocking isn't handling the reflecting for you so do it yourself"!) +#define BLOCK_SHOULD_REDIRECT (1<<2) +/// Attack was redirected (whether by us or by SHOULD_REDIRECT flagging for automatic handling) +#define BLOCK_REDIRECTED (1<<3) +/// Attack was blocked by something like a shield. +#define BLOCK_PHYSICAL_EXTERNAL (1<<4) +/// Attack was blocked by something worn on you. +#define BLOCK_PHYSICAL_INTERNAL (1<<5) +/// Attack outright missed because the target dodged. Should usually be combined with redirection passthrough or something (see martial arts) +#define BLOCK_TARGET_DODGED (1<<7) +/// Meta-flag for run_block/do_run_block : By default, BLOCK_SUCCESS tells do_run_block() to assume the attack is completely blocked and not continue the block chain. If this is present, it will continue to check other items in the chain rather than stopping. +#define BLOCK_CONTINUE_CHAIN (1<<8) + +/// For keys in associative list/block_return as we don't want to saturate our (somewhat) limited flags. +#define BLOCK_RETURN_REDIRECT_METHOD "REDIRECT_METHOD" + /// Pass through victim + #define REDIRECT_METHOD_PASSTHROUGH "passthrough" + /// Deflect at randomish angle + #define REDIRECT_METHOD_DEFLECT "deflect" + /// reverse 180 angle, basically (as opposed to "realistic" wall reflections) + #define REDIRECT_METHOD_REFLECT "reflect" + /// "do not taser the bad man with the desword" - actually aims at the firer/attacker rather than just reversing + #define REDIRECT_METHOD_RETURN_TO_SENDER "no_you" + +/// These keys are generally only applied to the list if real_attack is FALSE. Used incase we want to make "smarter" mob AI in the future or something. +/// Tells the caller how likely from 0 (none) to 100 (always) we are to reflect energy projectiles +#define BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE "reflect_projectile_chance" +/// Tells the caller how likely we are to block attacks from 0 to 100 in general +#define BLOCK_RETURN_NORMAL_BLOCK_CHANCE "normal_block_chance" +/// Tells the caller about how many hits we can soak on average before our blocking fails. +#define BLOCK_RETURN_BLOCK_CAPACITY "block_capacity" + +/// Default if the above isn't set in the list. +#define DEFAULT_REDIRECT_METHOD_PROJECTILE REDIRECT_METHOD_DEFLECT + +/// Block priorities +#define BLOCK_PRIORITY_HELD_ITEM 100 +#define BLOCK_PRIORITY_CLOTHING 50 +#define BLOCK_PRIORITY_WEAR_SUIT 75 +#define BLOCK_PRIORITY_UNIFORM 25 + +#define BLOCK_PRIORITY_DEFAULT BLOCK_PRIORITY_HELD_ITEM diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 1ef8b9bb66..53348b3467 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -179,7 +179,7 @@ // #define SPEECH_FORCED 7 #define COMSIG_MOB_ANTAG_ON_GAIN "mob_antag_on_gain" //from base of /datum/antagonist/on_gain(): (antag_datum) -#define COMSIG_MOB_SPELL_CAST_CHECK "mob_spell_cast_check" //called from base of /obj/effect/proc_holder/spell/cast_check(): (spell) +#define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //called from base of /obj/effect/proc_holder/spell/can_cast(): (spell) // /mob/living signals #define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs) @@ -190,8 +190,11 @@ #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 "comsig_mob_client_login" //sent when a mob/login() finishes: (client) +#define COMSIG_MOB_CLIENT_LOGOUT "comsig_mob_client_logout" //sent when a mob/logout() starts: (client) #define COMSIG_MOB_CLIENT_MOVE "comsig_mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc) #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) @@ -240,9 +243,14 @@ #define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) #define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args) #define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" //called on item when crossed by something (): (/atom/movable) +#define COMSIG_ITEM_WORN_OVERLAYS "item_worn_overlays" //from base of obj/item/worn_overlays(): (isinhands, icon_file, used_state, style_flags, list/overlays) +// THE FOLLOWING TWO BLOCKS SHOULD RETURN BLOCK FLAGS AS DEFINED IN __DEFINES/combat.dm! +#define COMSIG_ITEM_CHECK_BLOCK "check_block" //from base of obj/item/check_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +#define COMSIG_ITEM_RUN_BLOCK "run_block" //from base of obj/item/run_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) // /obj/item/clothing signals #define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () +#define COMSIG_SUIT_MADE_HELMET "suit_made_helmet" //from base of obj/item/clothing/suit/MakeHelmet(): (helmet) // /obj/item/implant signals #define COMSIG_IMPLANT_ACTIVATED "implant_activated" //from base of /obj/item/implant/proc/activate(): () diff --git a/code/__DEFINES/dye_keys.dm b/code/__DEFINES/dye_keys.dm new file mode 100644 index 0000000000..133f9c47d3 --- /dev/null +++ b/code/__DEFINES/dye_keys.dm @@ -0,0 +1,28 @@ +#define DYE_REGISTRY_UNDER "under" +#define DYE_REGISTRY_JUMPSKIRT "jumpskirt" +#define DYE_REGISTRY_GLOVES "gloves" +#define DYE_REGISTRY_SNEAKERS "sneakers" +#define DYE_REGISTRY_FANNYPACK "fannypack" +#define DYE_REGISTRY_BEDSHEET "bedsheet" + +#define DYE_RED "red" +#define DYE_ORANGE "orange" +#define DYE_YELLOW "yellow" +#define DYE_GREEN "green" +#define DYE_BLUE "blue" +#define DYE_PURPLE "purple" +#define DYE_BLACK "black" +#define DYE_WHITE "white" +#define DYE_RAINBOW "rainbow" +#define DYE_MIME "mime" +#define DYE_COSMIC "cosmic" +#define DYE_QM "qm" +#define DYE_LAW "law" +#define DYE_CAPTAIN "captain" +#define DYE_HOP "hop" +#define DYE_HOS "hos" +#define DYE_CE "ce" +#define DYE_RD "rd" +#define DYE_CMO "cmo" +#define DYE_REDCOAT "redcoat" +#define DYE_CLOWN "clown" diff --git a/code/__DEFINES/dynamic.dm b/code/__DEFINES/dynamic.dm index ae5b031c8b..da8a76e71e 100644 --- a/code/__DEFINES/dynamic.dm +++ b/code/__DEFINES/dynamic.dm @@ -7,6 +7,7 @@ #define WAROPS_ALWAYS_ALLOWED (1<<1) #define USE_PREF_WEIGHTS (1<<2) #define FORCE_IF_WON (1<<3) +#define USE_PREV_ROUND_WEIGHTS (1<<4) #define ONLY_RULESET (1<<0) #define HIGHLANDER_RULESET (1<<1) diff --git a/code/__DEFINES/instruments.dm b/code/__DEFINES/instruments.dm new file mode 100644 index 0000000000..3c414f87f4 --- /dev/null +++ b/code/__DEFINES/instruments.dm @@ -0,0 +1,29 @@ +#define INSTRUMENT_MIN_OCTAVE 1 +#define INSTRUMENT_MAX_OCTAVE 9 +#define INSTRUMENT_MIN_KEY 0 +#define INSTRUMENT_MAX_KEY 127 + +/// Max number of playing notes per instrument. +#define CHANNELS_PER_INSTRUMENT 128 + +/// Distance multiplier that makes us not be impacted by 3d sound as much. This is a multiplier so lower it is the closer we will pretend to be to people. +#define INSTRUMENT_DISTANCE_FALLOFF_BUFF 0.2 +/// How many tiles instruments have no falloff for +#define INSTRUMENT_DISTANCE_NO_FALLOFF 3 + +/// Maximum length a note should ever go for +#define INSTRUMENT_MAX_TOTAL_SUSTAIN (5 SECONDS) + +/// These are per decisecond. +#define INSTRUMENT_EXP_FALLOFF_MIN 1.025 //100/(1.025^50) calculated for [INSTRUMENT_MIN_SUSTAIN_DROPOFF] to be 30. +#define INSTRUMENT_EXP_FALLOFF_MAX 10 + +/// Minimum volume for when the sound is considered dead. +#define INSTRUMENT_MIN_SUSTAIN_DROPOFF 0 + +#define SUSTAIN_LINEAR 1 +#define SUSTAIN_EXPONENTIAL 2 + +// /datum/instrument instrument_flags +#define INSTRUMENT_LEGACY (1<<0) //Legacy instrument. Implies INSTRUMENT_DO_NOT_AUTOSAMPLE +#define INSTRUMENT_DO_NOT_AUTOSAMPLE (1<<1) //Do not automatically sample diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index f4954f8f05..fd50b8b70d 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -1,13 +1,5 @@ /*ALL DEFINES RELATED TO INVENTORY OBJECTS, MANAGEMENT, ETC, GO HERE*/ -//ITEM INVENTORY WEIGHT, FOR w_class -#define WEIGHT_CLASS_TINY 1 //Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money -#define WEIGHT_CLASS_SMALL 2 //Pockets can hold small and tiny items, ex: Flashlight, Multitool, Grenades, GPS Device -#define WEIGHT_CLASS_NORMAL 3 //Standard backpacks can carry tiny, small & normal items, ex: Fire extinguisher, Stunbaton, Gas Mask, Metal Sheets -#define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in a normal bag, ex: Defibrillator, Backpack, Space Suits -#define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons - Can not fit in Boh -#define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh - //Inventory depth: limits how many nested storage items you can access directly. //1: stuff in mob, 2: stuff in backpack, 3: stuff in box in backpack, etc #define INVENTORY_DEPTH 3 diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 55bfcaff79..4be0985fbc 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -67,6 +67,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) ) #define isdwarf(A) (is_species(A, /datum/species/dwarf)) #define isdullahan(A) (is_species(A, /datum/species/dullahan)) +#define isvampire(A) (is_species(A,/datum/species/vampire)) // Citadel specific species #define isipcperson(A) (is_species(A, /datum/species/ipc)) @@ -263,4 +264,4 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list( #define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob)) -#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs)) \ No newline at end of file +#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs)) diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers_planes.dm similarity index 90% rename from code/__DEFINES/layers.dm rename to code/__DEFINES/layers_planes.dm index 35947b320e..d0f9f8bc28 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers_planes.dm @@ -129,11 +129,20 @@ #define HUD_PLANE 21 #define HUD_LAYER 21 #define HUD_RENDER_TARGET "HUD_PLANE" -#define ABOVE_HUD_PLANE 22 -#define ABOVE_HUD_LAYER 22 + +#define VOLUMETRIC_STORAGE_BOX_PLANE 23 +#define VOLUMETRIC_STORAGE_BOX_LAYER 23 +#define VOLUMETRIC_STORAGE_BOX_RENDER_TARGET "VOLUME_STORAGE_BOX_PLANE" + +#define VOLUMETRIC_STORAGE_ITEM_PLANE 24 +#define VOLUMETRIC_STORAGE_ITEM_LAYER 24 +#define VOLUMETRIC_STORAGE_ITEM_RENDER_TARGET "VOLUME_STORAGE_ITEM_PLANE" + +#define ABOVE_HUD_PLANE 25 +#define ABOVE_HUD_LAYER 25 #define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE" -#define SPLASHSCREEN_LAYER 23 -#define SPLASHSCREEN_PLANE 23 +#define SPLASHSCREEN_LAYER 30 +#define SPLASHSCREEN_PLANE 30 #define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE" diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 9efffefce5..3fb149d071 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -465,7 +465,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define EGG_LAYING_MESSAGES list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.") // list of all null rod weapons -#define HOLY_WEAPONS /obj/item/nullrod, /obj/item/twohanded/dualsaber/hypereutactic/chaplain, /obj/item/gun/energy/laser/redtag/hitscan/chaplain, /obj/item/multitool/chaplain, /obj/item/melee/baseball_bat/chaplain +#define HOLY_WEAPONS /obj/item/nullrod, /obj/item/twohanded/dualsaber/hypereutactic/chaplain, /obj/item/gun/energy/laser/redtag/hitscan/chaplain, /obj/item/multitool/chaplain, /obj/item/clothing/gloves/fingerless/pugilist/chaplain, /obj/item/melee/baseball_bat/chaplain // Used by PDA and cartridge code to reduce repetitiveness of spritesheets #define PDAIMG(what) {""} diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm index 76c326cec0..4d40474a3c 100644 --- a/code/__DEFINES/movespeed_modification.dm +++ b/code/__DEFINES/movespeed_modification.dm @@ -59,6 +59,7 @@ #define MOVESPEED_ID_SPECIES "SPECIES_SPEED_MOD" +#define MOVESPEED_ID_SMALL_STRIDE "SMALL_STRIDE" #define MOVESPEED_ID_PRONE_DRAGGING "PRONE_DRAG" #define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY" #define MOVESPEED_ID_SHRINK_RAY "SHRUNKEN_SPEED_MODIFIER" @@ -78,4 +79,6 @@ #define MOVESPEED_ID_COLD "COLD" #define MOVESPEED_ID_HUNGRY "HUNGRY" #define MOVESPEED_ID_DAMAGE_SLOWDOWN "DAMAGE" -#define MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING "FLYING" \ No newline at end of file +#define MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING "FLYING" + +#define MOVESPEED_ID_CIRRHOSIS "CIRRHOSIS" \ No newline at end of file diff --git a/code/__DEFINES/radiation.dm b/code/__DEFINES/radiation.dm index 596a6a0378..ece997a7fc 100644 --- a/code/__DEFINES/radiation.dm +++ b/code/__DEFINES/radiation.dm @@ -45,9 +45,9 @@ Ask ninjanomnom if they're around // WARNING: The deines below could have disastrous consequences if tweaked incorrectly. See: The great SM purge of Oct.6.2017 // contamination_chance = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1/(steps*RAD_DISTANCE_COEFFICIENT), 1)) // contamination_strength = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT -#define RAD_MINIMUM_CONTAMINATION 350 // How strong does a radiation wave have to be to contaminate objects +#define RAD_MINIMUM_CONTAMINATION 300 // How strong does a radiation wave have to be to contaminate objects #define RAD_CONTAMINATION_CHANCE_COEFFICIENT 0.005 // Higher means higher strength scaling contamination chance -#define RAD_CONTAMINATION_STR_COEFFICIENT 0.3 // Higher means higher strength scaling contamination strength +#define RAD_CONTAMINATION_STR_COEFFICIENT 0.99 // Higher means higher strength scaling contamination strength #define RAD_DISTANCE_COEFFICIENT 1 // Lower means further rad spread -#define RAD_HALF_LIFE 90 // The half-life of contaminated objects \ No newline at end of file +#define RAD_HALF_LIFE 90 // The half-life of contaminated objects diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 581bb2bc29..73781154c5 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -20,6 +20,7 @@ #define CHANNEL_HIGHEST_AVAILABLE 1008 //CIT CHANGE - COMPENSATES FOR VORESOUND CHANNELS +#define MAX_INSTRUMENT_CHANNELS (128 * 6) #define SOUND_MINIMUM_PRESSURE 10 #define FALLOFF_SOUNDS 1 diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index a7ffd1c543..9a9133c196 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -99,7 +99,7 @@ #define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above. #define STATUS_EFFECT_NO_COMBAT_MODE /datum/status_effect/no_combat_mode //Wont allow combat mode and will disable it -#define STATUS_EFFECT_MESMERIZE /datum/status_effect/no_combat_mode/mesmerize //Just reskinned no_combat_mode +#define STATUS_EFFECT_MESMERIZE /datum/status_effect/mesmerize //Just reskinned no_combat_mode #define STATUS_EFFECT_ELECTROSTAFF /datum/status_effect/electrostaff //slows down victim diff --git a/code/__DEFINES/storage.dm b/code/__DEFINES/storage.dm new file mode 100644 index 0000000000..b4240455fe --- /dev/null +++ b/code/__DEFINES/storage.dm @@ -0,0 +1,47 @@ +// storage_flags variable on /datum/component/storage + +// Storage limits. These can be combined (and usually are combined). +/// Check max_items and contents.len when trying to insert +#define STORAGE_LIMIT_MAX_ITEMS (1<<0) +/// Check max_combined_w_class. +#define STORAGE_LIMIT_COMBINED_W_CLASS (1<<1) +/// Use the new volume system. Will automatically force rendering to use the new volume/baystation scaling UI so this is kind of incompatible with stuff like stack storage etc etc. +#define STORAGE_LIMIT_VOLUME (1<<2) +/// Use max_w_class +#define STORAGE_LIMIT_MAX_W_CLASS (1<<3) + +#define STORAGE_FLAGS_LEGACY_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_COMBINED_W_CLASS | STORAGE_LIMIT_MAX_W_CLASS) +#define STORAGE_FLAGS_VOLUME_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_VOLUME | STORAGE_LIMIT_MAX_W_CLASS) + +//ITEM INVENTORY WEIGHT, FOR w_class +/// Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money +#define WEIGHT_CLASS_TINY 1 +/// Pockets can hold small and tiny items, ex: Flashlight, Multitool, Grenades, GPS Device +#define WEIGHT_CLASS_SMALL 2 +/// Standard backpacks can carry tiny, small & normal items, ex: Fire extinguisher, Stunbaton, Gas Mask, Metal Sheets +#define WEIGHT_CLASS_NORMAL 3 +/// Items that can be weilded or equipped but not stored in a normal bag, ex: Defibrillator, Backpack, Space Suits +#define WEIGHT_CLASS_BULKY 4 +/// Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons - Can not fit in Boh +#define WEIGHT_CLASS_HUGE 5 +/// Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh +#define WEIGHT_CLASS_GIGANTIC 6 + +/// Macro for automatically getting the volume of an item from its w_class. +#define AUTO_SCALE_VOLUME(w_class) (2 ** w_class) +/// Macro for automatically getting the volume of a storage item from its max_w_class and max_combined_w_class. +#define AUTO_SCALE_STORAGE_VOLUME(w_class, max_combined_w_class) (AUTO_SCALE_VOLUME(w_class) * (max_combined_w_class / w_class)) + +// UI defines +/// Size of volumetric box icon +#define VOLUMETRIC_STORAGE_BOX_ICON_SIZE 32 +/// Size of EACH left/right border icon for volumetric boxes +#define VOLUMETRIC_STORAGE_BOX_BORDER_SIZE 1 +/// Minimum pixels an item must have in volumetric scaled storage UI +#define MINIMUM_PIXELS_PER_ITEM 6 +/// Maximum number of objects that will be allowed to be displayed using the volumetric display system. Arbitrary number to prevent server lockups. +#define MAXIMUM_VOLUMETRIC_ITEMS 256 +/// How much padding to give between items +#define VOLUMETRIC_STORAGE_ITEM_PADDING 1 +/// How much padding to give to edges +#define VOLUMETRIC_STORAGE_EDGE_PADDING 1 diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index a693b26b20..5aa0301bf6 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -50,17 +50,19 @@ #define INIT_ORDER_PROFILER 100 #define INIT_ORDER_FAIL2TOPIC 99 #define INIT_ORDER_TITLE 98 -#define INIT_ORDER_GARBAGE 97 -#define INIT_ORDER_DBCORE 95 -#define INIT_ORDER_BLACKBOX 94 -#define INIT_ORDER_SERVER_MAINT 93 -#define INIT_ORDER_INPUT 85 +#define INIT_ORDER_GARBAGE 95 +#define INIT_ORDER_DBCORE 93 +#define INIT_ORDER_BLACKBOX 92 +#define INIT_ORDER_SERVER_MAINT 91 +#define INIT_ORDER_INPUT 90 +#define INIT_ORDER_SOUNDS 85 #define INIT_ORDER_VIS 80 #define INIT_ORDER_RESEARCH 75 #define INIT_ORDER_EVENTS 70 #define INIT_ORDER_JOBS 65 #define INIT_ORDER_QUIRKS 60 #define INIT_ORDER_TICKER 55 +#define INIT_ORDER_INSTRUMENTS 53 #define INIT_ORDER_MAPPING 50 #define INIT_ORDER_NETWORKS 45 #define INIT_ORDER_ATOMS 30 @@ -100,6 +102,7 @@ #define FIRE_PRIORITY_PROCESS 25 #define FIRE_PRIORITY_THROWING 25 #define FIRE_PRIORITY_SPACEDRIFT 30 +#define FIRE_PRIORITY_INSTRUMENTS 30 #define FIRE_PRIORITY_FIELDS 30 #define FIRE_PRIOTITY_SMOOTHING 35 #define FIRE_PRIORITY_NETWORKS 40 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 476d99fd9b..e70e0ba743 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -147,6 +147,8 @@ #define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat. #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 +#define TRAIT_KI_VAMPIRE "ki-vampire" //when someone with this trait rolls maximum damage on a punch and stuns the target, they regain some stamina and do clone damage #define TRAIT_PASSTABLE "passtable" // mobility flag traits @@ -240,8 +242,8 @@ #define GHOSTROLE_TRAIT "ghostrole" #define APHRO_TRAIT "aphro" #define BLOODSUCKER_TRAIT "bloodsucker" -#define CLOTHING_TRAIT "clothing" //used for quirky carrygloves #define SHOES_TRAIT "shoes" //inherited from your sweet kicks +#define GLOVE_TRAIT "glove" //inherited by your cool gloves // unique trait sources, still defines #define STATUE_MUTE "statue" @@ -275,6 +277,7 @@ #define LOCKED_HELMET_TRAIT "locked-helmet" #define NINJA_SUIT_TRAIT "ninja-suit" #define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant" +#define MARTIAL_ARTIST_TRAIT "martial_artist" #define SLEEPING_CARP_TRAIT "sleeping_carp" #define RISING_BASS_TRAIT "rising_bass" #define ABDUCTOR_ANTAGONIST "abductor-antagonist" diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index 9afae12c30..5f78aeb740 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -112,7 +112,7 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) set desc = "Toggles seeing LocalOutOfCharacter chat" prefs.chat_toggles ^= CHAT_LOOC prefs.save_preferences() - src << "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel." + to_chat(src, "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.") SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /mob/living/carbon/proc/has_penis() diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index f16b566b00..a34b3ce67c 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -550,6 +550,27 @@ for(var/thing in flat_list) .[thing] = TRUE +/proc/deep_list2params(list/deep_list) + var/list/L = list() + for(var/i in deep_list) + var/key = i + if(isnum(key)) + L += "[key]" + continue + if(islist(key)) + key = deep_list2params(key) + else if(!istext(key)) + key = "[REF(key)]" + L += "[key]" + var/value = deep_list[key] + if(!isnull(value)) + if(islist(value)) + value = deep_list2params(value) + else if(!(istext(key) || isnum(key))) + value = "[REF(value)]" + L["[key]"] = "[value]" + return list2params(L) + //Picks from the list, with some safeties, and returns the "default" arg if it fails #define DEFAULTPICK(L, default) ((islist(L) && length(L)) ? pick(L) : default) diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index c95896d853..9b877e8fb0 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -116,4 +116,7 @@ GLOBAL_VAR_INIT(cmp_field, "name") if(a_sign != b_sign) return a_sign - b_sign else - return sorttext(b_name, a_name) \ No newline at end of file + return sorttext(b_name, a_name) + +/proc/cmp_item_block_priority_asc(obj/item/A, obj/item/B) + return A.block_priority - B.block_priority diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 7703b13018..7f5035347c 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -425,8 +425,7 @@ candidates -= M /proc/pollGhostCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE) - var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility)) - var/list/candidates = eligibility.get_all_ghost_role_eligible() + var/list/candidates = get_all_ghost_role_eligible() return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates) /proc/pollCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE, list/group = null) @@ -581,4 +580,4 @@ var/area/A = C.area if(GLOB.typecache_powerfailure_safe_areas[A.type]) continue - C.energy_fail(rand(duration_min,duration_max)) \ No newline at end of file + C.energy_fail(rand(duration_min,duration_max)) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 38e25b04c5..0c45a746d8 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -89,6 +89,14 @@ INVOKE_ASYNC(GLOBAL_PROC, /proc/init_ref_coin_values) //so the current procedure doesn't sleep because of UNTIL() + for(var/path in subtypesof(/area/holodeck)) + var/area/holodeck/A = path + var/list/compatibles = initial(A.compatible_holodeck_comps) + if(!compatibles || initial(A.abstract_type) == path) + continue + for(var/comp in compatibles) + LAZYADD(GLOB.holodeck_areas_prototypes[comp], A) + //creates every subtype of prototype (excluding prototype) and adds it to list L. //if no list/L is provided, one is created. /proc/init_subtypes(prototype, list/L) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index febd333578..e022c10007 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -209,7 +209,8 @@ "ipc_antenna" = "None", "flavor_text" = "", "meat_type" = "Mammalian", - "body_model" = MALE + "body_model" = MALE, + "body_size" = RESIZE_DEFAULT_SIZE )) /proc/random_hair_style(gender) diff --git a/code/__HELPERS/radiation.dm b/code/__HELPERS/radiation.dm index e082be7d1f..1570eededb 100644 --- a/code/__HELPERS/radiation.dm +++ b/code/__HELPERS/radiation.dm @@ -25,8 +25,22 @@ /proc/radiation_pulse(atom/source, intensity, range_modifier, log=FALSE, can_contaminate=TRUE) if(!SSradiation.can_fire) return - for(var/dir in GLOB.cardinals) - new /datum/radiation_wave(source, dir, intensity, range_modifier, can_contaminate) + var/area/A = get_area(source) + var/atom/nested_loc = source.loc + var/spawn_waves = TRUE + while(nested_loc != A) + if(nested_loc.rad_flags & RAD_PROTECT_CONTENTS) + spawn_waves = FALSE + break + nested_loc = nested_loc.loc + if(spawn_waves) + for(var/dir in GLOB.cardinals) + new /datum/radiation_wave(source, dir, intensity, range_modifier, can_contaminate) + + var/static/last_huge_pulse = 0 + if(intensity > 3000 && world.time > last_huge_pulse + 200) + last_huge_pulse = world.time + log = TRUE var/list/things = get_rad_contents(source) //copypasta because I don't want to put special code in waves to handle their origin for(var/k in 1 to things.len) @@ -35,11 +49,7 @@ continue thing.rad_act(intensity) - var/static/last_huge_pulse = 0 - if(intensity > 3000 && world.time > last_huge_pulse + 200) - last_huge_pulse = world.time - log = TRUE if(log) - var/turf/_source_T = isturf(source) ? source : get_turf(source) - log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [loc_name(_source_T)] ") + var/turf/_source_T = get_turf(source) + log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [loc_name(_source_T)][spawn_waves ? "" : " (contained by [nested_loc.name])"]") return TRUE diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 0a4af736dd..7cbfbd040a 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -320,8 +320,10 @@ parts += "[FOURSPACES]Nobody died this shift!" if(istype(SSticker.mode, /datum/game_mode/dynamic)) var/datum/game_mode/dynamic/mode = SSticker.mode + mode.update_playercounts() parts += "[FOURSPACES]Final threat level: [mode.threat_level]" parts += "[FOURSPACES]Final threat: [mode.threat]" + parts += "[FOURSPACES]Average threat: [mode.threat_average]" parts += "[FOURSPACES]Executed rules:" for(var/datum/dynamic_ruleset/rule in mode.executed_rules) parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - [rule.name]: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat" @@ -511,7 +513,7 @@ if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED) SSticker.show_roundend_report(owner.client, FALSE) -/datum/action/report/IsAvailable() +/datum/action/report/IsAvailable(silent = FALSE) return 1 /datum/action/report/Topic(href,href_list) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index ac97966eef..afa858afb7 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -8,10 +8,8 @@ /proc/invertHTML(HTMLstring) if(!istext(HTMLstring)) CRASH("Given non-text argument!") - return else if(length(HTMLstring) != 7) CRASH("Given non-HTML argument!") - return else if(length_char(HTMLstring) != 7) CRASH("Given non-hex symbols in argument!") var/textr = copytext(HTMLstring, 2, 4) @@ -1565,3 +1563,16 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) if(channels_to_use.len) world.TgsChatBroadcast() + +//Checks to see if either the victim has a garlic necklace or garlic in their blood +/proc/blood_sucking_checks(var/mob/living/carbon/target, check_neck, check_blood) + //Bypass this if the target isnt carbon. + if(!iscarbon(target)) + return TRUE + if(check_neck) + if(istype(target.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace)) + return FALSE + if(check_blood) + if(target.reagents.has_reagent(/datum/reagent/consumable/garlic)) + return FALSE + return TRUE diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 5367322d8e..f0c854c398 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -249,5 +249,11 @@ GLOBAL_LIST_INIT(bitfields, list( "COMBAT_FLAG_SOFT_STAMCRIT" = COMBAT_FLAG_SOFT_STAMCRIT, "COMBAT_FLAG_INTENTIONALLY_RESTING" = COMBAT_FLAG_INTENTIONALLY_RESTING, "COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST + ), + "storage_flags" = list( + "STORAGE_LIMIT_MAX_ITEMS" = STORAGE_LIMIT_MAX_ITEMS, + "STORAGE_LIMIT_MAX_W_CLASS" = STORAGE_LIMIT_MAX_W_CLASS, + "STORAGE_LIMIT_COMBINED_W_CLASS" = STORAGE_LIMIT_COMBINED_W_CLASS, + "STORAGE_LIMIT_VOLUME" = STORAGE_LIMIT_VOLUME ) )) diff --git a/code/_globalvars/lists/mapping.dm b/code/_globalvars/lists/mapping.dm index fb8863ebe7..bcf35859c3 100644 --- a/code/_globalvars/lists/mapping.dm +++ b/code/_globalvars/lists/mapping.dm @@ -50,3 +50,5 @@ GLOBAL_LIST_EMPTY_TYPED(areas_by_type, /area) GLOBAL_LIST_EMPTY(all_abstract_markers) GLOBAL_LIST_EMPTY(stationroom_landmarks) //List of all spawns for stationrooms + +GLOBAL_LIST_EMPTY(holodeck_areas_prototypes) //List of holodeck area prototypes per holodeck computer type \ No newline at end of file diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index bdc6ea2980..7c116cc606 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -334,7 +334,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." return var/datum/antagonist/cult/antag = mob_viewer.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(!antag) + if(!antag?.cult_team) return var/datum/objective/sacrifice/sac_objective = locate() in antag.cult_team.objectives diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 490f0aa0f0..328e008f10 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -367,7 +367,7 @@ blood_display.hud = src infodisplay += blood_display - vamprank_display = new /obj/screen/bloodsucker/rank_counter // Vampire Rank + vamprank_display = new /obj/screen/bloodsucker/rank_counter // Bloodsucker Rank vamprank_display.hud = src infodisplay += vamprank_display diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index f5eb8535a5..4ed286eb08 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -210,20 +210,6 @@ user.swap_hand(held_index) return TRUE -/obj/screen/close - name = "close" - layer = ABOVE_HUD_LAYER - plane = ABOVE_HUD_PLANE - icon_state = "backpack_close" - -/obj/screen/close/Initialize(mapload, new_master) - . = ..() - master = new_master - -/obj/screen/close/Click() - var/datum/component/storage/S = master - S.hide_from(usr) - return TRUE /obj/screen/drop name = "drop" @@ -406,30 +392,6 @@ else icon_state = "act_rest0" -/obj/screen/storage - name = "storage" - icon_state = "block" - screen_loc = "7,7 to 10,8" - layer = HUD_LAYER - plane = HUD_PLANE - -/obj/screen/storage/Initialize(mapload, new_master) - . = ..() - master = new_master - -/obj/screen/storage/Click(location, control, params) - if(world.time <= usr.next_move) - return TRUE - if(usr.incapacitated()) - return TRUE - if (ismecha(usr.loc)) // stops inventory actions in a mech - return TRUE - if(master) - var/obj/item/I = usr.get_active_held_item() - if(I) - master.attackby(null, I, usr, params) - return TRUE - /obj/screen/throw_catch name = "throw/catch" icon = 'icons/mob/screen_midnight.dmi' diff --git a/code/_onclick/hud/screen_objects/storage.dm b/code/_onclick/hud/screen_objects/storage.dm new file mode 100644 index 0000000000..db287565f2 --- /dev/null +++ b/code/_onclick/hud/screen_objects/storage.dm @@ -0,0 +1,110 @@ +/obj/screen/storage + name = "storage" + var/insertion_click = FALSE + +/obj/screen/storage/Initialize(mapload, new_master) + . = ..() + master = new_master + +/obj/screen/storage/Click(location, control, params) + if(!insertion_click) + return ..() + if(world.time <= usr.next_move) + return TRUE + if(usr.incapacitated()) + return TRUE + if (ismecha(usr.loc)) // stops inventory actions in a mech + return TRUE + if(master) + var/obj/item/I = usr.get_active_held_item() + if(I) + master.attackby(null, I, usr, params) + return TRUE + +/obj/screen/storage/boxes + name = "storage" + icon_state = "block" + screen_loc = "7,7 to 10,8" + layer = HUD_LAYER + plane = HUD_PLANE + insertion_click = TRUE + +/obj/screen/storage/close + name = "close" + layer = ABOVE_HUD_LAYER + plane = ABOVE_HUD_PLANE + icon_state = "backpack_close" + +/obj/screen/storage/close/Click() + var/datum/component/storage/S = master + S.close(usr) + return TRUE + +/obj/screen/storage/left + icon_state = "storage_start" + insertion_click = TRUE + +/obj/screen/storage/right + icon_state = "storage_end" + insertion_click = TRUE + +/obj/screen/storage/continuous + icon_state = "storage_continue" + insertion_click = TRUE + +/obj/screen/storage/volumetric_box + icon_state = "stored_continue" + var/obj/item/our_item + +/obj/screen/storage/volumetric_box/Initialize(mapload, new_master, our_item) + src.our_item = our_item + return ..() + +/obj/screen/storage/volumetric_box/Destroy() + our_item = null + return ..() + +/obj/screen/storage/volumetric_box/Click(location, control, params) + return our_item.Click(location, control, params) + +/obj/screen/storage/volumetric_box/center + icon_state = "stored_continue" + var/obj/screen/storage/stored_left/left + var/obj/screen/storage/stored_right/right + var/pixel_size + +/obj/screen/storage/volumetric_box/center/Initialize(mapload, new_master, our_item) + left = new(null, src, our_item) + right = new(null, src, our_item) + return ..() + +/obj/screen/storage/volumetric_box/center/Destroy() + QDEL_NULL(left) + QDEL_NULL(right) + return ..() + +/obj/screen/storage/volumetric_box/center/proc/on_screen_objects() + return list(src, left, right) + +/** + * Sets the size of this box screen object and regenerates its left/right borders. This includes the actual border's size! + */ +/obj/screen/storage/volumetric_box/center/proc/set_pixel_size(pixels) + if(pixel_size == pixels) + return + pixel_size = pixels + cut_overlays() + //our icon size is 32 pixels. + transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0) + left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE + right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE + add_overlay(left) + add_overlay(right) + +/obj/screen/storage/stored_left + icon_state = "stored_start" + appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM // Yes I know RESET_TRANSFORM is in APPEARANCE_UI but we're hard-asserting this incase someone changes it. + +/obj/screen/storage/stored_right + icon_state = "stored_end" + appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index f422e073b2..b0e1d39d9a 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -125,13 +125,13 @@ if(!CHECK_MOBILITY(user, MOBILITY_STAND)) totitemdamage *= 0.5 //CIT CHANGES END HERE - if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration)) + if((user != src) && run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user) & BLOCK_SUCCESS) return FALSE send_item_attack_message(I, user) I.do_stagger_action(src, user) if(I.force) apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage - if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW)) + if(I.damtype == BRUTE) if(prob(33)) I.add_mob_blood(src) var/turf/location = get_turf(src) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index f253bc543d..f11093cba7 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -449,3 +449,27 @@ key_mode = KEY_MODE_TEXT value_mode = VALUE_MODE_FLAG config_entry_value = list(GEN_VISIBLE_NO_CLOTHES, GEN_VISIBLE_NO_UNDIES, GEN_VISIBLE_NEVER) //refer to cit_helpers for all toggles. + +//Body size configs, the feature will be disabled if both min and max have the same value. +/datum/config_entry/number/body_size_min + config_entry_value = RESIZE_DEFAULT_SIZE + min_val = 0.1 //to avoid issues with zeros and negative values. + max_val = RESIZE_DEFAULT_SIZE + +/datum/config_entry/number/body_size_max + config_entry_value = RESIZE_DEFAULT_SIZE + min_val = RESIZE_DEFAULT_SIZE + +//Pun-Pun movement slowdown given to characters with a body size smaller than this value, +//to compensate for their smaller hitbox. +//To disable, just make sure the value is lower than 'body_size_min' +/datum/config_entry/number/threshold_body_size_slowdown + config_entry_value = RESIZE_DEFAULT_SIZE * 0.85 + min_val = 0 + max_val = RESIZE_DEFAULT_SIZE + +//multiplicative slowdown multiplier. See 'dna.update_body_size' for the operation. +//doesn't apply to floating or crawling mobs +/datum/config_entry/number/body_size_slowdown_multiplier + config_entry_value = 0.25 + min_val = 0.1 //To encourage folks to disable the slowdown through the above config instead. diff --git a/code/controllers/hooks.dm b/code/controllers/hooks.dm index f499a61ae7..fe6a49c854 100644 --- a/code/controllers/hooks.dm +++ b/code/controllers/hooks.dm @@ -27,13 +27,11 @@ var/hook_path = text2path("/hook/[hook]") if(!hook_path) CRASH("Invalid hook '/hook/[hook]' called.") - return 0 var/caller = new hook_path var/status = 1 for(var/P in typesof("[hook_path]/proc")) if(!call(caller, P)(arglist(args))) CRASH("Hook '[P]' failed or runtimed.") - status = 0 return status diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm index 8b068e5d67..3243a8d8c8 100644 --- a/code/controllers/subsystem/dcs.dm +++ b/code/controllers/subsystem/dcs.dm @@ -38,11 +38,17 @@ PROCESSING_SUBSYSTEM_DEF(dcs) if(istext(key)) value = arguments[key] if(!(istext(key) || isnum(key))) - key = REF(key) + if(islist(key)) // CITADEL EDIT + key = deep_list2params(key) + else + key = REF(key) key = "[key]" // Key is stringified so numbers dont break things if(!isnull(value)) if(!(istext(value) || isnum(value))) - value = REF(value) + if(islist(value)) // CITADEL EDIT + value = deep_list2params(value) + else + value = REF(value) named_arguments["[key]"] = value else fullid += "[key]" diff --git a/code/controllers/subsystem/fail2topic.dm b/code/controllers/subsystem/fail2topic.dm index 02e7bc7aab..78c4807c3f 100644 --- a/code/controllers/subsystem/fail2topic.dm +++ b/code/controllers/subsystem/fail2topic.dm @@ -21,9 +21,6 @@ SUBSYSTEM_DEF(fail2topic) DropFirewallRule() // Clear the old bans if any still remain - if (world.system_type == UNIX && enabled) - enabled = FALSE - subsystem_log("DISABLED - UNIX systems are not supported.") if(!enabled) flags |= SS_NO_FIRE can_fire = FALSE @@ -90,7 +87,10 @@ SUBSYSTEM_DEF(fail2topic) fail_counts -= ip rate_limiting -= ip - . = shell("netsh advfirewall firewall add rule name=\"[rule_name]\" dir=in interface=any action=block remoteip=[ip]") + if (world.system_type == UNIX) + . = shell("iptables -A [rule_name] -s [ip] -j DROP") + else + . = shell("netsh advfirewall firewall add rule name=\"[rule_name]\" dir=in interface=any action=block remoteip=[ip]") if (.) subsystem_log("Failed to ban [ip]. Exit code: [.].") @@ -105,7 +105,10 @@ SUBSYSTEM_DEF(fail2topic) active_bans = list() - . = shell("netsh advfirewall firewall delete rule name=\"[rule_name]\"") + if (world.system_type == UNIX) + . = shell("iptables -F [rule_name]") //Let's just assume that folks running linux are smart enough to have a dedicated chain configured for this. + else + . = shell("netsh advfirewall firewall delete rule name=\"[rule_name]\"") if (.) subsystem_log("Failed to drop firewall rule. Exit code: [.].") diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index de2ff17a97..0a60c6e5d3 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -14,6 +14,7 @@ SUBSYSTEM_DEF(persistence) var/list/saved_modes = list(1,2,3) var/list/saved_dynamic_rules = list(list(),list(),list()) var/list/saved_storytellers = list("foo","bar","baz") + var/list/average_dynamic_threat = 50 var/list/saved_maps var/list/saved_trophies = list() var/list/spawned_objects = list() @@ -191,6 +192,8 @@ SUBSYSTEM_DEF(persistence) if(!json) return saved_storytellers = json["data"] + if(saved_storytellers.len > 3) + average_dynamic_threat = saved_storytellers[4] saved_storytellers.len = 3 /datum/controller/subsystem/persistence/proc/LoadRecentMaps() @@ -434,9 +437,10 @@ SUBSYSTEM_DEF(persistence) saved_storytellers[3] = saved_storytellers[2] saved_storytellers[2] = saved_storytellers[1] saved_storytellers[1] = mode.storyteller.name + average_dynamic_threat = (mode.threat_average + average_dynamic_threat) / 2 var/json_file = file("data/RecentStorytellers.json") var/list/file_data = list() - file_data["data"] = saved_storytellers + file_data["data"] = saved_storytellers + average_dynamic_threat fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) diff --git a/code/controllers/subsystem/processing/chemistry.dm b/code/controllers/subsystem/processing/chemistry.dm index da31d65fb3..64a780c1ad 100644 --- a/code/controllers/subsystem/processing/chemistry.dm +++ b/code/controllers/subsystem/processing/chemistry.dm @@ -1,5 +1,4 @@ PROCESSING_SUBSYSTEM_DEF(chemistry) wait = 5 flags = SS_KEEP_TIMING - - + name = "Chemistry" diff --git a/code/controllers/subsystem/processing/circuit.dm b/code/controllers/subsystem/processing/circuit.dm index 880e7a16a8..4fdc9ad806 100644 --- a/code/controllers/subsystem/processing/circuit.dm +++ b/code/controllers/subsystem/processing/circuit.dm @@ -86,7 +86,6 @@ PROCESSING_SUBSYSTEM_DEF(circuit) circuit_fabricator_recipe_list["Tools"] = list( /obj/item/integrated_electronics/wirer, /obj/item/integrated_electronics/debugger, - /obj/item/integrated_electronics/analyzer, /obj/item/integrated_electronics/detailer, /obj/item/card/data, /obj/item/card/data/full_color, diff --git a/code/controllers/subsystem/processing/instruments.dm b/code/controllers/subsystem/processing/instruments.dm new file mode 100644 index 0000000000..a4e0d7703f --- /dev/null +++ b/code/controllers/subsystem/processing/instruments.dm @@ -0,0 +1,43 @@ +PROCESSING_SUBSYSTEM_DEF(instruments) + name = "Instruments" + wait = 0.5 + init_order = INIT_ORDER_INSTRUMENTS + flags = SS_KEEP_TIMING + priority = FIRE_PRIORITY_INSTRUMENTS + var/static/list/datum/instrument/instrument_data = list() //id = datum + var/static/list/datum/song/songs = list() + var/static/musician_maxlines = 600 + var/static/musician_maxlinechars = 300 + var/static/musician_hearcheck_mindelay = 5 + var/static/max_instrument_channels = MAX_INSTRUMENT_CHANNELS + var/static/current_instrument_channels = 0 + +/datum/controller/subsystem/processing/instruments/Initialize() + initialize_instrument_data() + return ..() + +/datum/controller/subsystem/processing/instruments/proc/on_song_new(datum/song/S) + songs += S + +/datum/controller/subsystem/processing/instruments/proc/on_song_del(datum/song/S) + songs -= S + +/datum/controller/subsystem/processing/instruments/proc/initialize_instrument_data() + for(var/path in subtypesof(/datum/instrument)) + var/datum/instrument/I = path + if(initial(I.abstract_type) == path) + continue + I = new path + I.Initialize() + instrument_data[I.id || "[I.type]"] = I + CHECK_TICK + +/datum/controller/subsystem/processing/instruments/proc/get_instrument(id_or_path) + return instrument_data["[id_or_path]"] + +/datum/controller/subsystem/processing/instruments/proc/reserve_instrument_channel(datum/instrument/I) + if(current_instrument_channels > max_instrument_channels) + return + . = SSsounds.reserve_sound_channel(I) + if(!isnull(.)) + current_instrument_channels++ diff --git a/code/controllers/subsystem/processing/status_effects.dm b/code/controllers/subsystem/processing/status_effects.dm index e8984a44cb..57b340b2ce 100644 --- a/code/controllers/subsystem/processing/status_effects.dm +++ b/code/controllers/subsystem/processing/status_effects.dm @@ -1,3 +1,4 @@ PROCESSING_SUBSYSTEM_DEF(status_effects) wait = 1 flags = SS_TICKER + name = "Status Effects" diff --git a/code/controllers/subsystem/processing/weather.dm b/code/controllers/subsystem/processing/weather.dm index 0a1b4fc609..ca067953cc 100644 --- a/code/controllers/subsystem/processing/weather.dm +++ b/code/controllers/subsystem/processing/weather.dm @@ -47,7 +47,6 @@ PROCESSING_SUBSYSTEM_DEF(weather) break if (!ispath(weather_datum_type, /datum/weather)) CRASH("run_weather called with invalid weather_datum_type: [weather_datum_type || "null"]") - return if (isnull(z_levels)) z_levels = SSmapping.levels_by_trait(initial(weather_datum_type.target_trait)) @@ -55,7 +54,6 @@ PROCESSING_SUBSYSTEM_DEF(weather) z_levels = list(z_levels) else if (!islist(z_levels)) CRASH("run_weather called with invalid z_levels: [z_levels || "null"]") - return var/datum/weather/W = new weather_datum_type(z_levels) W.telegraph() diff --git a/code/controllers/subsystem/sounds.dm b/code/controllers/subsystem/sounds.dm new file mode 100644 index 0000000000..5e7c5e6545 --- /dev/null +++ b/code/controllers/subsystem/sounds.dm @@ -0,0 +1,91 @@ +#define DATUMLESS "NO_DATUM" + +SUBSYSTEM_DEF(sounds) + name = "Sounds" + flags = SS_NO_FIRE + init_order = INIT_ORDER_SOUNDS + var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels + + // Hey uh these two needs to be initialized fast because the whole "things get deleted before init" thing. + /// Assoc list, "[channel]" = either the datum using it or TRUE for an unsafe-reserved (datumless reservation) channel + var/list/using_channels = list() + /// Assoc list datum = list(channel1, channel2, ...) for what channels something reserved. + var/list/using_channels_by_datum = list() + /// List of all available channels with associations set to TRUE for fast lookups/allocation. + var/list/available_channels + +/datum/controller/subsystem/sounds/Initialize() + setup_available_channels() + return ..() + +/datum/controller/subsystem/sounds/proc/setup_available_channels() + available_channels = list() + for(var/i in 1 to using_channels_max) + available_channels[num2text(i)] = TRUE + +/// Removes a channel from using list. +/datum/controller/subsystem/sounds/proc/free_sound_channel(channel) + channel = num2text(channel) + var/using = using_channels[channel] + using_channels -= channel + if(using) + using_channels_by_datum[using] -= channel + if(!length(using_channels_by_datum[using])) + using_channels_by_datum -= using + available_channels[channel] = TRUE + +/// Frees all the channels a datum is using. +/datum/controller/subsystem/sounds/proc/free_datum_channels(datum/D) + var/list/L = using_channels_by_datum[D] + if(!L) + return + for(var/channel in L) + using_channels -= channel + available_channels[channel] = TRUE + using_channels_by_datum -= D + +/// Frees all datumless channels +/datum/controller/subsystem/sounds/proc/free_datumless_channels() + free_datum_channels(DATUMLESS) + +/// NO AUTOMATIC CLEANUP - If you use this, you better manually free it later! Returns an integer for channel. +/datum/controller/subsystem/sounds/proc/reserve_sound_channel_datumless() + var/channel = random_available_channel_text() + if(!channel) //oh no.. + return FALSE + available_channels -= channel + using_channels[channel] = DATUMLESS + LAZYINITLIST(using_channels_by_datum[DATUMLESS]) + using_channels_by_datum[DATUMLESS] += channel + return text2num(channel) + +/// Reserves a channel for a datum. Automatic cleanup only when the datum is deleted. Returns an integer for channel. +/datum/controller/subsystem/sounds/proc/reserve_sound_channel(datum/D) + if(!D) //i don't like typechecks but someone will fuck it up + CRASH("Attempted to reserve sound channel without datum using the managed proc.") + var/channel = random_available_channel_text() + if(!channel) + return FALSE + available_channels -= channel + using_channels[channel] = D + LAZYINITLIST(using_channels_by_datum[D]) + using_channels_by_datum[D] += channel + return text2num(channel) + +/// Random available channel, returns text. +/datum/controller/subsystem/sounds/proc/random_available_channel_text() + return pick(available_channels) + +/// Random available channel, returns number +/datum/controller/subsystem/sounds/proc/random_available_channel() + return text2num(pick(available_channels)) + +/// If a channel is available +/datum/controller/subsystem/sounds/proc/is_channel_available(channel) + return available_channels[num2text(channel)] + +/// How many channels we have left. +/datum/controller/subsystem/sounds/proc/available_channels_left() + return length(available_channels) + +#undef DATUMLESS diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm index 0d854371aa..87158f021e 100644 --- a/code/controllers/subsystem/traumas.dm +++ b/code/controllers/subsystem/traumas.dm @@ -172,7 +172,7 @@ SUBSYSTEM_DEF(traumas) /obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/mecha/combat/gygax/dark, /obj/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate, /obj/item/cartridge/virus/frame, /obj/item/chameleon, /obj/item/storage/box/syndie_kit/cutouts, /obj/item/clothing/suit/space/hardsuit/syndi, /obj/item/card/emag, /obj/item/storage/toolbox/syndicate, /obj/item/storage/book/bible/syndicate, /obj/item/encryptionkey/binary, /obj/item/encryptionkey/syndicate, /obj/item/aiModule/syndicate, /obj/item/clothing/shoes/magboots/syndie, /obj/item/powersink, /obj/item/sbeacondrop, /obj/item/sbeacondrop/bomb, /obj/item/syndicatedetonator, /obj/item/shield/energy, /obj/item/assault_pod, /obj/item/slimepotion/slime/sentience/nuclear, /obj/item/stack/telecrystal, /obj/item/jammer, /obj/item/codespeak_manual/unlimited, - /obj/item/toy/cards/deck/syndicate, /obj/item/storage/secure/briefcase/syndie, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/toy/syndicateballoon, /obj/item/clothing/gloves/rapid, /obj/item/paper/fluff/ruins/thederelict/syndie_mission, /obj/item/organ/cyberimp/eyes/hud/security/syndicate, /obj/item/clothing/head/HoS/syndicate, + /obj/item/toy/cards/deck/syndicate, /obj/item/storage/secure/briefcase/syndie, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/toy/syndicateballoon, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/paper/fluff/ruins/thederelict/syndie_mission, /obj/item/organ/cyberimp/eyes/hud/security/syndicate, /obj/item/clothing/head/HoS/syndicate, /obj/machinery/computer/pod/old/syndicate, /obj/machinery/vending/medical/syndicate_access, /obj/item/mmi/syndie, /obj/item/target/syndicate, /obj/machinery/vending/cigarette/syndicate, /obj/item/robot_module/syndicate, /obj/item/clothing/mask/gas/syndicate, /obj/machinery/power/singularity_beacon/syndicate, /obj/item/clothing/head/syndicatefake, /obj/item/radio/headset/syndicate, /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate, /obj/item/pda/syndicate, /obj/item/clothing/suit/armor/vest/capcarapace/syndicate, /obj/item/gun/ballistic/automatic/flechette, /obj/item/ammo_box/magazine/flechette, /obj/item/clothing/suit/toggle/lawyer/black/syndie, /obj/item/melee/transforming/energy/sword/cx/traitor, /obj/structure/sign/poster/contraband/syndicate_pistol, /obj/structure/sign/poster/contraband/syndicate_recruitment, /obj/item/bedsheet/syndie, /obj/item/borg/upgrade/syndicate, /obj/item/tank/jetpack/oxygen/harness, /obj/item/firing_pin/implant/pindicate, /obj/item/reagent_containers/glass/bottle/traitor, /obj/item/storage/belt/military, diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 7d72951278..a202afd905 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -763,7 +763,7 @@ SUBSYSTEM_DEF(vote) remove_from_client() Remove(owner) -/datum/action/vote/IsAvailable() +/datum/action/vote/IsAvailable(silent = FALSE) return 1 /datum/action/vote/proc/remove_from_client() diff --git a/code/datums/action.dm b/code/datums/action.dm index 74df2bf9a1..f2f93ac40d 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -6,13 +6,15 @@ /datum/action var/name = "Generic Action" var/desc = null - var/obj/target = null + var/atom/target = null var/check_flags = 0 var/required_mobility_flags = MOBILITY_USE var/processing = FALSE var/obj/screen/movable/action_button/button = null var/buttontooltipstyle = "" var/transparent_when_unavailable = TRUE + var/use_target_appearance = FALSE + var/list/target_appearance_matrix //if set, will be used to transform the target button appearance as an arglist. var/button_icon = 'icons/mob/actions/backgrounds.dmi' //This is the file for the BACKGROUND icon var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND //And this is the state for the background icon @@ -88,14 +90,14 @@ /datum/action/proc/Trigger() if(!IsAvailable()) return FALSE - if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER) + if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, target) & COMPONENT_ACTION_BLOCK_TRIGGER) return FALSE return TRUE /datum/action/proc/Process() return -/datum/action/proc/IsAvailable() +/datum/action/proc/IsAvailable(silent = FALSE) if(!owner) return FALSE var/mob/living/L = owner @@ -116,29 +118,42 @@ return TRUE /datum/action/proc/UpdateButtonIcon(status_only = FALSE, force = FALSE) - if(button) - if(!status_only) - button.name = name - button.desc = desc - if(owner && owner.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND) - var/list/settings = owner.hud_used.get_action_buttons_icons() - if(button.icon != settings["bg_icon"]) - button.icon = settings["bg_icon"] - if(button.icon_state != settings["bg_state"]) - button.icon_state = settings["bg_state"] - else - if(button.icon != button_icon) - button.icon = button_icon - if(button.icon_state != background_icon_state) - button.icon_state = background_icon_state + if(!button) + return + if(!status_only) + button.name = name + button.desc = desc + if(owner && owner.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND) + var/list/settings = owner.hud_used.get_action_buttons_icons() + if(button.icon != settings["bg_icon"]) + button.icon = settings["bg_icon"] + if(button.icon_state != settings["bg_state"]) + button.icon_state = settings["bg_state"] + else + if(button.icon != button_icon) + button.icon = button_icon + if(button.icon_state != background_icon_state) + button.icon_state = background_icon_state + if(!use_target_appearance) ApplyIcon(button, force) - if(!IsAvailable()) - button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0) - else - button.color = rgb(255,255,255,255) - return 1 + else if(target && button.appearance_cache != target.appearance) //replace with /ref comparison if this is not valid. + var/mutable_appearance/M = new(target) + M.layer = FLOAT_LAYER + M.plane = FLOAT_PLANE + if(target_appearance_matrix) + var/list/L = target_appearance_matrix + M.transform = matrix(L[1], L[2], L[3], L[4], L[5], L[6]) + button.cut_overlays() + button.add_overlay(M) + button.appearance_cache = target.appearance + + if(!IsAvailable(TRUE)) + button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0) + else + button.color = rgb(255,255,255,255) + return 1 /datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button, force = FALSE) if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force)) @@ -165,6 +180,7 @@ /datum/action/item_action check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_LYING|AB_CHECK_CONSCIOUS button_icon_state = null + use_target_appearance = TRUE // If you want to override the normal icon being the item // then change this to an icon state @@ -188,23 +204,6 @@ I.ui_action_click(owner, src) return 1 -/datum/action/item_action/ApplyIcon(obj/screen/movable/action_button/current_button, force) - if(button_icon && button_icon_state) - // If set, use the custom icon that we set instead - // of the item appearence - ..() - else if(target && current_button.appearance_cache != target.appearance) //replace with /ref comparison if this is not valid. - var/obj/item/I = target - var/old_layer = I.layer - var/old_plane = I.plane - I.layer = FLOAT_LAYER //AAAH - I.plane = FLOAT_PLANE //^ what that guy said - current_button.cut_overlays() - current_button.add_overlay(I) - I.layer = old_layer - I.plane = old_plane - current_button.appearance_cache = I.appearance - /datum/action/item_action/toggle_light name = "Toggle Light" @@ -302,23 +301,13 @@ name = "Toggle Friendly Fire \[ON\]" ..() -/datum/action/item_action/synthswitch - name = "Change Synthesizer Instrument" - desc = "Change the type of instrument your synthesizer is playing as." - -/datum/action/item_action/synthswitch/Trigger() - if(istype(target, /obj/item/instrument/piano_synth)) - var/obj/item/instrument/piano_synth/synth = target - return synth.selectInstrument() - return ..() - /datum/action/item_action/vortex_recall name = "Vortex Recall" desc = "Recall yourself, and anyone nearby, to an attuned hierophant beacon at any time.
If the beacon is still attached, will detach it." icon_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "vortex_recall" -/datum/action/item_action/vortex_recall/IsAvailable() +/datum/action/item_action/vortex_recall/IsAvailable(silent = FALSE) if(istype(target, /obj/item/hierophant_club)) var/obj/item/hierophant_club/H = target if(H.teleporting) @@ -330,7 +319,7 @@ background_icon_state = "bg_clock" buttontooltipstyle = "clockcult" -/datum/action/item_action/clock/IsAvailable() +/datum/action/item_action/clock/IsAvailable(silent = FALSE) if(!is_servant_of_ratvar(owner)) return 0 return ..() @@ -339,7 +328,7 @@ name = "Create Judicial Marker" desc = "Allows you to create a stunning Judicial Marker at any location in view. Click again to disable." -/datum/action/item_action/clock/toggle_visor/IsAvailable() +/datum/action/item_action/clock/toggle_visor/IsAvailable(silent = FALSE) if(!is_servant_of_ratvar(owner)) return 0 if(istype(target, /obj/item/clothing/glasses/judicial_visor)) @@ -418,7 +407,7 @@ /datum/action/item_action/jetpack_stabilization name = "Toggle Jetpack Stabilization" -/datum/action/item_action/jetpack_stabilization/IsAvailable() +/datum/action/item_action/jetpack_stabilization/IsAvailable(silent = FALSE) var/obj/item/tank/jetpack/J = target if(!istype(J) || !J.on) return 0 @@ -475,7 +464,7 @@ /datum/action/item_action/organ_action check_flags = AB_CHECK_CONSCIOUS -/datum/action/item_action/organ_action/IsAvailable() +/datum/action/item_action/organ_action/IsAvailable(silent = FALSE) var/obj/item/organ/I = target if(!I.owner) return 0 @@ -644,32 +633,32 @@ return FALSE if(target) var/obj/effect/proc_holder/S = target - S.Click() + S.Trigger(usr) return TRUE -/datum/action/spell_action/IsAvailable() +/datum/action/spell_action/IsAvailable(silent = FALSE) if(!target) return FALSE return TRUE /datum/action/spell_action/spell -/datum/action/spell_action/spell/IsAvailable() +/datum/action/spell_action/spell/IsAvailable(silent = FALSE) if(!target) return FALSE var/obj/effect/proc_holder/spell/S = target if(owner) - return S.can_cast(owner, FALSE, TRUE) + return S.can_cast(owner, FALSE, silent) return FALSE /datum/action/spell_action/alien -/datum/action/spell_action/alien/IsAvailable() +/datum/action/spell_action/alien/IsAvailable(silent = FALSE) if(!target) return FALSE var/obj/effect/proc_holder/alien/ab = target if(owner) - return ab.cost_check(ab.check_turf,owner,1) + return ab.cost_check(ab.check_turf,owner,silent) return FALSE @@ -711,7 +700,7 @@ button.maptext_width = 24 button.maptext_height = 12 -/datum/action/cooldown/IsAvailable() +/datum/action/cooldown/IsAvailable(silent = FALSE) return next_use_time <= world.time /datum/action/cooldown/proc/StartCooldown() diff --git a/code/datums/browser.dm b/code/datums/browser.dm index 8b82c1812e..5b1df6cb68 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -39,7 +39,7 @@ //title_image = ntitle_image /datum/browser/proc/add_stylesheet(name, file) - if (istype(name, /datum/asset/spritesheet)) + if(istype(name, /datum/asset/spritesheet)) var/datum/asset/spritesheet/sheet = name stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]" else diff --git a/code/datums/components/crafting/glassware.dm b/code/datums/components/crafting/glassware/glassware.dm similarity index 58% rename from code/datums/components/crafting/glassware.dm rename to code/datums/components/crafting/glassware/glassware.dm index 22d7e01f8a..2b57837c5d 100644 --- a/code/datums/components/crafting/glassware.dm +++ b/code/datums/components/crafting/glassware/glassware.dm @@ -14,26 +14,32 @@ name = "Glass working tools" desc = "A lovely belt of most the tools you will need to shape, mold, and refine glass into more advanced shapes." icon_state = "glass_tools" - tool_behaviour = TOOL_GLASS_CUT + tool_behaviour = TOOL_GLASS_CUT //Cutting takes 20 ticks /obj/item/glasswork/blowing_rod name = "Glass working blow rod" desc = "A hollow metal stick made for glass blowing." icon_state = "blowing_rods_unused" - tool_behaviour = TOOL_BLOW + tool_behaviour = TOOL_BLOW //Rods take 5 ticks -/obj/item/glasswork/glass_base +/obj/item/glasswork/glass_base //Welding takes 30 ticks name = "Glass fodder sheet" desc = "A sheet of glass set aside for glass working" icon_state = "glass_base" var/next_step = null var/rod = /obj/item/glasswork/blowing_rod -/obj/item/lens - name = "Optical lens" - desc = "Good for selling or crafting, by itself its useless" - icon = 'icons/obj/chemical.dmi' - icon_state = "glass_optics" +/obj/item/tea_plate + name = "Tea Plate" + desc = "A polished plate for a tea cup. How fancy!" + icon = 'icons/obj/glass_ware.dmi' + icon_state = "tea_plate" + +/obj/item/tea_cup + name = "Tea Cup" + desc = "A glass cup made for fake tea!" + icon = 'icons/obj/glass_ware.dmi' + icon_state = "tea_plate" //////////////////////Chem Disk///////////////////// //Two Steps // @@ -49,8 +55,9 @@ /obj/item/glasswork/glass_base/dish/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_GLASS_CUT) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/dish_part1 name = "Half chem dish sheet" @@ -61,8 +68,9 @@ /obj/item/glasswork/glass_base/dish_part1/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_GLASS_CUT) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + qdel(src) //////////////////////Lens////////////////////////// //Six Steps // @@ -78,8 +86,9 @@ /obj/item/glasswork/glass_base/glass_lens/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_GLASS_CUT) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/glass_lens_part1 name = "Glass fodder sheet" @@ -90,8 +99,9 @@ /obj/item/glasswork/glass_base/glass_lens_part1/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_WELDER) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,30, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/glass_lens_part2 name = "Glass fodder sheet" @@ -102,8 +112,9 @@ /obj/item/glasswork/glass_base/glass_lens_part2/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_WELDER) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,30, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/glass_lens_part3 name = "Glass fodder sheet" @@ -114,9 +125,10 @@ /obj/item/glasswork/glass_base/glass_lens_part3/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_BLOW) - new next_step(user.loc, 1) - qdel(src) - qdel(I) + if(do_after(user,5, target = src)) + new next_step(user.loc, 1) + qdel(src) + qdel(I) /obj/item/glasswork/glass_base/glass_lens_part4 name = "Glass fodder sheet" @@ -127,29 +139,31 @@ /obj/item/glasswork/glass_base/glass_lens_part4/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_GLASS_CUT) - new next_step(user.loc, 1) - new rod(user.loc, 1) - qdel(src) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/glass_lens_part5 name = "Unpolished glass lens" - desc = "A small unpolished glass lens. Could be polished with some cloth." - icon = 'icons/obj/chemical.dmi' + desc = "A small unpolished glass lens. Could be polished with some silk." + icon = 'icons/obj/glass_ware.dmi' icon_state = "glass_optics" next_step = /obj/item/glasswork/glass_base/glass_lens_part6 /obj/item/glasswork/glass_base/glass_lens_part5/attackby(obj/item/I, mob/user, params) ..() - if(istype(I, /obj/item/stack/sheet/cloth)) - new next_step(user.loc, 1) - qdel(src) + if(istype(I, /obj/item/stack/sheet/silk)) + if(do_after(user,10, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/glass_lens_part6 name = "Unrefined glass lens" desc = "A small polished glass lens. Just needs to be refined with some sandstone." - icon = 'icons/obj/chemical.dmi' + icon = 'icons/obj/glass_ware.dmi' icon_state = "glass_optics" - next_step = /obj/item/lens + next_step = /obj/item/glasswork/glass_base/lens /obj/item/glasswork/glass_base/glass_lens_part6/attackby(obj/item/I, mob/user, params) ..() @@ -171,8 +185,9 @@ /obj/item/glasswork/glass_base/spouty/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_GLASS_CUT) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/spouty_part2 name = "Glass fodder sheet" @@ -183,8 +198,9 @@ /obj/item/glasswork/glass_base/spouty_part2/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_WELDER) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,30, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/spouty_part3 name = "Glass fodder sheet" @@ -195,9 +211,10 @@ /obj/item/glasswork/glass_base/spouty_part3/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_BLOW) - new next_step(user.loc, 1) - qdel(src) - qdel(I) + if(do_after(user,5, target = src)) + new next_step(user.loc, 1) + qdel(src) + qdel(I) /obj/item/glasswork/glass_base/spouty_part4 name = "Glass fodder sheet" @@ -208,9 +225,10 @@ /obj/item/glasswork/glass_base/spouty_part4/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_GLASS_CUT) - new next_step(user.loc, 1) - new rod(user.loc, 1) - qdel(src) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) //////////////////////Small Bulb Flask////////////// //Two Steps // @@ -226,8 +244,9 @@ /obj/item/glasswork/glass_base/flask_small/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_WELDER) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,30, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/flask_small_part1 name = "Metled glass" @@ -238,9 +257,10 @@ /obj/item/glasswork/glass_base/flask_small_part1/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_BLOW) - new next_step(user.loc, 1) - qdel(src) - qdel(I) + if(do_after(user,5, target = src)) + new next_step(user.loc, 1) + qdel(src) + qdel(I) /obj/item/glasswork/glass_base/flask_small_part2 name = "Metled glass" @@ -251,9 +271,10 @@ /obj/item/glasswork/glass_base/flask_small_part2/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_GLASS_CUT) - new next_step(user.loc, 1) - new rod(user.loc, 1) - qdel(src) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) //////////////////////Large Bulb Flask////////////// //Two Steps // @@ -269,8 +290,9 @@ /obj/item/glasswork/glass_base/flask_large/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_WELDER) - new next_step(user.loc, 1) - qdel(src) + if(do_after(user,30, target = src)) + new next_step(user.loc, 1) + qdel(src) /obj/item/glasswork/glass_base/flask_large_part1 name = "Metled glass" @@ -281,9 +303,10 @@ /obj/item/glasswork/glass_base/flask_large_part1/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_BLOW) - new next_step(user.loc, 1) - qdel(src) - qdel(I) + if(do_after(user,5, target = src)) + new next_step(user.loc, 1) + qdel(src) + qdel(I) /obj/item/glasswork/glass_base/flask_large_part2 name = "Metled glass" @@ -294,6 +317,138 @@ /obj/item/glasswork/glass_base/flask_large_part2/attackby(obj/item/I, mob/user, params) ..() if(I.tool_behaviour == TOOL_GLASS_CUT) - new next_step(user.loc, 1) - new rod(user.loc, 1) - qdel(src) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) + +//////////////////////Tea Plates//////////////////// +//Three Steps // +//Sells for 1200 cr, takes 5 glass shets // +//Usefull for selling and chemical things // +//////////////////////////////////////////////////// + +/obj/item/glasswork/glass_base/tea_plate + name = "Glass fodder sheet" + desc = "A set of glass sheets set aside for glass working, this one is ideal for a tea plate, how fancy! Needs to be heated with some tools." + next_step = /obj/item/glasswork/glass_base/tea_plate1 + +/obj/item/glasswork/glass_base/tea_plate/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_WELDER) + if(do_after(user,30, target = src)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/tea_plate1 + name = "Metled glass" + desc = "A blob of metled glass, this one is ideal for a tea plate. Needs to be blown with some tools." + icon_state = "glass_base_molding" + next_step = /obj/item/glasswork/glass_base/tea_plate2 + +/obj/item/glasswork/glass_base/tea_plate1/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_BLOW) + if(do_after(user,5, target = src)) + new next_step(user.loc, 1) + qdel(src) + qdel(I) + +/obj/item/glasswork/glass_base/tea_plate2 + name = "Metled glass" + desc = "A blob of metled glass on the end of a blowing rod. Needs to be cut off with some tools." + icon_state = "blowing_rods_inuse" + next_step = /obj/item/glasswork/glass_base/tea_plate3 + +/obj/item/glasswork/glass_base/tea_plate2/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/tea_plate3 + name = "Disk of glass" + desc = "A disk of glass that can be cant be used for much. Needs to be polished with some silk." + icon_state = "glass_base_half" + next_step = /obj/item/tea_plate + +/obj/item/glasswork/glass_base/tea_plate3/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/stack/sheet/silk)) + if(do_after(user,10, target = src)) + new next_step(user.loc, 1) + qdel(src) + +//////////////////////Tea Cup/////////////////////// +//Four Steps // +//Sells for 1800 cr, takes 6 glass shets // +//Usefull for selling and chemical things // +//////////////////////////////////////////////////// + +/obj/item/glasswork/glass_base/tea_cup + name = "Glass fodder sheet" + desc = "A set of glass sheets set aside for glass working, this one is ideal for a tea cup, how fancy! Needs to be heated with some tools." + next_step = /obj/item/glasswork/glass_base/tea_cup1 + +/obj/item/glasswork/glass_base/tea_cup/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_WELDER) + if(do_after(user,30, target = src)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/tea_cup1 + name = "Metled glass" + desc = "A blob of metled glass, this one is ideal for a tea cup. Needs to be blown with some tools." + icon_state = "glass_base_molding" + next_step = /obj/item/glasswork/glass_base/tea_cup2 + +/obj/item/glasswork/glass_base/tea_cup1/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_BLOW) + if(do_after(user,5, target = src)) + new next_step(user.loc, 1) + qdel(src) + qdel(I) + +/obj/item/glasswork/glass_base/tea_cupe2 + name = "Metled glass" + desc = "A blob of metled glass on the end of a blowing rod. Needs to be cut off with some tools." + icon_state = "blowing_rods_inuse" + next_step = /obj/item/glasswork/glass_base/tea_cup3 + +/obj/item/glasswork/glass_base/tea_cup2/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_GLASS_CUT) + if(do_after(user,20, target = src)) + new next_step(user.loc, 1) + new rod(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/tea_cup3 + name = "Disk of glass" + desc = "A bowl of glass that can be cant be used for much. Needs to be polished with some silk." + icon_state = "glass_base_half" + next_step = /obj/item/glasswork/glass_base/tea_cup4 + +/obj/item/glasswork/glass_base/cup3/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/stack/sheet/silk)) + if(do_after(user,10, target = src)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/tea_cup4 + name = "Disk of glass" + desc = "A bowl of polished glass that can be cant be used for much. Needs some more glass to make a handle." + icon_state = "glass_base_half" + next_step = /obj/item/tea_cup + +/obj/item/glasswork/glass_base/cup4/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/stack/sheet/glass)) + if(do_after(user,10, target = src)) + new next_step(user.loc, 1) + qdel(src) \ No newline at end of file diff --git a/code/datums/components/crafting/glassware/lens_crafting.dm b/code/datums/components/crafting/glassware/lens_crafting.dm new file mode 100644 index 0000000000..117df25a30 --- /dev/null +++ b/code/datums/components/crafting/glassware/lens_crafting.dm @@ -0,0 +1,98 @@ +//This file is for crafting using a lens! + +/obj/item/glasswork/glass_base/lens + name = "Optical lens" + desc = "Good for selling or crafting, by itself its useless" + icon = 'icons/obj/glass_ware.dmi' + icon_state = "glass_optics" + +//Laser pointers - 2600 +/obj/item/glasswork/glass_base/laserpointer_shell + name = "Laser pointer assembly" + desc = "Good for selling or crafting, by itself its useless. Needs a power capactor." + icon_state = "laser_case" + icon = 'icons/obj/glass_ware.dmi' + next_step = /obj/item/glasswork/glass_base/laserpointer_shell_1 + +/obj/item/glasswork/glass_base/laserpointer_shell/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/stock_parts/capacitor)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/laserpointer_shell_1 + name = "Laser pointer assembly" + desc = "Good for selling or crafting, by itself its useless. Needs a glass lens." + icon_state = "laser_wire" + icon_state = "laser_case" + next_step = /obj/item/glasswork/glass_base/laserpointer_shell_2 + +/obj/item/glasswork/glass_base/laserpointer_shell_1/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/glasswork/glass_base/lens)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/laserpointer_shell_2 + name = "Laser pointer assembly" + desc = "Good for selling or crafting, by itself its useless. Needs to be screwed together." + icon_state = "laser_wire" + icon_state = "laser_case" + next_step = /obj/item/laser_pointer/blue/handmade + +/obj/item/glasswork/glass_base/laserpointer_shell_2/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_SCREWDRIVER) + if(do_after(user,260, target = src)) + new next_step(user.loc, 1) + qdel(src) + +//NERD SHIT - 5000 + +/obj/item/glasswork/glass_base/glasses_frame + name = "Glasses Frame" + desc = "Good for crafting a pare of glasses, by itself its useless. Just add a pare of lens." + icon = 'icons/obj/glass_ware.dmi' + icon_state = "frames" + next_step = /obj/item/glasswork/glass_base/glasses_frame_1 + +/obj/item/glasswork/glass_base/glasses_frame/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/glasswork/glass_base/lens)) + if(do_after(user,60, target = src)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/glasses_frame_1 + name = "Glasses Frame" + desc = "Good for crafting a pare of glasses, by itself its useless. Just add a the other lens." + icon = 'icons/obj/glass_ware.dmi' + icon_state = "frames_1" + next_step = /obj/item/glasswork/glass_base/glasses_frame_2 + +/obj/item/glasswork/glass_base/glasses_frame_1/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/glasswork/glass_base/lens)) + if(do_after(user,60, target = src)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glass_base/glasses_frame_2 + name = "Glasses Frame" + desc = "Good for crafting a pare of glasses, by itself its useless. Just adjust the pices into the frame with a screwdriver." + icon = 'icons/obj/glass_ware.dmi' + icon_state = "frames_2" + next_step = /obj/item/glasswork/glasses + +/obj/item/glasswork/glass_base/glasses_frame_2/attackby(obj/item/I, mob/user, params) + ..() + if(I.tool_behaviour == TOOL_SCREWDRIVER) + if(do_after(user,180, target = src)) + new next_step(user.loc, 1) + qdel(src) + +/obj/item/glasswork/glasses + name = "Hand Made Glasses" + desc = "Hande made glasses that have not been polished at all making them useless. Selling them could still be worth a bit of credits." + icon = 'icons/obj/glass_ware.dmi' + icon_state = "frames_2" \ No newline at end of file diff --git a/code/datums/components/crafting/recipes/recipes_clothing.dm b/code/datums/components/crafting/recipes/recipes_clothing.dm index ba47b64b97..b9e3c379b4 100644 --- a/code/datums/components/crafting/recipes/recipes_clothing.dm +++ b/code/datums/components/crafting/recipes/recipes_clothing.dm @@ -294,3 +294,12 @@ /obj/item/bedsheet/cosmos = 1) time = 60 category = CAT_CLOTHING + + +/datum/crafting_recipe/garlic_necklace + name = "Garlic Necklace" + result = /obj/item/clothing/neck/garlic_necklace + reqs = list(/obj/item/reagent_containers/food/snacks/grown/garlic = 15, + /obj/item/stack/cable_coil = 10) + time = 100 //Takes awhile to put all the garlics on the coil and knot it. + category = CAT_CLOTHING diff --git a/code/datums/components/phantomthief.dm b/code/datums/components/phantomthief.dm index ede222d001..57ab75f7a3 100644 --- a/code/datums/components/phantomthief.dm +++ b/code/datums/components/phantomthief.dm @@ -1,8 +1,8 @@ //This component applies a customizable drop_shadow filter to its wearer when they toggle combat mode on or off. This can stack. /datum/component/wearertargeting/phantomthief - dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS - signals = list(COMSIG_LIVING_COMBAT_ENABLED) + dupe_mode = COMPONENT_DUPE_ALLOWED + signals = list(COMSIG_LIVING_COMBAT_ENABLED, COMSIG_LIVING_COMBAT_DISABLED) proctype = .proc/handlefilterstuff var/filter_x var/filter_y @@ -19,8 +19,8 @@ filter_color = _color valid_slots = _valid_slots -/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate) - if(!combatmodestate) +/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(mob/living/user, was_forced = FALSE) + if(!(user.combat_flags & COMBAT_FLAG_COMBAT_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/radioactive.dm b/code/datums/components/radioactive.dm index 2853f800f5..decc2dd65c 100644 --- a/code/datums/components/radioactive.dm +++ b/code/datums/components/radioactive.dm @@ -25,7 +25,6 @@ RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, .proc/rad_attack) else CRASH("Something that wasn't an atom was given /datum/component/radioactive") - return if(strength > RAD_MINIMUM_CONTAMINATION) SSradiation.warn(src) @@ -84,4 +83,4 @@ #undef RAD_AMOUNT_LOW #undef RAD_AMOUNT_MEDIUM #undef RAD_AMOUNT_HIGH -#undef RAD_AMOUNT_EXTREME \ No newline at end of file +#undef RAD_AMOUNT_EXTREME diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm index 4c8f1b4c97..e044a59668 100644 --- a/code/datums/components/storage/concrete/_concrete.dm +++ b/code/datums/components/storage/concrete/_concrete.dm @@ -60,7 +60,7 @@ _contents_limbo = null if(_user_limbo) for(var/i in _user_limbo) - show_to(i) + ui_show(i) _user_limbo = null /datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE) diff --git a/code/datums/components/storage/concrete/emergency.dm b/code/datums/components/storage/concrete/emergency.dm index 348821a913..faaeada13d 100644 --- a/code/datums/components/storage/concrete/emergency.dm +++ b/code/datums/components/storage/concrete/emergency.dm @@ -18,7 +18,7 @@ return . = COMPONENT_NO_ATTACK_HAND if(!check_locked(source, user, TRUE)) - show_to(user) + ui_show(user) A.do_jiggle() if(rustle_sound) playsound(A, "rustle", 50, 1, -5) diff --git a/code/datums/components/storage/concrete/rped.dm b/code/datums/components/storage/concrete/rped.dm index 2f95466238..d919828e8e 100644 --- a/code/datums/components/storage/concrete/rped.dm +++ b/code/datums/components/storage/concrete/rped.dm @@ -3,6 +3,7 @@ allow_quick_gather = TRUE allow_quick_empty = TRUE click_gather = TRUE + storage_flags = STORAGE_FLAGS_LEGACY_DEFAULT max_w_class = WEIGHT_CLASS_NORMAL max_combined_w_class = 100 max_items = 100 diff --git a/code/datums/components/storage/concrete/stack.dm b/code/datums/components/storage/concrete/stack.dm index 1f0c44c650..a3f1e526a0 100644 --- a/code/datums/components/storage/concrete/stack.dm +++ b/code/datums/components/storage/concrete/stack.dm @@ -1,6 +1,7 @@ //Stack-only storage. /datum/component/storage/concrete/stack display_numerical_stacking = TRUE + storage_flags = STORAGE_FLAGS_LEGACY_DEFAULT var/max_combined_stack_amount = 300 max_w_class = WEIGHT_CLASS_NORMAL max_combined_w_class = WEIGHT_CLASS_NORMAL * 14 diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index ea72a8a6dd..4100942fec 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -21,9 +21,16 @@ var/locked = FALSE //when locked nothing can see inside or use it. - var/max_w_class = WEIGHT_CLASS_SMALL //max size of objects that will fit. - var/max_combined_w_class = 14 //max combined sizes of objects that will fit. - var/max_items = 7 //max number of objects that will fit. + /// Storage flags, including what kinds of limiters we use for how many items we can hold + var/storage_flags = STORAGE_FLAGS_LEGACY_DEFAULT + /// Max w_class we can hold. Applies to [STORAGE_LIMIT_COMBINED_W_CLASS] and [STORAGE_LIMIT_VOLUME] + var/max_w_class = WEIGHT_CLASS_SMALL + /// Max combined w_class. Applies to [STORAGE_LIMIT_COMBINED_W_CLASS] + var/max_combined_w_class = WEIGHT_CLASS_SMALL * 7 + /// Max items we can hold. Applies to [STORAGE_LIMIT_MAX_ITEMS] + var/max_items = 7 + /// Max volume we can hold. Applies to [STORAGE_LIMIT_VOLUME]. Auto scaled on New() if unset. + var/max_volume var/emp_shielded = FALSE @@ -39,8 +46,17 @@ var/display_numerical_stacking = FALSE //stack things of the same type and show as a single object with a number. - var/obj/screen/storage/boxes //storage display object - var/obj/screen/close/closer //close button object + /// "legacy"/default view mode's storage "boxes" + var/obj/screen/storage/boxes/ui_boxes + /// New volumetric storage display mode's left side + var/obj/screen/storage/left/ui_left + /// New volumetric storage display mode's center 'blocks' + var/obj/screen/storage/continuous/ui_continuous + /// The close button, used in all modes. Frames right side in volumetric mode. + var/obj/screen/storage/close/ui_close + /// Associative list of list(item = screen object) for volumetric storage item screen blocks + var/list/ui_item_blocks + var/current_maxscreensize var/allow_big_nesting = FALSE //allow storage objects of the same or greater size. @@ -68,9 +84,6 @@ return COMPONENT_INCOMPATIBLE if(master) change_master(master) - boxes = new(null, src) - closer = new(null, src) - orient2hud() RegisterSignal(parent, COMSIG_CONTAINS_STORAGE, .proc/on_check) RegisterSignal(parent, COMSIG_IS_STORAGE_LOCKED, .proc/check_locked) @@ -111,8 +124,15 @@ /datum/component/storage/Destroy() close_all() - QDEL_NULL(boxes) - QDEL_NULL(closer) + QDEL_NULL(ui_boxes) + QDEL_NULL(ui_close) + QDEL_NULL(ui_continuous) + QDEL_NULL(ui_left) + // DO NOT USE QDEL_LIST_ASSOC. + if(ui_item_blocks) + for(var/i in ui_item_blocks) + qdel(ui_item_blocks[i]) //qdel the screen object not the item + ui_item_blocks.Cut() LAZYCLEARLIST(is_using) return ..() @@ -286,7 +306,7 @@ if(!_target) _target = get_turf(parent) if(usr) - hide_from(usr) + ui_hide(usr) var/list/contents = contents() var/atom/real_location = real_location() for(var/obj/item/I in contents) @@ -300,106 +320,8 @@ if(check_locked()) close_all() -/datum/component/storage/proc/_process_numerical_display() - . = list() - for(var/obj/item/I in accessible_items()) - if(QDELETED(I)) - continue - if(!.[I.type]) - .[I.type] = new /datum/numbered_display(I, 1) - else - var/datum/numbered_display/ND = .[I.type] - ND.number++ - . = sortTim(., /proc/cmp_numbered_displays_name_asc, associative = TRUE) - -//This proc determines the size of the inventory to be displayed. Please touch it only if you know what you're doing. -/datum/component/storage/proc/orient2hud(mob/user, maxcolumns) - var/list/accessible_contents = accessible_items() - var/adjusted_contents = length(accessible_contents) - - //Numbered contents display - var/list/datum/numbered_display/numbered_contents - if(display_numerical_stacking) - numbered_contents = _process_numerical_display() - adjusted_contents = numbered_contents.len - - var/columns = CLAMP(max_items, 1, maxcolumns ? maxcolumns : screen_max_columns) - var/rows = CLAMP(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows) - standard_orient_objs(rows, columns, numbered_contents) - -//This proc draws out the inventory and places the items on it. It uses the standard position. -/datum/component/storage/proc/standard_orient_objs(rows, cols, list/obj/item/numerical_display_contents) - boxes.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+cols-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]" - var/cx = screen_start_x - var/cy = screen_start_y - if(islist(numerical_display_contents)) - for(var/type in numerical_display_contents) - var/datum/numbered_display/ND = numerical_display_contents[type] - ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE - ND.sample_object.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" - ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]" - ND.sample_object.layer = ABOVE_HUD_LAYER - ND.sample_object.plane = ABOVE_HUD_PLANE - cx++ - if(cx - screen_start_x >= cols) - cx = screen_start_x - cy++ - if(cy - screen_start_y >= rows) - break - else - for(var/obj/O in accessible_items()) - if(QDELETED(O)) - continue - O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip" - O.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" - O.maptext = "" - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - cx++ - if(cx - screen_start_x >= cols) - cx = screen_start_x - cy++ - if(cy - screen_start_y >= rows) - break - closer.screen_loc = "[screen_start_x + cols]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y]" - -/datum/component/storage/proc/show_to(mob/M, set_screen_size = TRUE) - if(!M.client) - return FALSE - var/list/cview = getviewsize(M.client.view) - var/maxallowedscreensize = cview[1]-8 - if(set_screen_size) - current_maxscreensize = maxallowedscreensize - else if(current_maxscreensize) - maxallowedscreensize = current_maxscreensize - if(M.active_storage != src && (M.stat == CONSCIOUS)) - for(var/obj/item/I in accessible_items()) - if(I.on_found(M)) - return FALSE - if(M.active_storage) - M.active_storage.hide_from(M) - orient2hud(M, (isliving(M) ? maxallowedscreensize : 7)) - M.client.screen |= boxes - M.client.screen |= closer - M.client.screen |= accessible_items() - M.active_storage = src - LAZYOR(is_using, M) - return TRUE - -/datum/component/storage/proc/hide_from(mob/M) - if(!M.client) - return TRUE - var/atom/real_location = real_location() - M.client.screen -= boxes - M.client.screen -= closer - M.client.screen -= real_location.contents - if(M.active_storage == src) - M.active_storage = null - LAZYREMOVE(is_using, M) - return TRUE - /datum/component/storage/proc/close(mob/M) - hide_from(M) + ui_hide(M) /datum/component/storage/proc/close_all() . = FALSE @@ -418,25 +340,6 @@ var/datum/component/storage/concrete/master = master() master.emp_act(source, severity) -//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right. -//The numbers are calculated from the bottom-left The bottom-left slot being 1,1. -/datum/component/storage/proc/orient_objs(tx, ty, mx, my) - var/atom/real_location = real_location() - var/cx = tx - var/cy = ty - boxes.screen_loc = "[tx]:,[ty] to [mx],[my]" - for(var/obj/O in real_location) - if(QDELETED(O)) - continue - O.screen_loc = "[cx],[cy]" - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - cx++ - if(cx > mx) - cx = tx - cy-- - closer.screen_loc = "[mx+1],[my]" - //Resets something that is being removed from storage. /datum/component/storage/proc/_removal_reset(atom/movable/thing) if(!istype(thing)) @@ -448,6 +351,9 @@ /datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing) _removal_reset(thing) + if(LAZYACCESS(ui_item_blocks, thing)) + qdel(ui_item_blocks[thing]) + ui_item_blocks -= thing 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 @@ -462,7 +368,7 @@ /datum/component/storage/proc/refresh_mob_views() var/list/seeing = can_see_contents() for(var/i in seeing) - show_to(i) + ui_show(i) return TRUE /datum/component/storage/proc/can_see_contents() @@ -559,7 +465,7 @@ A.add_fingerprint(M) if(!force && (check_locked(null, M) || !M.CanReach(parent, view_only = TRUE))) return FALSE - show_to(M, !ghost) + ui_show(M, !ghost) /datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M) if(isitem(O)) @@ -587,10 +493,6 @@ if(M && !stop_messages) host.add_fingerprint(M) return FALSE - if(real_location.contents.len >= max_items) - if(!stop_messages) - to_chat(M, "[host] is full, make some space!") - return FALSE //Storage item is full if(length(can_hold)) if(!is_type_in_typecache(I, can_hold)) if(!stop_messages) @@ -600,17 +502,34 @@ if(!stop_messages) to_chat(M, "[host] cannot hold [I]!") return FALSE - if(I.w_class > max_w_class) - if(!stop_messages) - to_chat(M, "[I] is too big for [host]!") - return FALSE - var/sum_w_class = I.w_class - for(var/obj/item/_I in real_location) - sum_w_class += _I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it. - if(sum_w_class > max_combined_w_class) - if(!stop_messages) - to_chat(M, "[I] won't fit in [host], make some space!") - return FALSE + // STORAGE LIMITS + if(storage_flags & STORAGE_LIMIT_MAX_ITEMS) + if(real_location.contents.len >= max_items) + if(!stop_messages) + to_chat(M, "[host] has too many things in it, make some space!") + return FALSE //Storage item is full + if(storage_flags & STORAGE_LIMIT_MAX_W_CLASS) + if(I.w_class > max_w_class) + if(!stop_messages) + to_chat(M, "[I] is too long for [host]!") + return FALSE + if(storage_flags & STORAGE_LIMIT_COMBINED_W_CLASS) + var/sum_w_class = I.w_class + for(var/obj/item/_I in real_location) + sum_w_class += _I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it. + if(sum_w_class > max_combined_w_class) + if(!stop_messages) + to_chat(M, "[I] won't fit in [host], make some space!") + return FALSE + if(storage_flags & STORAGE_LIMIT_VOLUME) + var/sum_volume = I.get_w_volume() + for(var/obj/item/_I in real_location) + sum_volume += _I.get_w_volume() + if(sum_volume > get_max_volume()) + if(!stop_messages) + to_chat(M, "[I] is too spacious to fit in [host], make some space!") + return FALSE + ///////////////// if(isitem(host)) var/obj/item/IP = host var/datum/component/storage/STR_I = I.GetComponent(/datum/component/storage) @@ -742,7 +661,7 @@ if(A.loc == user) . = COMPONENT_NO_ATTACK_HAND if(!check_locked(source, user, TRUE)) - show_to(user) + ui_show(user) A.do_jiggle() /datum/component/storage/proc/signal_on_pickup(datum/source, mob/user) @@ -761,7 +680,7 @@ return do_quick_empty(loctarget) /datum/component/storage/proc/signal_hide_attempt(datum/source, mob/target) - return hide_from(target) + return ui_hide(target) /datum/component/storage/proc/on_alt_click(datum/source, mob/user) if(!isliving(user) || !user.CanReach(parent)) @@ -790,7 +709,7 @@ user.visible_message("[user] draws [I] from [parent]!", "You draw [I] from [parent].") return TRUE -/datum/component/storage/proc/action_trigger(datum/signal_source, datum/action/source) +/datum/component/storage/proc/action_trigger(datum/action/source, obj/target) gather_mode_switch(source.owner) return COMPONENT_ACTION_BLOCK_TRIGGER @@ -803,3 +722,9 @@ to_chat(user, "[parent] now picks up all items in a tile at once.") if(COLLECT_ONE) to_chat(user, "[parent] now picks up one item at a time.") + +/** + * Gets our max volume + */ +/datum/component/storage/proc/get_max_volume() + return max_volume || AUTO_SCALE_STORAGE_VOLUME(max_w_class, max_combined_w_class) diff --git a/code/datums/components/storage/ui.dm b/code/datums/components/storage/ui.dm new file mode 100644 index 0000000000..c1c049dfd3 --- /dev/null +++ b/code/datums/components/storage/ui.dm @@ -0,0 +1,293 @@ +/** + * Generates a list of numbered_display datums for the numerical display system. + */ +/datum/component/storage/proc/_process_numerical_display() + . = list() + for(var/obj/item/I in accessible_items()) + if(QDELETED(I)) + continue + if(!.[I.type]) + .[I.type] = new /datum/numbered_display(I, 1) + else + var/datum/numbered_display/ND = .[I.type] + ND.number++ + . = sortTim(., /proc/cmp_numbered_displays_name_asc, associative = TRUE) + +/** + * Orients all objects in legacy mode, and returns the objects to show to the user. + */ +/datum/component/storage/proc/orient2hud_legacy(mob/user, maxcolumns) + . = list() + var/list/accessible_contents = accessible_items() + var/adjusted_contents = length(accessible_contents) + + //Numbered contents display + var/list/datum/numbered_display/numbered_contents + if(display_numerical_stacking) + numbered_contents = _process_numerical_display() + adjusted_contents = numbered_contents.len + + var/columns = CLAMP(max_items, 1, maxcolumns ? maxcolumns : screen_max_columns) + var/rows = CLAMP(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows) + + // First, boxes. + ui_boxes = get_ui_boxes() + ui_boxes.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+columns-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]" + . += ui_boxes + // Then, closer. + ui_close = get_ui_close() + ui_close.screen_loc = "[screen_start_x + columns]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y]" + . += ui_close + // Then orient the actual items. + var/cx = screen_start_x + var/cy = screen_start_y + if(islist(numbered_contents)) + for(var/type in numbered_contents) + var/datum/numbered_display/ND = numbered_contents[type] + ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE + ND.sample_object.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" + ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]" + ND.sample_object.layer = ABOVE_HUD_LAYER + ND.sample_object.plane = ABOVE_HUD_PLANE + . += ND.sample_object + cx++ + if(cx - screen_start_x >= columns) + cx = screen_start_x + cy++ + if(cy - screen_start_y >= rows) + break + else + for(var/obj/O in accessible_items()) + if(QDELETED(O)) + continue + O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip" + O.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" + O.maptext = "" + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + . += O + cx++ + if(cx - screen_start_x >= columns) + cx = screen_start_x + cy++ + if(cy - screen_start_y >= rows) + break + +/** + * Orients all objects in .. volumetric mode. Does not support numerical display! + */ +/datum/component/storage/proc/orient2hud_volumetric(mob/user, maxcolumns) + . = list() + + // Generate ui_item_blocks for missing ones and render+orient. + var/list/atom/contents = accessible_items() + // our volume + var/our_volume = get_max_volume() + var/horizontal_pixels = (maxcolumns * world.icon_size) - (VOLUMETRIC_STORAGE_EDGE_PADDING * 2) + var/max_horizontal_pixels = horizontal_pixels * screen_max_rows + // sigh loopmania time + var/used = 0 + // define outside for performance + var/volume + var/list/volume_by_item = list() + var/list/percentage_by_item = list() + for(var/obj/item/I in contents) + volume = I.get_w_volume() + used += volume + volume_by_item[I] = volume + percentage_by_item[I] = volume / get_max_volume() + var/padding_pixels = ((length(percentage_by_item) - 1) * VOLUMETRIC_STORAGE_ITEM_PADDING) + VOLUMETRIC_STORAGE_EDGE_PADDING * 2 + var/min_pixels = (MINIMUM_PIXELS_PER_ITEM * length(percentage_by_item)) + padding_pixels + // do the check for fallback for when someone has too much gamer gear + if((min_pixels) > (max_horizontal_pixels + 4)) // 4 pixel grace zone + to_chat(user, "[parent] was showed to you in legacy mode due to your items overrunning the three row limit! Consider not carrying too much or bugging a maintainer to raise this limit!") + return orient2hud_legacy(user, maxcolumns) + // after this point we are sure we can somehow fit all items into our max number of rows. + + // determine rows + var/rows = CLAMP(CEILING(min_pixels / horizontal_pixels, 1), 1, screen_max_rows) + + var/overrun = FALSE + if(used > our_volume) + // congratulations we are now in overrun mode. everything will be crammed to minimum storage pixels. + to_chat(user, "[parent] rendered in overrun mode due to more items inside than the maximum volume supports.") + overrun = TRUE + + // how much we are using + var/using_horizontal_pixels = horizontal_pixels * rows + + // item padding + using_horizontal_pixels -= padding_pixels + + // define outside for marginal performance boost + var/obj/item/I + // start at this pixel from screen_start_x. + var/current_pixel = VOLUMETRIC_STORAGE_EDGE_PADDING + var/row = 1 + + LAZYINITLIST(ui_item_blocks) + + for(var/i in percentage_by_item) + I = i + var/percent = percentage_by_item[I] + if(!ui_item_blocks[I]) + ui_item_blocks[I] = new /obj/screen/storage/volumetric_box/center(null, src, I) + var/obj/screen/storage/volumetric_box/center/B = ui_item_blocks[I] + var/pixels_to_use = overrun? MINIMUM_PIXELS_PER_ITEM : max(using_horizontal_pixels * percent, MINIMUM_PIXELS_PER_ITEM) + var/addrow = FALSE + if(CEILING(pixels_to_use, 1) >= FLOOR(horizontal_pixels - current_pixel - VOLUMETRIC_STORAGE_EDGE_PADDING, 1)) + pixels_to_use = horizontal_pixels - current_pixel - VOLUMETRIC_STORAGE_EDGE_PADDING + addrow = TRUE + + // now that we have pixels_to_use, place our thing and add it to the returned list. + + B.screen_loc = I.screen_loc = "[screen_start_x]:[round(current_pixel + (pixels_to_use * 0.5) + VOLUMETRIC_STORAGE_ITEM_PADDING, 1)],[screen_start_y+row-1]:[screen_pixel_y]" + // add the used pixels to pixel after we place the object + current_pixel += pixels_to_use + VOLUMETRIC_STORAGE_ITEM_PADDING + + // set various things + B.set_pixel_size(pixels_to_use) + B.layer = VOLUMETRIC_STORAGE_BOX_LAYER + B.plane = VOLUMETRIC_STORAGE_BOX_PLANE + B.name = I.name + + I.mouse_opacity = MOUSE_OPACITY_ICON + I.maptext = "" + I.layer = VOLUMETRIC_STORAGE_ITEM_LAYER + I.plane = VOLUMETRIC_STORAGE_ITEM_PLANE + + // finally add our things. + . += B.on_screen_objects() + . += I + + // go up a row if needed + if(addrow) + row++ + current_pixel = VOLUMETRIC_STORAGE_EDGE_PADDING + + // Then, continuous section. + ui_continuous = get_ui_continuous() + ui_continuous.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+maxcolumns-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]" + . += ui_continuous + // Then, left. + ui_left = get_ui_left() + ui_left.screen_loc = "[screen_start_x]:[screen_pixel_x - 2],[screen_start_y]:[screen_pixel_y] to [screen_start_x]:[screen_pixel_x - 2],[screen_start_y+rows-1]:[screen_pixel_y]" + . += ui_left + // Then, closer, which is also our right element. + ui_close = get_ui_close() + ui_close.screen_loc = "[screen_start_x + maxcolumns]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x + maxcolumns]:[screen_pixel_x],[screen_start_y + row - 1]:[screen_pixel_y]" + . += ui_close + +/** + * Shows our UI to a mob. + */ +/datum/component/storage/proc/ui_show(mob/M, set_screen_size = TRUE) + if(!M.client) + return FALSE + var/list/cview = getviewsize(M.client.view) + // in tiles + var/maxallowedscreensize = cview[1]-8 + if(set_screen_size) + current_maxscreensize = maxallowedscreensize + else if(current_maxscreensize) + maxallowedscreensize = current_maxscreensize + // we got screen size, register signal + RegisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_logout, override = TRUE) + if(M.active_storage != src) + if(M.active_storage) + M.active_storage.ui_hide(M) + M.active_storage = src + LAZYOR(is_using, M) + if(volumetric_ui()) + //new volumetric ui bay-style + M.client.screen |= orient2hud_volumetric(M, maxallowedscreensize) + else + //old ui + M.client.screen |= orient2hud_legacy(M, maxallowedscreensize) + return TRUE + +/** + * VV hooked to ensure no lingering screen objects. + */ +/datum/component/storage/vv_edit_var(var_name, var_value) + var/list/old + if(var_name == NAMEOF(src, storage_flags)) + old = is_using.Copy() + for(var/i in is_using) + ui_hide(i) + . = ..() + if(old) + for(var/i in old) + ui_show(i) + +/** + * Proc triggered by signal to ensure logging out clients don't linger. + */ +/datum/component/storage/proc/on_logout(datum/source, client/C) + ui_hide(source) + +/** + * Hides our UI from a mob + */ +/datum/component/storage/proc/ui_hide(mob/M) + if(!M.client) + return TRUE + UnregisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT) + M.client.screen -= list(ui_boxes, ui_close, ui_left, ui_continuous) + get_ui_item_objects_hide() + if(M.active_storage == src) + M.active_storage = null + LAZYREMOVE(is_using, M) + return TRUE + +/** + * Returns TRUE if we are using volumetric UI instead of box UI + */ +/datum/component/storage/proc/volumetric_ui() + var/atom/real_location = real_location() + return (storage_flags & STORAGE_LIMIT_VOLUME) && (length(real_location.contents) <= MAXIMUM_VOLUMETRIC_ITEMS) && !display_numerical_stacking + +/** + * Gets the ui item objects to ui_hide. + */ +/datum/component/storage/proc/get_ui_item_objects_hide() + if(!volumetric_ui()) + var/atom/real_location = real_location() + return real_location.contents + else + . = list() + for(var/i in ui_item_blocks) + // get both the box and the item + . += ui_item_blocks[i] + . += i + +/** + * Gets our ui_boxes, making it if it doesn't exist. + */ +/datum/component/storage/proc/get_ui_boxes() + if(!ui_boxes) + ui_boxes = new(null, src) + return ui_boxes + +/** + * Gets our ui_left, making it if it doesn't exist. + */ +/datum/component/storage/proc/get_ui_left() + if(!ui_left) + ui_left = new(null, src) + return ui_left + +/** + * Gets our ui_close, making it if it doesn't exist. + */ +/datum/component/storage/proc/get_ui_close() + if(!ui_close) + ui_close = new(null, src) + return ui_close + +/** + * Gets our ui_continuous, making it if it doesn't exist. + */ +/datum/component/storage/proc/get_ui_continuous() + if(!ui_continuous) + ui_continuous = new(null, src) + return ui_continuous diff --git a/code/datums/components/virtual_reality.dm b/code/datums/components/virtual_reality.dm index 9239d4c565..56e06e3582 100644 --- a/code/datums/components/virtual_reality.dm +++ b/code/datums/components/virtual_reality.dm @@ -176,7 +176,7 @@ /** *The following procs simply acts as hooks for quit(), since components do not use callbacks anymore */ -/datum/component/virtual_reality/proc/action_trigger(datum/signal_source, datum/action/source) +/datum/component/virtual_reality/proc/action_trigger(datum/action/source, obj/target) quit() return COMPONENT_ACTION_BLOCK_TRIGGER diff --git a/code/datums/components/wearertargeting.dm b/code/datums/components/wearertargeting.dm index feaa88f934..4760757701 100644 --- a/code/datums/components/wearertargeting.dm +++ b/code/datums/components/wearertargeting.dm @@ -19,4 +19,4 @@ UnregisterSignal(equipper, signals) /datum/component/wearertargeting/proc/on_drop(datum/source, mob/user) - UnregisterSignal(user, signals) \ No newline at end of file + UnregisterSignal(user, signals) diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm index 20f2c1bbb5..30c6625049 100644 --- a/code/datums/components/wet_floor.dm +++ b/code/datums/components/wet_floor.dm @@ -19,7 +19,6 @@ var/datum/component/wet_floor/WF = newcomp //Lets make an assumption if(WF.gc()) //See if it's even valid, still. Also does LAZYLEN and stuff for us. CRASH("Wet floor component tried to inherit another, but the other was able to garbage collect while being inherited! What a waste of time!") - return for(var/i in WF.time_left_list) add_wet(text2num(i), WF.time_left_list[i]) diff --git a/code/datums/dash_weapon.dm b/code/datums/dash_weapon.dm index 8eda936bb7..c31139dcd7 100644 --- a/code/datums/dash_weapon.dm +++ b/code/datums/dash_weapon.dm @@ -19,7 +19,7 @@ dashing_item = dasher holder = user -/datum/action/innate/dash/IsAvailable() +/datum/action/innate/dash/IsAvailable(silent = FALSE) if(current_charges > 0) return TRUE else diff --git a/code/datums/datum.dm b/code/datums/datum.dm index a856f2392d..6202ac444e 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -109,6 +109,8 @@ UnregisterSignal(target, signal_procs[target]) //END: ECS SHIT + SSsounds.free_datum_channels(src) + return QDEL_HINT_QUEUE #ifdef DATUMVAR_DEBUGGING_MODE @@ -173,11 +175,9 @@ if(!islist(jsonlist)) if(!istext(jsonlist)) CRASH("Invalid JSON") - return jsonlist = json_decode(jsonlist) if(!islist(jsonlist)) CRASH("Invalid JSON") - return if(!jsonlist["DATUM_TYPE"]) return if(!ispath(jsonlist["DATUM_TYPE"])) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 95b45b6bc2..1c866ea535 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -41,6 +41,7 @@ /datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0) if(!istype(destination)) return + var/old_size = destination.dna.features["body_size"] destination.dna.unique_enzymes = unique_enzymes destination.dna.uni_identity = uni_identity destination.dna.blood_type = blood_type @@ -56,6 +57,8 @@ if(transfer_SE) destination.dna.mutation_index = mutation_index + destination.dna.update_body_size(old_size) + SEND_SIGNAL(destination, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, src, transfer_SE) /datum/dna/proc/copy_dna(datum/dna/new_dna) @@ -368,7 +371,9 @@ /mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures) 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 @@ -644,3 +649,15 @@ gib() else set_species(/datum/species/dullahan) + +/datum/dna/proc/update_body_size(old_size) + if(!holder || features["body_size"] == old_size) + return + holder.resize = features["body_size"] / old_size + holder.update_transform() + var/danger = CONFIG_GET(number/threshold_body_size_slowdown) + if(features["body_size"] < danger) + var/slowdown = 1 + round(danger/features["body_size"], 0.1) * CONFIG_GET(number/body_size_slowdown_multiplier) + holder.add_movespeed_modifier(MOVESPEED_ID_SMALL_STRIDE, TRUE, 100, NONE, TRUE, slowdown, ALL, FLOATING|CRAWLING) + else if(old_size < danger) + holder.remove_movespeed_modifier(MOVESPEED_ID_SMALL_STRIDE) diff --git a/code/datums/elements/ghost_role_eligibility.dm b/code/datums/elements/ghost_role_eligibility.dm index 81fd593d5f..4e7884efe4 100644 --- a/code/datums/elements/ghost_role_eligibility.dm +++ b/code/datums/elements/ghost_role_eligibility.dm @@ -1,67 +1,48 @@ +GLOBAL_LIST_EMPTY(ghost_eligible_mobs) + +GLOBAL_LIST_EMPTY(client_ghost_timeouts) + /datum/element/ghost_role_eligibility element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE - id_arg_index = 3 - var/list/timeouts = list() - var/list/mob/eligible_mobs = list() + id_arg_index = 2 var/penalizing = FALSE var/free_ghost = FALSE -/datum/element/ghost_role_eligibility/Attach(datum/target,penalize = FALSE,free_ghosting = FALSE, penalize_on_ghost = FALSE) +/datum/element/ghost_role_eligibility/Attach(datum/target,free_ghosting = FALSE, penalize_on_ghost = FALSE) . = ..() if(!ismob(target)) return ELEMENT_INCOMPATIBLE penalizing = penalize_on_ghost free_ghost = free_ghosting var/mob/M = target - if(!(M in eligible_mobs)) - eligible_mobs += M + if(!(M in GLOB.ghost_eligible_mobs)) + GLOB.ghost_eligible_mobs += M RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/get_ghost_flags) - if(penalize) //penalizing them from making a ghost role / midround antag comeback right away. - var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) MINUTES - var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES - if(world.time < roundstart_quit_limit) //add up the time difference to their antag rolling penalty if they quit before half a (ingame) hour even passed. - penalty += roundstart_quit_limit - world.time - if(penalty) - penalty += world.realtime - if(SSautotransfer.can_fire && SSautotransfer.maxvotes) - var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes - if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) - penalty = CANT_REENTER_ROUND - if(!(M.ckey in timeouts)) - timeouts += M.ckey - timeouts[M.ckey] = 0 - else if(timeouts[M.ckey] == CANT_REENTER_ROUND) - return - timeouts[M.ckey] = max(timeouts[M.ckey],penalty) /datum/element/ghost_role_eligibility/Detach(mob/M) . = ..() - if(M in eligible_mobs) - eligible_mobs -= M + if(M in GLOB.ghost_eligible_mobs) + GLOB.ghost_eligible_mobs -= M UnregisterSignal(M, COMSIG_MOB_GHOSTIZE) -/datum/element/ghost_role_eligibility/proc/get_all_ghost_role_eligible(silent = FALSE) +/proc/get_all_ghost_role_eligible(silent = FALSE) var/list/candidates = list() - for(var/m in eligible_mobs) + for(var/m in GLOB.ghost_eligible_mobs) var/mob/M = m if(M.can_reenter_round(TRUE)) candidates += M return candidates /mob/proc/can_reenter_round(silent = FALSE) - var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility)) - return eli.can_reenter_round(src,silent) - -/datum/element/ghost_role_eligibility/proc/can_reenter_round(var/mob/M,silent = FALSE) - if(!(M in eligible_mobs)) + if(!(src in GLOB.ghost_eligible_mobs)) return FALSE - if(!(M.ckey in timeouts)) + if(!(ckey in GLOB.client_ghost_timeouts)) return TRUE - var/timeout = timeouts[M.ckey] + var/timeout = GLOB.client_ghost_timeouts[ckey] if(timeout != CANT_REENTER_ROUND && timeout <= world.realtime) return TRUE - if(!silent && M.client) - to_chat(M, "You are unable to reenter the round[timeout != CANT_REENTER_ROUND ? " yet. Your ghost role blacklist will expire in [DisplayTimeText(timeout - world.realtime)]" : ""].") + if(!silent && client) + to_chat(src, "You are unable to reenter the round[timeout != CANT_REENTER_ROUND ? " yet. Your ghost role blacklist will expire in [DisplayTimeText(timeout - world.realtime)]" : ""].") return FALSE /datum/element/ghost_role_eligibility/proc/get_ghost_flags() diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm index 220aee4608..a5c6e2725d 100644 --- a/code/datums/elements/mob_holder.dm +++ b/code/datums/elements/mob_holder.dm @@ -71,7 +71,7 @@ name = "bugged mob" desc = "Yell at coderbrush." icon = null - alternate_worn_icon = 'icons/mob/animals_held.dmi' + mob_overlay_icon = 'icons/mob/animals_held.dmi' righthand_file = 'icons/mob/animals_held_rh.dmi' lefthand_file = 'icons/mob/animals_held_lh.dmi' icon_state = "" @@ -86,7 +86,7 @@ assimilate(target) if(alt_worn) - alternate_worn_icon = alt_worn + mob_overlay_icon = alt_worn if(worn_state) item_state = worn_state icon_state = worn_state diff --git a/code/datums/elements/polychromic.dm b/code/datums/elements/polychromic.dm new file mode 100644 index 0000000000..1c438c86c5 --- /dev/null +++ b/code/datums/elements/polychromic.dm @@ -0,0 +1,187 @@ +#define POLYCHROMIC_ALTCLICK (1<<0) +#define POLYCHROMIC_ACTION (1<<1) +#define POLYCHROMIC_NO_HELD (1<<2) +#define POLYCHROMIC_NO_WORN (1<<3) + +/datum/element/polychromic + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 3 + var/overlays_states //A list or a number of states. In the latter case, the atom icon_state/item_state will be used followed by a number. + var/list/colors_by_atom = list() //list of color strings or mutable appearances, depending on the above variable. + var/icon_file + var/worn_file //used in place of items' held or mob overlay icons if present. + var/list/overlays_names //wrap numbers into text strings please. + var/list/actions_by_atom = list() + var/poly_flags + var/static/list/suits_with_helmet_typecache = typecacheof(list(/obj/item/clothing/suit/hooded, /obj/item/clothing/suit/space/hardsuit)) + var/list/helmet_by_suit = list() //because poly winter coats exist. + var/list/suit_by_helmet = list() //Idem. + +/datum/element/polychromic/Attach(datum/target, list/colors, states, _flags = POLYCHROMIC_ACTION|POLYCHROMIC_NO_HELD, _icon, _worn, list/names = list("Primary", "Secondary", "Tertiary", "Quaternary", "Quinary", "Senary")) + . = ..() + var/make_appearances = islist(states) + var/states_len = make_appearances ? length(states) : states + var/names_len = length(names) + if(!states_len || !names_len || colors_by_atom[target] || !isatom(target)) + return ELEMENT_INCOMPATIBLE + var/atom/A = target + + overlays_states = states + icon_file = _icon + worn_file = _worn + poly_flags = _flags + + var/mut_icon = icon_file || A.icon + var/list/L = list() + for(var/I in 1 to states_len) + var/col = LAZYACCESS(colors, I) || "#FFFFFF" + L += make_appearances ? mutable_appearance(mut_icon, overlays_states[I], color = col) : col + colors_by_atom[A] = L + + RegisterSignal(A, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlays) + + if(_flags & POLYCHROMIC_ALTCLICK) + RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/on_examine) + RegisterSignal(A, COMSIG_CLICK_ALT, .proc/set_color) + + if(!overlays_names && names) //generate + overlays_names = names + var/diff = states_len - names_len + if(diff > 0) + for(var/i in 1 to diff) + overlays_names += "[names_len + i]°" + else if(diff < 0) + overlays_names.len += diff + + if(isitem(A)) + if(_flags & POLYCHROMIC_ACTION) + RegisterSignal(A, COMSIG_ITEM_EQUIPPED, .proc/grant_user_action) + RegisterSignal(A, COMSIG_ITEM_DROPPED, .proc/remove_user_action) + if(!(_flags & POLYCHROMIC_NO_WORN) || !(_flags & POLYCHROMIC_NO_HELD)) + A.AddElement(/datum/element/update_icon_updates_onmob) + RegisterSignal(A, COMSIG_ITEM_WORN_OVERLAYS, .proc/apply_worn_overlays) + if(suits_with_helmet_typecache[A.type]) + RegisterSignal(A, COMSIG_SUIT_MADE_HELMET, .proc/register_helmet) + else if(_flags & POLYCHROMIC_ACTION && ismob(A)) //in the event mob update icon procs are ever standarized. + var/datum/action/polychromic/P = new(A) + RegisterSignal(P, COMSIG_ACTION_TRIGGER, .proc/activate_action) + actions_by_atom[A] = P + P.Grant(A) + + A.update_icon() //apply the overlays. + +/datum/element/polychromic/Detach(atom/A) + . = ..() + colors_by_atom -= A + var/datum/action/polychromic/P = actions_by_atom[A] + if(P) + actions_by_atom -= A + qdel(P) + UnregisterSignal(A, list(COMSIG_PARENT_EXAMINE, COMSIG_CLICK_ALT, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_ITEM_WORN_OVERLAYS, COMSIG_SUIT_MADE_HELMET)) + if(isitem(A)) + var/obj/item/clothing/head/H = helmet_by_suit[A] + if(H) + UnregisterSignal(H, list(COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ITEM_WORN_OVERLAYS, COMSIG_PARENT_QDELETING)) + helmet_by_suit -= A + suit_by_helmet -= H + colors_by_atom -= H + if(!QDELETED(H)) + H.update_icon() //removing the overlays + if(!(poly_flags & POLYCHROMIC_NO_WORN) || !(poly_flags & POLYCHROMIC_NO_HELD)) + A.RemoveElement(/datum/element/update_icon_updates_onmob) + if(!QDELETED(A) && ismob(A.loc)) + var/mob/M = A.loc + if(!(poly_flags & POLYCHROMIC_NO_HELD) && M.is_holding(A)) + M.update_inv_hands() + else if(!(poly_flags & POLYCHROMIC_NO_WORN)) + M.regenerate_icons() + if(!QDELETED(A)) + A.update_icon() //removing the overlays + +/datum/element/polychromic/proc/apply_overlays(atom/source, list/overlays) + var/list/L = colors_by_atom[source] + var/f_icon = icon_file || source.icon + if(isnum(overlays_states)) + for(var/i in 1 to overlays_states) + overlays += mutable_appearance(f_icon, "[source.icon_state]-[i]", color = L[i]) + else + overlays += colors_by_atom[source] + +/datum/element/polychromic/proc/apply_worn_overlays(obj/item/source, isinhands, icon, used_state, style_flags, list/overlays) + if(poly_flags & (isinhands ? POLYCHROMIC_NO_HELD : POLYCHROMIC_NO_WORN)) + return + var/f_icon = worn_file || icon + var/list/L = colors_by_atom[source] + + if(isnum(overlays_states)) + for(var/i in 1 to overlays_states) + overlays += mutable_appearance(f_icon, "[used_state]-[i]", color = L[i]) + else + for(var/i in 1 to length(overlays_states)) + var/mutable_appearance/M = L[i] + overlays += mutable_appearance(f_icon, overlays_states[i], color = M.color) + +/datum/element/polychromic/proc/set_color(atom/source, mob/user) + var/choice = input(user,"Polychromic options", "Recolor [source]") as null|anything in overlays_names + if(!choice || QDELETED(source) || !user.canUseTopic(source, BE_CLOSE, NO_DEXTERY)) + return + var/index = overlays_names.Find(choice) + var/list/L = colors_by_atom[source] + if(!L) // Ummmmmh. + return + var/mutable_appearance/M = L[index] + var/old_color = istype(M) ? M.color : M + var/ncolor = input(user, "Polychromic options", "Choose [choice] Color", old_color) as color|null + if(!ncolor || QDELETED(source) || !colors_by_atom[source] || !user.canUseTopic(source, BE_CLOSE, NO_DEXTERY)) + return + ncolor = sanitize_hexcolor(ncolor, 6, TRUE, old_color) + if(istype(M)) + M.color = ncolor + else + L[index] = ncolor + + source.update_icon() + return TRUE + +/datum/element/polychromic/proc/grant_user_action(atom/source, mob/user, slot) + if(slot == SLOT_IN_BACKPACK || slot == SLOT_LEGCUFFED || slot == SLOT_HANDCUFFED || slot == SLOT_GENERC_DEXTROUS_STORAGE) + return + var/datum/action/polychromic/P = actions_by_atom[source] + if(!P) + P = new (source) + P.name = "Modify [source]'\s Colors" + actions_by_atom[source] = P + P.check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS + RegisterSignal(P, COMSIG_ACTION_TRIGGER, .proc/activate_action) + P.Grant(user) + +/datum/element/polychromic/proc/remove_user_action(atom/source, mob/user) + var/datum/action/polychromic/P = actions_by_atom[source] + P?.Remove(user) + +/datum/element/polychromic/proc/activate_action(datum/action/source, atom/target) + set_color(target, source.owner) + +/datum/element/polychromic/proc/on_examine(atom/source, mob/user, list/examine_list) + examine_list += "Alt-click to recolor it." + +/datum/element/polychromic/proc/register_helmet(atom/source, obj/item/clothing/head/H) + suit_by_helmet[H] = source + helmet_by_suit[source] = H + colors_by_atom[H] = colors_by_atom[source] + RegisterSignal(H, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlays) + RegisterSignal(H, COMSIG_ITEM_WORN_OVERLAYS, .proc/apply_worn_overlays) + RegisterSignal(H, COMSIG_PARENT_QDELETING, .proc/unregister_helmet) + +/datum/element/polychromic/proc/unregister_helmet(atom/source) + var/obj/item/clothing/suit/S = suit_by_helmet[source] + suit_by_helmet -= source + helmet_by_suit -= S + colors_by_atom -= source + +/datum/action/polychromic + name = "Modify Polychromic Colors" + background_icon_state = "bg_polychromic" + use_target_appearance = TRUE + button_icon_state = null + target_appearance_matrix = list(0.8,0,0,0,0.8,0) diff --git a/code/datums/elements/spellcasting.dm b/code/datums/elements/spellcasting.dm index a917108bf1..877bcdbcd3 100644 --- a/code/datums/elements/spellcasting.dm +++ b/code/datums/elements/spellcasting.dm @@ -12,7 +12,7 @@ RegisterSignal(target, COMSIG_ITEM_EQUIPPED, .proc/on_equip) RegisterSignal(target, COMSIG_ITEM_DROPPED, .proc/on_drop) else if(ismob(target)) - RegisterSignal(target, COMSIG_MOB_SPELL_CAST_CHECK, .proc/on_cast) + RegisterSignal(target, COMSIG_MOB_SPELL_CAN_CAST, .proc/on_cast) stacked_spellcasting_by_user[target]++ else return ELEMENT_INCOMPATIBLE @@ -21,24 +21,24 @@ /datum/element/spellcasting/Detach(datum/target) . = ..() - UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_MOB_SPELL_CAST_CHECK)) + UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_MOB_SPELL_CAN_CAST)) if(users_by_item[target]) var/mob/user = users_by_item[target] stacked_spellcasting_by_user[user]-- if(!stacked_spellcasting_by_user[user]) stacked_spellcasting_by_user -= user - UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK) + UnregisterSignal(user, COMSIG_MOB_SPELL_CAN_CAST) else if(ismob(target)) stacked_spellcasting_by_user[target]-- if(!stacked_spellcasting_by_user[target]) stacked_spellcasting_by_user -= target /datum/element/spellcasting/proc/on_equip(datum/source, mob/equipper, slot) - if(!(slot in cast_slots)) + if(!(cast_slots & slotdefine2slotbit(slot))) return users_by_item[source] = equipper if(!stacked_spellcasting_by_user[equipper]) - RegisterSignal(equipper, COMSIG_MOB_SPELL_CAST_CHECK, .proc/on_cast) + RegisterSignal(equipper, COMSIG_MOB_SPELL_CAN_CAST, .proc/on_cast) stacked_spellcasting_by_user[equipper]++ /datum/element/spellcasting/proc/on_drop(datum/source, mob/user) @@ -48,7 +48,7 @@ stacked_spellcasting_by_user[user]-- if(!stacked_spellcasting_by_user[user]) stacked_spellcasting_by_user -= user - UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK) + UnregisterSignal(user, COMSIG_MOB_SPELL_CAN_CAST) /datum/element/spellcasting/proc/on_cast(mob/caster, obj/effect/proc_holder/spell) return cast_flags diff --git a/code/datums/elements/update_icon_updates_onmob.dm b/code/datums/elements/update_icon_updates_onmob.dm index ca0e8b1641..5c71547f62 100644 --- a/code/datums/elements/update_icon_updates_onmob.dm +++ b/code/datums/elements/update_icon_updates_onmob.dm @@ -5,7 +5,7 @@ . = ..() if(!istype(target, /obj/item)) return ELEMENT_INCOMPATIBLE - RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, .proc/update_onmob) + RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, .proc/update_onmob, override = TRUE) /datum/element/update_icon_updates_onmob/proc/update_onmob(obj/item/target) if(ismob(target.loc)) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 6b0981665d..c46a03a986 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -128,7 +128,7 @@ // Can most things breathe? if(trace_gases) continue - if(A_gases[/datum/gas/oxygen] >= 16) + if(A_gases[/datum/gas/oxygen] <= 16) continue if(A_gases[/datum/gas/plasma]) continue diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm index 49942976ce..bafb6fbf0e 100644 --- a/code/datums/looping_sounds/_looping_sound.dm +++ b/code/datums/looping_sounds/_looping_sound.dm @@ -73,7 +73,7 @@ var/list/atoms_cache = output_atoms var/sound/S = sound(soundfile) if(direct) - S.channel = open_sound_channel() + S.channel = SSsounds.random_available_channel() S.volume = volume for(var/i in 1 to atoms_cache.len) var/atom/thing = atoms_cache[i] diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm index 7b7975bedb..d8a888871e 100644 --- a/code/datums/martial/_martial.dm +++ b/code/datums/martial/_martial.dm @@ -35,6 +35,17 @@ current_target = new_target streak = "" +/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)) + damage *= 1.5 + if(!CHECK_MOBILITY(A, MOBILITY_STAND)) + damage *= 0.5 + if(!(A.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + damage *= 0.25 + return damage + /datum/martial_art/proc/teach(mob/living/carbon/human/H, make_temporary = FALSE) if(!istype(H) || !H.mind) return FALSE @@ -50,6 +61,7 @@ if(help_verb) H.verbs += help_verb H.mind.martial_art = src + ADD_TRAIT(H, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT) return TRUE /datum/martial_art/proc/store(datum/martial_art/M,mob/living/carbon/human/H) @@ -68,7 +80,8 @@ else 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/martial/boxing.dm b/code/datums/martial/boxing.dm index 16d61c29f9..93d70c12cc 100644 --- a/code/datums/martial/boxing.dm +++ b/code/datums/martial/boxing.dm @@ -16,16 +16,13 @@ A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) var/atk_verb = pick("left hook","right hook","straight punch") - - var/damage = rand(10, 13) - var/extra_damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh) + var/extra_damage = damage_roll(A,D) if(extra_damage == A.dna.species.punchdamagelow) playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) D.visible_message("[A] has attempted to [atk_verb] [D]!", \ "[A] has attempted to [atk_verb] [D]!", null, COMBAT_MESSAGE_RANGE) log_combat(A, D, "attempted to hit", atk_verb) return TRUE - damage += extra_damage var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) var/armor_block = D.run_armor_check(affecting, "melee") @@ -35,7 +32,7 @@ D.visible_message("[A] has [atk_verb]ed [D]!", \ "[A] has [atk_verb]ed [D]!", null, COMBAT_MESSAGE_RANGE) - D.apply_damage(damage, STAMINA, affecting, armor_block) + D.apply_damage(rand(10,13) + extra_damage, STAMINA, affecting, armor_block) log_combat(A, D, "punched (boxing) ") if(D.getStaminaLoss() > 100 && istype(D.mind?.martial_art, /datum/martial_art/boxing)) var/knockout_prob = (D.getStaminaLoss() + rand(-15,15))*0.75 diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm index 0871cf7eaa..39fac11129 100644 --- a/code/datums/martial/cqc.dm +++ b/code/datums/martial/cqc.dm @@ -42,11 +42,12 @@ /datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!can_use(A)) return FALSE + var/damage = (damage_roll(A,D) + 5) if(CHECK_MOBILITY(D, MOBILITY_STAND)) D.visible_message("[A] slams [D] into the ground!", \ "[A] slams you into the ground!") playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1) - D.apply_damage(10, BRUTE) + D.apply_damage(damage, BRUTE) D.DefaultCombatKnockdown(120) log_combat(A, D, "slammed (CQC)") return TRUE @@ -54,29 +55,33 @@ /datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!can_use(A)) return FALSE - if(CHECK_MOBILITY(D, MOBILITY_STAND)) - D.visible_message("[A] kicks [D] back!", \ - "[A] kicks you back!") - playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) - var/atom/throw_target = get_edge_target_turf(D, A.dir) - D.throw_at(throw_target, 1, 14, A) - D.apply_damage(10, BRUTE) - log_combat(A, D, "kicked (CQC)") + var/damage = damage_roll(A,D) if(!CHECK_MOBILITY(D, MOBILITY_STAND) && CHECK_MOBILITY(D, MOBILITY_USE)) log_combat(A, D, "knocked out (Head kick)(CQC)") D.visible_message("[A] kicks [D]'s head, knocking [D.p_them()] out!", \ "[A] kicks your head, knocking you out!") playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1) D.SetSleeping(300) - D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 150) + D.apply_damage(damage + 5, BRUTE) + var/atom/throw_target = get_edge_target_turf(D, A.dir) + D.throw_at(throw_target, 1, 14, A) + D.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage + 10, 150) + else + D.visible_message("[A] kicks [D]!", \ + "[A] kicks you!") + playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + D.Dizzy(damage) + D.apply_damage(damage + 15, BRUTE) + log_combat(A, D, "kicked (CQC)") return TRUE /datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!can_use(A)) return FALSE + var/damage = (damage_roll(A,D) + 55) log_combat(A, D, "pressured (CQC)") D.visible_message("[A] punches [D]'s neck!") - D.adjustStaminaLoss(60) + D.apply_damage(damage, STAMINA) playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) return TRUE @@ -85,11 +90,12 @@ return if(!can_use(A)) return FALSE + var/damage = (damage_roll(A,D) + 15) if(!D.stat) log_combat(A, D, "restrained (CQC)") D.visible_message("[A] locks [D] into a restraining position!", \ "[A] locks you into a restraining position!") - D.adjustStaminaLoss(20) + D.apply_damage(damage, STAMINA) D.Stun(100) restraining = TRUE addtimer(VARSET_CALLBACK(src, restraining, FALSE), 50, TIMER_UNIQUE) @@ -98,6 +104,7 @@ /datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!can_use(A)) return FALSE + var/damage = damage_roll(A,D) if(!D.stat) log_combat(A, D, "consecutive CQC'd (CQC)") D.visible_message("[A] strikes [D]'s abdomen, neck and back consecutively", \ @@ -106,8 +113,8 @@ var/obj/item/I = D.get_active_held_item() if(I && D.temporarilyRemoveItemFromInventory(I)) A.put_in_hands(I) - D.adjustStaminaLoss(50) - D.apply_damage(25, BRUTE) + D.apply_damage(damage + 45, STAMINA) + D.apply_damage(damage + 20, BRUTE) return TRUE /datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -135,7 +142,7 @@ log_combat(A, D, "attacked (CQC)") A.do_attack_animation(D) var/picked_hit_type = pick("CQC'd", "Big Bossed") - var/bonus_damage = 13 + var/bonus_damage = (damage_roll(A,D) + 7) if(!CHECK_MOBILITY(D, MOBILITY_STAND)) bonus_damage += 5 picked_hit_type = "stomps on" @@ -151,7 +158,7 @@ D.visible_message("[A] leg sweeps [D]!", \ "[A] leg sweeps you!") playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1) - D.apply_damage(10, BRUTE) + D.apply_damage(bonus_damage, BRUTE) D.DefaultCombatKnockdown(60) log_combat(A, D, "sweeped (CQC)") return TRUE @@ -161,6 +168,7 @@ return FALSE add_to_streak("D",D) var/obj/item/I = null + var/damage = (damage_roll(A,D)*0.5) if(check_streak(A,D)) return TRUE if(prob(65)) @@ -172,7 +180,7 @@ if(I && D.temporarilyRemoveItemFromInventory(I)) A.put_in_hands(I) D.Jitter(2) - D.apply_damage(5, BRUTE) + D.apply_damage(damage, BRUTE) else D.visible_message("[A] attempted to disarm [D]!", \ "[A] attempted to disarm [D]!") diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 1a244f911e..df42fba07d 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -84,64 +84,71 @@ if("neck_chop") streak = "" neck_chop(A,D) - return 1 + return TRUE if("leg_sweep") streak = "" leg_sweep(A,D) - return 1 + return TRUE if("quick_choke")//is actually lung punch streak = "" quick_choke(A,D) - return 1 - return 0 + return TRUE + return FALSE /datum/martial_art/krav_maga/proc/leg_sweep(mob/living/carbon/human/A, mob/living/carbon/human/D) + var/obj/item/bodypart/affecting = D.get_bodypart(BODY_ZONE_CHEST) + var/armor_block = D.run_armor_check(affecting, "melee") + var/damage = damage_roll(A,D) if(!CHECK_MOBILITY(D, MOBILITY_STAND)) - return 0 + return FALSE D.visible_message("[A] leg sweeps [D]!", \ "[A] leg sweeps you!") playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1) - D.apply_damage(5, BRUTE) - D.DefaultCombatKnockdown(40, override_hardstun = 0.01, override_stamdmg = 25) + D.apply_damage(damage + 25, STAMINA, affecting, armor_block) + D.DefaultCombatKnockdown(80, override_hardstun = 1, override_stamdmg = 0) log_combat(A, D, "leg sweeped") - return 1 + return TRUE /datum/martial_art/krav_maga/proc/quick_choke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)//is actually lung punch + var/damage = damage_roll(A,D) D.visible_message("[A] pounds [D] on the chest!", \ "[A] slams your chest! You can't breathe!") playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1) if(D.losebreath <= 10) D.losebreath = CLAMP(D.losebreath + 5, 0, 10) - D.adjustOxyLoss(10) + D.adjustOxyLoss(damage + 5) log_combat(A, D, "quickchoked") - return 1 + return TRUE /datum/martial_art/krav_maga/proc/neck_chop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + var/damage = (damage_roll(A,D)*0.5) D.visible_message("[A] karate chops [D]'s neck!", \ "[A] karate chops your neck, rendering you unable to speak!") playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1) - D.apply_damage(5, BRUTE) + D.apply_damage(damage, BRUTE) if(D.silent <= 10) D.silent = CLAMP(D.silent + 10, 0, 10) log_combat(A, D, "neck chopped") - return 1 + return TRUE /datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(check_streak(A,D)) - return 1 + return TRUE log_combat(A, D, "grabbed (Krav Maga)") ..() /datum/martial_art/krav_maga/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) + var/armor_block = D.run_armor_check(affecting, "melee") if(check_streak(A,D)) - return 1 + return TRUE log_combat(A, D, "punched") var/picked_hit_type = pick("punches", "kicks") - var/bonus_damage = 10 - if(CHECK_MOBILITY(D, MOBILITY_STAND)) - bonus_damage += 5 + var/bonus_damage = damage_roll(A,D) + if(!CHECK_MOBILITY(D, MOBILITY_STAND)) + bonus_damage += 10 picked_hit_type = "stomps on" - D.apply_damage(bonus_damage, BRUTE) + D.apply_damage(bonus_damage, BRUTE, affecting, armor_block) if(picked_hit_type == "kicks" || picked_hit_type == "stomps on") A.do_attack_animation(D, ATTACK_EFFECT_KICK) playsound(get_turf(D), 'sound/effects/hit_kick.ogg', 50, 1, -1) @@ -151,24 +158,34 @@ D.visible_message("[A] [picked_hit_type] [D]!", \ "[A] [picked_hit_type] you!") log_combat(A, D, "[picked_hit_type] with [name]") - return 1 + return TRUE -/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - var/obj/item/I = null - if(prob(60)) - I = D.get_active_held_item() - if(I) - if(D.temporarilyRemoveItemFromInventory(I)) - A.put_in_hands(I) - D.visible_message("[A] has disarmed [D]!", \ - "[A] has disarmed [D]!") - playsound(D, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) +/datum/martial_art/krav_maga/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(check_streak(A,D)) + return TRUE + var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) + var/armor_block = D.run_armor_check(affecting, "melee") + var/damage = (damage_roll(A,D)*2) + if(D.mobility_flags & MOBILITY_STAND) + D.visible_message("[A] reprimands [D]!", \ + "You're slapped by [A]!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) + to_chat(A, "You jab [D]!") + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) + playsound(D, 'sound/effects/hit_punch.ogg', 50, TRUE, -1) + D.apply_damage(damage + 5, STAMINA, affecting, armor_block) + log_combat(A, D, "punched nonlethally") else - D.visible_message("[A] attempted to disarm [D]!", \ - "[A] attempted to disarm [D]!") - playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - log_combat(A, D, "disarmed (Krav Maga)", "[I ? " removing \the [I]" : ""]") - return 1 + D.visible_message("[A] reprimands [D]!", \ + "You're manhandled by [A]!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) + to_chat(A, "You stomp [D]!") + A.do_attack_animation(D, ATTACK_EFFECT_KICK) + playsound(D, 'sound/effects/hit_punch.ogg', 50, TRUE, -1) + D.apply_damage(damage + 10, STAMINA, affecting, armor_block) + log_combat(A, D, "stomped nonlethally") + if(prob(D.getStaminaLoss())) + D.visible_message("[D] sputters and recoils in pain!", "You recoil in pain as you are jabbed in a nerve!") + D.drop_all_held_items() + return TRUE //Krav Maga Gloves diff --git a/code/datums/martial/mushpunch.dm b/code/datums/martial/mushpunch.dm index fe9f0d77d6..3fd0a637c2 100644 --- a/code/datums/martial/mushpunch.dm +++ b/code/datums/martial/mushpunch.dm @@ -4,6 +4,7 @@ /datum/martial_art/mushpunch/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) var/atk_verb + var/damage = (damage_roll(A,D)*3) to_chat(A, "You begin to wind up an attack...") if(!do_after(A, 25, target = D)) to_chat(A, "Your attack was interrupted!") @@ -12,7 +13,7 @@ atk_verb = pick("punches", "smashes", "ruptures", "cracks") D.visible_message("[A] [atk_verb] [D] with inhuman strength, sending [D.p_them()] flying backwards!", \ "[A] [atk_verb] you with inhuman strength, sending you flying backwards!") - D.apply_damage(rand(15,30), BRUTE) + D.apply_damage(damage, BRUTE) //KAPOW playsound(D, 'sound/effects/meteorimpact.ogg', 25, 1, -1) var/throwtarget = get_edge_target_turf(A, get_dir(A, get_step_away(D, A))) D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time. diff --git a/code/datums/martial/plasma_fist.dm b/code/datums/martial/plasma_fist.dm index 71fb00c467..c751d3b146 100644 --- a/code/datums/martial/plasma_fist.dm +++ b/code/datums/martial/plasma_fist.dm @@ -44,11 +44,13 @@ return /datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D) + var/damage = (damage_roll(A,D)*3) D.visible_message("[A] has hit [D] with Plasma Punch!", \ "[A] has hit [D] with Plasma Punch!") playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) D.throw_at(throw_target, 200, 4,A) + D.apply_damage(damage, BRUTE) A.say("HYAH!", forced="plasma fist") log_combat(A, D, "threw back (Plasma Fist)") return diff --git a/code/datums/martial/psychotic_brawl.dm b/code/datums/martial/psychotic_brawl.dm index 75053dbbfc..06d07260ed 100644 --- a/code/datums/martial/psychotic_brawl.dm +++ b/code/datums/martial/psychotic_brawl.dm @@ -14,6 +14,7 @@ /datum/martial_art/psychotic_brawling/proc/psycho_attack(mob/living/carbon/human/A, mob/living/carbon/human/D) var/atk_verb + var/damage = damage_roll(A,D) switch(rand(1,8)) if(1) D.help_shake_act(A) @@ -44,10 +45,10 @@ D.visible_message("[A] [atk_verb] [D]!", \ "[A] [atk_verb] you!") playsound(get_turf(D), 'sound/weapons/punch1.ogg', 40, 1, -1) - D.apply_damage(rand(5,10), BRUTE, BODY_ZONE_HEAD) - A.apply_damage(rand(5,10), BRUTE, BODY_ZONE_HEAD) + D.apply_damage(damage*1.5, BRUTE, BODY_ZONE_HEAD) + A.apply_damage(damage, BRUTE, BODY_ZONE_HEAD) if(!istype(D.head,/obj/item/clothing/head/helmet/) && !istype(D.head,/obj/item/clothing/head/hardhat)) - D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5) + D.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage) A.Stun(rand(10,45)) D.DefaultCombatKnockdown(rand(5,30))//CIT CHANGE - makes stuns from martial arts always use Knockdown instead of Stun for the sake of consistency if(5,6) @@ -55,7 +56,7 @@ atk_verb = pick("punches", "kicks", "hits", "slams into") D.visible_message("[A] [atk_verb] [D] with inhuman strength, sending [D.p_them()] flying backwards!", \ "[A] [atk_verb] you with inhuman strength, sending you flying backwards!") - D.apply_damage(rand(15,30), BRUTE) + D.apply_damage(damage*2, BRUTE) playsound(get_turf(D), 'sound/effects/meteorimpact.ogg', 25, 1, -1) var/throwtarget = get_edge_target_turf(A, get_dir(A, get_step_away(D, A))) D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time. diff --git a/code/datums/martial/rising_bass.dm b/code/datums/martial/rising_bass.dm index 8055bd54e9..2d760fc10a 100644 --- a/code/datums/martial/rising_bass.dm +++ b/code/datums/martial/rising_bass.dm @@ -78,6 +78,7 @@ return TRUE /datum/martial_art/the_rising_bass/proc/sideKick(mob/living/carbon/human/A, mob/living/carbon/human/D) + var/damage = (damage_roll(A,D)*0.5) if(CHECK_MOBILITY(D, MOBILITY_STAND)) var/dir = A.dir & (NORTH | SOUTH) ? pick(EAST, WEST) : pick(NORTH, SOUTH) var/oppdir = dir == NORTH ? SOUTH : dir == SOUTH ? NORTH : dir == EAST ? WEST : EAST @@ -87,7 +88,7 @@ D.visible_message("[A] kicks [D] in the side, sliding them over!", \ "[A] kicks you in the side, forcing you to step away!") playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - D.apply_damage(5, BRUTE, BODY_ZONE_CHEST) + D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST) D.DefaultCombatKnockdown(60) var/L = !checkfordensity(H,D) ? (!checkfordensity(K,D) ? D.loc : K) : H D.forceMove(L) @@ -96,6 +97,7 @@ return TRUE /datum/martial_art/the_rising_bass/proc/shoulderFlip(mob/living/carbon/human/A, mob/living/carbon/human/D) + var/damage = (damage_roll(A,D) + 25) if(CHECK_MOBILITY(D, MOBILITY_STAND)) var/turf/H = get_step(A, get_dir(D,A)) var/L = checkfordensity(H,D) ? H : A.loc @@ -104,8 +106,8 @@ "[A] flips you over their shoulder, slamming you into the ground!") playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) D.emote("scream") - D.apply_damage(10, BRUTE, BODY_ZONE_CHEST) - D.apply_damage(30, BRUTE, BODY_ZONE_HEAD) + D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST) + D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD) D.Sleeping(60) D.DefaultCombatKnockdown(300) D.forceMove(L) @@ -114,6 +116,7 @@ return FALSE /datum/martial_art/the_rising_bass/proc/repulsePunch(mob/living/carbon/human/A, mob/living/carbon/human/D) + var/damage = damage_roll(A,D) if(CHECK_MOBILITY(D, MOBILITY_STAND) && repulsecool < world.time) A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) D.visible_message("[A] smashes [D] in the chest, throwing them away!", \ @@ -121,7 +124,7 @@ playsound(get_turf(A), 'sound/weapons/punch1.ogg', 50, 1, -1) var/atom/F = get_edge_target_turf(D, get_dir(A, get_step_away(D, A))) D.throw_at(F, 10, 1) - D.apply_damage(10, BRUTE, BODY_ZONE_CHEST) + D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST) D.DefaultCombatKnockdown(90) log_combat(A, D, "repulse punched (Rising Bass)") repulsecool = world.time + 3 SECONDS @@ -129,12 +132,13 @@ return FALSE /datum/martial_art/the_rising_bass/proc/footSmash(mob/living/carbon/human/A, mob/living/carbon/human/D) + var/damage = (damage_roll(A,D)*0.5) if(CHECK_MOBILITY(D, MOBILITY_STAND)) A.do_attack_animation(D, ATTACK_EFFECT_KICK) D.visible_message("[A] smashes their foot down on [D]'s foot!", \ "[A] smashes your foot!") playsound(get_turf(A), 'sound/weapons/punch1.ogg', 50, 1, -1) - D.apply_damage(5, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) + D.apply_damage(damage, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) D.dropItemToGround(D.get_active_held_item()) log_combat(A, D, "foot smashed (Rising Bass)") return TRUE @@ -181,7 +185,7 @@ . = ..() if(A.incapacitated(FALSE, TRUE)) //NO STUN return BULLET_ACT_HIT - if(!(A.mobility_flags & MOBILITY_USE)) //NO UNABLE TO USE + if(!CHECK_ALL_MOBILITY(A, MOBILITY_USE|MOBILITY_STAND)) //NO UNABLE TO USE, NO DODGING ON THE FLOOR return BULLET_ACT_HIT if(A.dna && A.dna.check_mutation(HULK)) //NO HULK return BULLET_ACT_HIT diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index a9e1b8a729..527ee01206 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -31,45 +31,48 @@ var/atk_verb = pick("precisely kick", "brutally chop", "cleanly hit", "viciously slam") ///this is the critical hit damage added to the attack if it rolls, it starts at 0 because it'll be changed when rolled var/crit_damage = 0 + var/damage = damage_roll(A,D) D.visible_message("[A] [atk_verb]s [D]!", \ "[A] [atk_verb]s you!", null, null, A) to_chat(A, "You [atk_verb] [D]!") if(prob(10)) - crit_damage += 20 + crit_damage += (damage*2 + 15) playsound(get_turf(D), 'sound/weapons/bite.ogg', 50, TRUE, -1) - D.visible_message("[D] sputters blood as the blow strikes them with inhuman force!", "You are struck with incredible precision by [A]!") + D.visible_message("[D] staggers as the blow strikes them with inhuman force!", "You are struck with incredible precision by [A]!") log_combat(A, D, "critcal strong punched (Sleeping Carp)")//log it here because a critical can swing for 40 force and it's important for the sake of how hard they hit else playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1) log_combat(A, D, "strong punched (Sleeping Carp)")//so as to not double up on logging - D.apply_damage(20 + crit_damage, BRUTE, affecting) + D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting) return ///Crashing Wave Kick: Harm Disarm combo, throws people seven tiles backwards /datum/martial_art/the_sleeping_carp/proc/launchKick(mob/living/carbon/human/A, mob/living/carbon/human/D) + var/damage = (damage_roll(A,D) + 15) A.do_attack_animation(D, ATTACK_EFFECT_KICK) D.visible_message("[A] kicks [D] square in the chest, sending them flying!", \ "You are kicked square in the chest by [A], sending you flying!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1) var/atom/throw_target = get_edge_target_turf(D, A.dir) D.throw_at(throw_target, 7, 14, A) - D.apply_damage(15, BRUTE, BODY_ZONE_CHEST) + D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST) log_combat(A, D, "launchkicked (Sleeping Carp)") return ///Keelhaul: Harm Grab combo, knocks people down, deals stamina damage while they're on the floor /datum/martial_art/the_sleeping_carp/proc/dropKick(mob/living/carbon/human/A, mob/living/carbon/human/D) + var/damage = damage_roll(A,D) A.do_attack_animation(D, ATTACK_EFFECT_KICK) playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1) if((D.mobility_flags & MOBILITY_STAND)) - D.apply_damage(10, BRUTE, BODY_ZONE_HEAD) + D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD) D.DefaultCombatKnockdown(50, override_hardstun = 0.01, override_stamdmg = 0) - D.adjustStaminaLoss(40) //A cit specific change form the tg port to really punish anyone who tries to stand up + D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD) //A cit specific change form the tg port to really punish anyone who tries to stand up D.visible_message("[A] kicks [D] in the head, sending them face first into the floor!", \ "You are kicked in the head by [A], sending you crashing to the floor!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) - else if(!(D.mobility_flags & MOBILITY_STAND)) - D.apply_damage(5, BRUTE, BODY_ZONE_HEAD) - D.adjustStaminaLoss(40) + else + D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD) + D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD) D.drop_all_held_items() D.visible_message("[A] kicks [D] in the head!", \ "You are kicked in the head by [A]!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) @@ -85,6 +88,7 @@ /datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) add_to_streak("H",D) + var/damage = (damage_roll(A,D) + 5) if(check_streak(A,D)) return TRUE var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) @@ -93,7 +97,7 @@ D.visible_message("[A] [atk_verb]s [D]!", \ "[A] [atk_verb]s you!", null, null, A) to_chat(A, "You [atk_verb] [D]!") - D.apply_damage(rand(10,15), BRUTE, affecting) + D.apply_damage(damage, BRUTE, affecting) playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1) log_combat(A, D, "punched (Sleeping Carp)") return TRUE @@ -110,7 +114,7 @@ . = ..() if(A.incapacitated(FALSE, TRUE)) //NO STUN return BULLET_ACT_HIT - if(!(A.mobility_flags & MOBILITY_USE)) //NO UNABLE TO USE + if(!CHECK_ALL_MOBILITY(A, MOBILITY_USE|MOBILITY_STAND)) //NO UNABLE TO USE, NO DEFLECTION ON THE FLOOR return BULLET_ACT_HIT if(A.dna && A.dna.check_mutation(HULK)) //NO HULK return BULLET_ACT_HIT @@ -121,6 +125,7 @@ playsound(get_turf(A), pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE) P.firer = A P.setAngle(rand(0, 360))//SHING + A.adjustStaminaLossBuffered (3) //Citadel change to stop infinite bullet sponging as you run away, but it is buffered! return BULLET_ACT_FORCE_PIERCE return BULLET_ACT_HIT @@ -133,7 +138,6 @@ ADD_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT) H.physiology.brute_mod *= 0.4 //brute is really not gonna cut it H.physiology.burn_mod *= 0.7 //burn is distinctly more useful against them than brute but they're still resistant - H.physiology.stamina_mod *= 0.5 //stun batons prove to be one of the few ways to fight them. They have stun resistance already, so I think doubling down too hard on this resistance is a bit much. H.physiology.stun_mod *= 0.3 //for those rare stuns H.physiology.pressure_mod *= 0.3 //go hang out with carp H.physiology.cold_mod *= 0.3 //cold mods are different to burn mods, they do stack however @@ -148,7 +152,6 @@ REMOVE_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT) H.physiology.brute_mod = initial(H.physiology.brute_mod) H.physiology.burn_mod = initial(H.physiology.burn_mod) - H.physiology.stamina_mod = initial(H.physiology.stamina_mod) H.physiology.stun_mod = initial(H.physiology.stun_mod) H.physiology.pressure_mod = initial(H.physiology.pressure_mod) //no more carpies H.physiology.cold_mod = initial(H.physiology.cold_mod) @@ -237,7 +240,7 @@ else return ..() -/obj/item/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(wielded) - return ..() - return FALSE +/obj/item/twohanded/bostaff/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!wielded) + return BLOCK_NONE + return ..() diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm index 349efdd342..f7923d029f 100644 --- a/code/datums/martial/wrestling.dm +++ b/code/datums/martial/wrestling.dm @@ -19,29 +19,29 @@ /datum/martial_art/wrestling/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(!can_use(A, D)) - return 0 + return FALSE switch(streak) if("drop") streak = "" drop(A,D) - return 1 + return TRUE if("strike") streak = "" strike(A,D) - return 1 + return TRUE if("kick") streak = "" kick(A,D) - return 1 + return TRUE if("throw") streak = "" throw_wrassle(A,D) - return 1 + return TRUE if("slam") streak = "" slam(A,D) - return 1 - return 0 + return TRUE + return FALSE /datum/action/slam name = "Slam (Cinch) - Slam a grappled opponent into the floor." @@ -138,7 +138,7 @@ /datum/martial_art/wrestling/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) if(check_streak(A,D)) - return 1 + return TRUE log_combat(A, D, "punched with wrestling") ..() @@ -173,11 +173,11 @@ if (get_dist(A, D) > 1) to_chat(A, "[D] is too far away!") - return 0 + return FALSE if (!isturf(A.loc) || !isturf(D.loc)) to_chat(A, "You can't throw [D] from here!") - return 0 + return FALSE A.setDir(turn(A.dir, 90)) var/turf/T = get_step(A, A.dir) @@ -186,7 +186,7 @@ D.forceMove(T) D.setDir(get_dir(D, A)) else - return 0 + return FALSE sleep(delay) @@ -195,11 +195,11 @@ if (get_dist(A, D) > 1) to_chat(A, "[D] is too far away!") - return 0 + return FALSE if (!isturf(A.loc) || !isturf(D.loc)) to_chat(A, "You can't throw [D] from here!") - return 0 + return FALSE D.forceMove(A.loc) // Maybe this will help with the wallthrowing bug. @@ -211,7 +211,7 @@ D.emote("scream") D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human.proc/DefaultCombatKnockdown, 20)) log_combat(A, D, "has thrown with wrestling") - return 0 + return FALSE /datum/martial_art/wrestling/proc/FlipAnimation(mob/living/carbon/human/D) set waitfor = FALSE @@ -227,6 +227,7 @@ if(!A.pulling || A.pulling != D) to_chat(A, "You need to have [D] in a cinch!") return + var/damage = damage_roll(A,D) D.forceMove(A.loc) A.setDir(get_dir(A, D)) D.setDir(get_dir(D, A)) @@ -258,7 +259,7 @@ A.pixel_y = 0 D.pixel_x = 0 D.pixel_y = 0 - return 0 + return FALSE if (!isturf(A.loc) || !isturf(D.loc)) to_chat(A, "You can't slam [D] here!") @@ -266,7 +267,7 @@ A.pixel_y = 0 D.pixel_x = 0 D.pixel_y = 0 - return 0 + return FALSE else if (A) A.pixel_x = 0 @@ -274,7 +275,7 @@ if (D) D.pixel_x = 0 D.pixel_y = 0 - return 0 + return FALSE sleep(1) @@ -286,11 +287,11 @@ if (get_dist(A, D) > 1) to_chat(A, "[D] is too far away!") - return 0 + return FALSE if (!isturf(A.loc) || !isturf(D.loc)) to_chat(A, "You can't slam [D] here!") - return 0 + return FALSE D.forceMove(A.loc) @@ -309,11 +310,11 @@ switch(rand(1,3)) if (2) - D.adjustBruteLoss(rand(20,30)) + D.apply_damage(damage + 25, BRUTE) if (3) D.ex_act(EXPLODE_LIGHT) else - D.adjustBruteLoss(rand(10,20)) + D.apply_damage(damage + 15, BRUTE) else D.ex_act(EXPLODE_LIGHT) @@ -327,7 +328,7 @@ log_combat(A, D, "body-slammed") - return 0 + return FALSE /datum/martial_art/wrestling/proc/CheckStrikeTurf(mob/living/carbon/human/A, turf/T) if (A && (T && isturf(T) && get_dist(A, T) <= 1)) @@ -337,6 +338,7 @@ if(!D) return var/turf/T = get_turf(A) + var/damage = damage_roll(A,D) if (T && isturf(T) && D && isturf(D.loc)) for (var/i = 0, i < 4, i++) A.setDir(turn(A.dir, 90)) @@ -345,7 +347,7 @@ addtimer(CALLBACK(src, .proc/CheckStrikeTurf, A, T), 4) A.visible_message("[A] headbutts [D]!") - D.adjustBruteLoss(rand(10,20)) + D.apply_damage(damage + 15, BRUTE) playsound(A.loc, "swing_hit", 50, 1) D.Unconscious(20) log_combat(A, D, "headbutted") @@ -353,13 +355,14 @@ /datum/martial_art/wrestling/proc/kick(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!D) return + var/damage = damage_roll(A,D) A.emote("scream") A.emote("flip") A.setDir(turn(A.dir, 90)) A.visible_message("[A] roundhouse-kicks [D]!") playsound(A.loc, "swing_hit", 50, 1) - D.adjustBruteLoss(rand(10,20)) + D.apply_damage(damage + 15, STAMINA) var/turf/T = get_edge_target_turf(A, get_dir(A, get_step_away(D, A))) if (T && isturf(T)) @@ -373,7 +376,8 @@ var/obj/surface = null var/turf/ST = null var/falling = 0 - + var/damage = damage_roll(A,D) + for (var/obj/O in oview(1, A)) if (O.density == 1) if (O == A) @@ -401,15 +405,15 @@ A.pixel_y = 0 if (falling == 1) A.visible_message("...and dives head-first into the ground, ouch!") - A.adjustBruteLoss(rand(10,20)) + A.apply_damage(damage + 15, BRUTE) A.DefaultCombatKnockdown(60) to_chat(A, "[D] is too far away!") - return 0 + return FALSE if (!isturf(A.loc) || !isturf(D.loc)) A.pixel_y = 0 to_chat(A, "You can't drop onto [D] from here!") - return 0 + return FALSE if(A) animate(A, transform = matrix(90, MATRIX_ROTATE), time = 1, loop = 0) @@ -427,9 +431,9 @@ if (prob(33) || D.stat) D.ex_act(EXPLODE_LIGHT) else - D.adjustBruteLoss(rand(20,30)) + D.apply_damage(damage + 25, BRUTE) else - D.adjustBruteLoss(rand(20,30)) + D.apply_damage(damage + 25, BRUTE) D.DefaultCombatKnockdown(40) @@ -442,14 +446,16 @@ return /datum/martial_art/wrestling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + damage_roll(A,D) if(check_streak(A,D)) - return 1 + return TRUE log_combat(A, D, "wrestling-disarmed") ..() /datum/martial_art/wrestling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + damage_roll(A,D) if(check_streak(A,D)) - return 1 + return TRUE if(!can_use(A,D)) return ..() if(A.pulling == D || A == D) // don't stun grab yoursel @@ -459,7 +465,7 @@ "[A] gets [D] in a cinch!") D.Stun(rand(60,100)) log_combat(A, D, "cinched") - return 1 + return TRUE /obj/item/storage/belt/champion/wrestling name = "Wrestling Belt" @@ -492,7 +498,7 @@ //Make sure that moves can only be used on people wearing the holodeck belt /datum/martial_art/wrestling/holodeck/can_use(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) if(!(istype(D.mind?.martial_art, /datum/martial_art/wrestling/holodeck))) - return 0 + return FALSE else return ..() diff --git a/code/datums/mutations/combined.dm b/code/datums/mutations/combined.dm index d3cc83f9c0..465706c897 100644 --- a/code/datums/mutations/combined.dm +++ b/code/datums/mutations/combined.dm @@ -26,3 +26,7 @@ /datum/generecipe/tonguechem required = "/datum/mutation/human/tongue_spike; /datum/mutation/human/stimmed" result = TONGUESPIKECHEM + +/datum/generecipe/hulk + required = "/datum/mutation/human/strong; /datum/mutation/human/radioactive" + result = HULK diff --git a/code/datums/radiation_wave.dm b/code/datums/radiation_wave.dm index 4795f8da60..5dce5791c2 100644 --- a/code/datums/radiation_wave.dm +++ b/code/datums/radiation_wave.dm @@ -117,7 +117,7 @@ continue contam_atoms += thing var/did_contam = 0 - if(length(can_contam)) + if(can_contam) var/rad_strength = ((strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT)/contam_atoms.len for(var/k in 1 to contam_atoms.len) var/atom/thing = contam_atoms[k] diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 5a69ebe427..69b74841df 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -113,20 +113,25 @@ duration = set_duration . = ..() -/datum/status_effect/no_combat_mode/mesmerize +/datum/status_effect/mesmerize id = "Mesmerize" alert_type = /obj/screen/alert/status_effect/mesmerized -/datum/status_effect/no_combat_mode/mesmerize/on_creation(mob/living/new_owner, set_duration) +/datum/status_effect/mesmerize/on_creation(mob/living/new_owner, set_duration) . = ..() ADD_TRAIT(owner, TRAIT_MUTE, "mesmerize") owner.add_movespeed_modifier("[STATUS_EFFECT_MESMERIZE]_[id]", TRUE, priority = 64, override = TRUE, multiplicative_slowdown = 5, blacklisted_movetypes = FALSE? NONE : CRAWLING) -/datum/status_effect/no_combat_mode/mesmerize/on_remove() +/datum/status_effect/mesmerize/on_remove() . = ..() REMOVE_TRAIT(owner, TRAIT_MUTE, "mesmerize") owner.remove_movespeed_modifier("[STATUS_EFFECT_MESMERIZE]_[id]") +/datum/status_effect/mesmerize/on_creation(mob/living/new_owner, set_duration) + if(isnum(set_duration)) + duration = set_duration + . = ..() + /obj/screen/alert/status_effect/mesmerized name = "Mesmerized" desc = "You cant tear your sight from who is in front of you... their gaze is simply too enthralling.." diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index d4a5dcdeb3..ad24126e45 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -38,7 +38,6 @@ ..() if(!istype(holder, holder_type)) CRASH("Wire holder is not of the expected type!") - return src.holder = holder if(randomize) diff --git a/code/game/area/areas/holodeck.dm b/code/game/area/areas/holodeck.dm index d32091f98b..75ed2b656c 100644 --- a/code/game/area/areas/holodeck.dm +++ b/code/game/area/areas/holodeck.dm @@ -6,6 +6,8 @@ hidden = TRUE var/obj/machinery/computer/holodeck/linked + var/list/compatible_holodeck_comps + var/abstract_type = /area/holodeck var/restricted = 0 // if true, program goes on emag list /* @@ -53,6 +55,8 @@ */ /area/holodeck/rec_center name = "\improper Recreational Holodeck" + compatible_holodeck_comps = list(/obj/machinery/computer/holodeck) + abstract_type = /area/holodeck/rec_center /area/holodeck/rec_center/offline name = "Holodeck - Offline" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 266d5b5bb5..44a891e24a 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -584,11 +584,8 @@ stoplag(1) qdel(progress) to_chat(user, "You dump as much of [src_object.parent]'s contents into [STR.insert_preposition]to [src] as you can.") - STR.orient2hud(user) - src_object.orient2hud(user) if(user.active_storage) //refresh the HUD to show the transfered contents - user.active_storage.close(user) - user.active_storage.show_to(user) + user.active_storage.ui_show(user) return TRUE /atom/proc/get_dumping_location(obj/item/storage/source,mob/user) diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 1a57cf5051..413484b99b 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -147,7 +147,6 @@ return "health-85" else return "health-100" - return "0" //HOOKS @@ -323,7 +322,6 @@ return "crit" else return "dead" - return "dead" //Sillycone hooks /mob/living/silicon/proc/diag_hud_set_health() diff --git a/code/game/gamemodes/bloodsucker/bloodsucker.dm b/code/game/gamemodes/bloodsucker/bloodsucker.dm index 9515d6063c..bb776d7bc0 100644 --- a/code/game/gamemodes/bloodsucker/bloodsucker.dm +++ b/code/game/gamemodes/bloodsucker/bloodsucker.dm @@ -9,8 +9,14 @@ var/list/vassal_allowed_antags = list(/datum/antagonist/brother, /datum/antagonist/traitor, /datum/antagonist/traitor/internal_affairs, /datum/antagonist/survivalist, \ /datum/antagonist/rev, /datum/antagonist/nukeop, /datum/antagonist/pirate, /datum/antagonist/cult, /datum/antagonist/abductee, /datum/antagonist/valentine, /datum/antagonist/heartbreaker,) // The antags you're allowed to be if turning Vassal. -/proc/isvamp(mob/living/M) - return istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/bloodsucker) + +/proc/AmBloodsucker(mob/living/M, falseIfInDisguise = FALSE) + if(!M.mind) + return FALSE + // No Datum + if(!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) + return FALSE + return TRUE /datum/game_mode/bloodsucker name = "bloodsucker" @@ -70,49 +76,27 @@ // Gamemode is all done being set up. We have all our Vamps. We now pick objectives and let them know what's happening. /datum/game_mode/bloodsucker/post_setup() - // Sunlight (Creating Bloodsuckers manually will check to create this, too) check_start_sunlight() - // Vamps for(var/datum/mind/bloodsucker in bloodsuckers) - // spawn() --> Run block of code but game continues on past it. - // sleep() --> Run block of code and freeze code there (including whoever called us) until it's resolved. - - //Clean Bloodsucker Species (racist?) - //clean_invalid_species(bloodsucker) - // TO-DO !!! - - // Add Bloodsucker Antag Datum (or remove from list on Fail) - if (!make_bloodsucker(bloodsucker)) + if(!make_bloodsucker(bloodsucker)) bloodsuckers -= bloodsucker - - // NOTE: Hunters are done in ..() parent proc - return ..() -// Checking for ACTUALLY Dead Vamps -/datum/game_mode/bloodsucker/are_special_antags_dead() - // Bloodsucker not Final Dead - for(var/datum/mind/bloodsucker in bloodsuckers) - if(!bloodsucker.AmFinalDeath()) - return FALSE - return TRUE - - // Init Sunlight (called from datum_bloodsucker.on_gain(), in case game mode isn't even Bloodsucker /datum/game_mode/proc/check_start_sunlight() // Already Sunlight (and not about to cancel) - if (istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me) + if(istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me) return bloodsucker_sunlight = new () // End Sun (last bloodsucker removed) /datum/game_mode/proc/check_cancel_sunlight() // No Sunlight - if (!istype(bloodsucker_sunlight)) + if(!istype(bloodsucker_sunlight)) return - if (bloodsuckers.len <= 0) + if(bloodsuckers.len <= 0) bloodsucker_sunlight.cancel_me = TRUE qdel(bloodsucker_sunlight) bloodsucker_sunlight = null @@ -151,43 +135,37 @@ // Not High Enough if(creator) var/datum/antagonist/bloodsucker/creator_bloodsucker = creator.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - if(!istype(creator_bloodsucker) || creator_bloodsucker.vamplevel < BLOODSUCKER_LEVEL_TO_EMBRACE) + if(!istype(creator_bloodsucker) || creator_bloodsucker.bloodsucker_level < BLOODSUCKER_LEVEL_TO_EMBRACE) to_chat(creator, "Your blood is too thin to turn this corpse!") return FALSE return TRUE /datum/game_mode/proc/make_bloodsucker(datum/mind/bloodsucker, datum/mind/creator = null) // NOTE: This is a game_mode/proc, NOT a game_mode/bloodsucker/proc! We need to access this function despite the game mode. - if (!can_make_bloodsucker(bloodsucker)) + if(!can_make_bloodsucker(bloodsucker)) return FALSE - // Create Datum: Fledgling var/datum/antagonist/bloodsucker/A // [FLEDGLING] - if (creator) + if(creator) A = new (bloodsucker) A.creator = creator bloodsucker.add_antag_datum(A) // Log message_admins("[bloodsucker] has become a Bloodsucker, and was created by [creator].") log_admin("[bloodsucker] has become a Bloodsucker, and was created by [creator].") - // [MASTER] else A = bloodsucker.add_antag_datum(ANTAG_DATUM_BLOODSUCKER) - - return TRUE - /datum/game_mode/proc/remove_bloodsucker(datum/mind/bloodsucker) bloodsucker.remove_antag_datum(ANTAG_DATUM_BLOODSUCKER) - /datum/game_mode/proc/clean_invalid_species(datum/mind/bloodsucker) // Only checking for Humans here - if (!ishuman(bloodsucker.current) || !bloodsucker.current.client) + if(!ishuman(bloodsucker.current) || !bloodsucker.current.client) return var/am_valid = TRUE var/mob/living/carbon/human/H = bloodsucker.current @@ -202,7 +180,7 @@ // everyone will wonder why you're a human with Plasma clothes (jk they'll know you're antag) // Convert to HUMAN (along with ID and PDA) - if (!am_valid) + if(!am_valid) H.set_species(/datum/species/human) H.real_name = H.client.prefs.custom_names["human"] var/obj/item/card/id/ID = H.wear_id?.GetID() @@ -211,12 +189,13 @@ ID.update_label() -/datum/game_mode/proc/can_make_vassal(mob/living/target, datum/mind/creator, display_warning=TRUE)//, check_antag_or_loyal=FALSE) +/datum/game_mode/proc/can_make_vassal(mob/living/target, datum/mind/creator, display_warning = TRUE)//, check_antag_or_loyal=FALSE) // Not Correct Type: Abort - if (!iscarbon(target) || !creator) + if(!iscarbon(target) || !creator) return FALSE - if (target.stat > UNCONSCIOUS) + if(target.stat > UNCONSCIOUS) return FALSE + // Check Overdose: Am I even addicted to blood? Do I even have any in me? //if (!target.reagents.addiction_list || !target.reagents.reagent_list) //message_admins("DEBUG2: can_make_vassal() Abort: No reagents") @@ -233,23 +212,23 @@ //message_admins("DEBUG4: can_make_vassal() Abort: No Blood") // return 0 // No Mind! - if (!target.mind || !target.mind.key) - if (display_warning) + if(!target.mind || !target.mind.key) + if(display_warning) to_chat(creator, "[target] isn't self-aware enough to be made into a Vassal.") return FALSE // Already MY Vassal var/datum/antagonist/vassal/V = target.mind.has_antag_datum(ANTAG_DATUM_VASSAL) - if (istype(V) && V.master) - if (V.master.owner == creator) - if (display_warning) + if(istype(V) && V.master) + if(V.master.owner == creator) + if(display_warning) to_chat(creator, "[target] is already your loyal Vassal!") else - if (display_warning) + if(display_warning) to_chat(creator, "[target] is the loyal Vassal of another Bloodsucker!") return FALSE // Already Antag or Loyal (Vamp Hunters count as antags) - if (target.mind.enslaved_to || AmInvalidAntag(target.mind)) //!VassalCheckAntagValid(target.mind, check_antag_or_loyal)) // HAS_TRAIT(target, TRAIT_MINDSHIELD, "implant") || - if (display_warning) + if(target.mind.enslaved_to || AmInvalidAntag(target.mind)) //!VassalCheckAntagValid(target.mind, check_antag_or_loyal)) // HAS_TRAIT(target, TRAIT_MINDSHIELD, "implant") || + if(display_warning) to_chat(creator, "[target] resists the power of your blood to dominate their mind!") return FALSE return TRUE @@ -268,24 +247,24 @@ return FALSE // Does even ONE antag appear in this mind that isn't in the list? Then FAIL! for(var/datum/antagonist/antag_datum in M.antag_datums) - if (!(antag_datum.type in vassal_allowed_antags)) // vassal_allowed_antags is a list stored in the game mode, above. + if(!(antag_datum.type in vassal_allowed_antags)) // vassal_allowed_antags is a list stored in the game mode, above. //message_admins("DEBUG VASSAL: Found Invalid: [antag_datum] // [antag_datum.type]") return TRUE //message_admins("DEBUG VASSAL: Valid Antags! (total of [M.antag_datums.len])") // WHEN YOU DELETE THE ABOVE: Remove the 3 second timer on converting the vassal too. return FALSE -/datum/game_mode/proc/make_vassal(mob/living/target, datum/mind/creator) - if (!can_make_vassal(target,creator)) +/datum/game_mode/proc/make_vassal(var/mob/living/target, var/datum/mind/creator) + if(!can_make_vassal(target, creator)) return FALSE // Make Vassal - var/datum/antagonist/vassal/V = new (target.mind) + var/datum/antagonist/vassal/V = new(target.mind) var/datum/antagonist/bloodsucker/B = creator.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) V.master = B target.mind.add_antag_datum(V, V.master.get_team()) // Update Bloodsucker Title (we're a daddy now) B.SelectTitle(am_fledgling = FALSE) // Only works if you have no title yet. - // Log + // Log it message_admins("[target] has become a Vassal, and is enslaved to [creator].") log_admin("[target] has become a Vassal, and is enslaved to [creator].") return TRUE diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 4db8f4129a..8029685bf7 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -119,7 +119,6 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th C.appearance = chosen_prof.appearance_list[slot] C.name = chosen_prof.name_list[slot] C.flags_cover = chosen_prof.flags_cover_list[slot] - C.item_color = chosen_prof.item_color_list[slot] C.item_state = chosen_prof.item_state_list[slot] if(equip) user.equip_to_slot_or_del(C, GLOB.slot2slot[slot]) diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 15d7744205..7b798f19e4 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -45,8 +45,11 @@ Credit where due: // PROCS // /////////// -/proc/is_servant_of_ratvar(mob/M) - return istype(M) && !isobserver(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/clockcult) +/proc/is_servant_of_ratvar(mob/M, require_full_power = FALSE, holy_water_check = FALSE) + if(!istype(M) || isobserver(M)) + return FALSE + var/datum/antagonist/clockcult/D = M?.mind?.has_antag_datum(/datum/antagonist/clockcult) + return D && (!require_full_power || !D.neutered) && (!holy_water_check || !D.ignore_holy_water) /proc/is_eligible_servant(mob/M) if(!istype(M)) @@ -70,12 +73,14 @@ Credit where due: return TRUE return FALSE -/proc/add_servant_of_ratvar(mob/L, silent = FALSE, create_team = TRUE) +/proc/add_servant_of_ratvar(mob/L, silent = FALSE, create_team = TRUE, override_type) if(!L || !L.mind) return var/update_type = /datum/antagonist/clockcult if(silent) update_type = /datum/antagonist/clockcult/silent + if(override_type) //prioritizes + update_type = override_type var/datum/antagonist/clockcult/C = new update_type(L.mind) C.make_team = create_team C.show_in_roundend = create_team //tutorial scarabs begone @@ -105,9 +110,6 @@ Credit where due: L.playsound_local(get_turf(L), 'sound/ambience/antag/clockcultalr.ogg', 40, TRUE, frequency = 100000, pressure_affected = FALSE) flash_color(L, flash_color = list("#BE8700", "#BE8700", "#BE8700", rgb(0,0,0)), flash_time = 5) - - - /proc/remove_servant_of_ratvar(mob/L, silent = FALSE) if(!L || !L.mind) return diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index 0a231a5ff1..4d3ea2d02e 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -63,7 +63,7 @@ attack_verb_on = list("slipped") clumsy_check = FALSE sharpness = IS_BLUNT - item_color = "yellow" + sword_color = "yellow" heat = 0 light_color = "#ffff00" var/next_trombone_allowed = 0 diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 497cc2f1c3..8ec4123201 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -3,8 +3,11 @@ /datum/game_mode var/list/datum/mind/cult = list() -/proc/iscultist(mob/living/M) - return istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/cult) +/proc/iscultist(mob/living/M, require_full_power = FALSE, holy_water_check = FALSE) + if(!istype(M)) + return FALSE + var/datum/antagonist/cult/D = M?.mind?.has_antag_datum(/datum/antagonist/cult) + return D && (!require_full_power || !D.neutered) && (!holy_water_check || !D.ignore_holy_water) /datum/team/cult/proc/is_sacrifice_target(datum/mind/mind) for(var/datum/objective/sacrifice/sac_objective in objectives) @@ -93,7 +96,7 @@ add_cultist(cult_mind, 0, equip=TRUE) if(!main_cult) var/datum/antagonist/cult/C = cult_mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(C && C.cult_team) + if(C?.cult_team) main_cult = C.cult_team ..() diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index b8a5e72d55..d548f373db 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -54,12 +54,18 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) // Current storyteller var/datum/dynamic_storyteller/storyteller = null // Threat logging vars + /// Starting threat level, for things that increase it but can bring it back down. + var/initial_threat_level = 0 /// Target threat level right now. Events and antags will try to keep the round at this level. var/threat_level = 0 /// The current antag threat. Recalculated every time a ruletype starts or ends. var/threat = 0 - /// Starting threat level, for things that increase it but can bring it back down. - var/initial_threat_level = 0 + /// Threat average over the course of the round, for endgame logs. + var/threat_average = 0 + /// Number of times threat average has been calculated, for calculating above. + var/threat_average_weight = 0 + /// Last time a threat average sample was taken. Used for weighting the rolling average. + var/last_threat_sample_time = 0 /// Things that cause a rolling threat adjustment to be displayed at roundend. var/list/threat_tallies = list() /// Running information about the threat. Can store text or datum entries. @@ -199,7 +205,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) if(threatadd > 0) create_threat(threatadd) else - spend_threat(-threatadd) + remove_threat(threatadd) else if (href_list["injectlate"]) latejoin_injection_cooldown = 0 forced_injection = TRUE @@ -241,6 +247,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) . += "Peaceful Waypoint
" . += "Your station orbits deep within controlled, core-sector systems and serves as a waypoint for routine traffic through Nanotrasen's trade empire. Due to the combination of high security, interstellar traffic, and low strategic value, it makes any direct threat of violence unlikely. Your primary enemies will be incompetence and bored crewmen: try to organize team-building events to keep staffers interested and productive. However, even deep in our territory there may be subversive elements, especially for such a high-value target as your station. Keep an eye out, but don't expect much trouble." set_security_level(SEC_LEVEL_GREEN) + station_goals.len = 0 for(var/T in subtypesof(/datum/station_goal)) var/datum/station_goal/G = new T if(!(G in station_goals)) @@ -251,6 +258,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) . += "Core Territory
" . += "Your station orbits within reliably mundane, secure space. Although Nanotrasen has a firm grip on security in your region, the valuable resources and strategic position aboard your station make it a potential target for infiltrations. Monitor crew for non-loyal behavior, but expect a relatively tame shift free of large-scale destruction. We expect great things from your station." set_security_level(SEC_LEVEL_GREEN) + station_goals.len = 0 for(var/T in subtypesof(/datum/station_goal)) var/datum/station_goal/G = new T if(!(G in station_goals)) @@ -490,7 +498,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) starting_rule = pickweight(drafted_rules) // Check if the ruleset is highlander and if a highlander ruleset has been executed else if(starting_rule.flags & HIGHLANDER_RULESET) // Should already be filtered out, but making sure. Check filtering at end of proc if reported. - if(threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking) + if(threat_level <= GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking) if(highlander_executed) drafted_rules -= starting_rule if(drafted_rules.len <= 0) @@ -715,6 +723,16 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) continue current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow) threat = storyteller.calculate_threat() + added_threat + if(threat_average_weight) + var/cur_sample_weight = world.time - last_threat_sample_time + threat_average = ((threat_average * threat_average_weight) + (threat * cur_sample_weight)) / (threat_average_weight + cur_sample_weight) + threat_average_weight += cur_sample_weight + last_threat_sample_time = world.time + else + threat_average = threat + threat_average_weight++ + last_threat_sample_time = world.time + /// Removes type from the list /datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type) for(var/I in type_list) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index cec6f31e99..da33da5f43 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -222,6 +222,26 @@ message_admins("[M.name] was made into a bloodsucker by dynamic.") return TRUE +////////////////////////////////////////////// +// // +// CHANGELINGS // +// // +////////////////////////////////////////////// + +/datum/dynamic_ruleset/latejoin/changeling + name = "Changeling Infiltrator" + config_tag = "latejoin_changeling" + antag_flag = ROLE_CHANGELING + antag_datum = /datum/antagonist/changeling + restricted_roles = list("AI", "Cyborg") + protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") + required_candidates = 1 + weight = 3 + cost = 15 + requirements = list(101,101,101,101,101,101,101,101,101,101) + property_weights = list("trust" = -2, "valid" = 2) + high_population_requirement = 101 + ////////////////////////////////////////////// // // // COLLECTOR // diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index b746100f27..48e306b2b5 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -34,8 +34,7 @@ living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS]) living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS]) list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS]) - var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility)) - ghost_eligible = trim_list(eligibility.get_all_ghost_role_eligible()) + ghost_eligible = trim_list(get_all_ghost_role_eligible()) /datum/dynamic_ruleset/midround/proc/trim_list(list/L = list()) var/list/trimmed_list = L.Copy() diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index 35d5a04488..c37eb9bc2a 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -11,6 +11,7 @@ WAROPS_ALWAYS_ALLOWED: Can always do warops, regardless of threat level. USE_PREF_WEIGHTS: Will use peoples' preferences to change the threat centre. FORCE_IF_WON: If this mode won the vote, forces it + USE_PREV_ROUND_WEIGHTS: Changes its threat centre based on the average chaos of previous rounds. */ var/flags = 0 var/dead_player_weight = 1 // How much dead players matter for threat calculation @@ -92,6 +93,8 @@ Property weights are: mean += 5 if(voters) GLOB.dynamic_curve_centre += (mean/voters) + if(flags & USE_PREV_ROUND_WEIGHTS) + GLOB.dynamic_curve_centre += (50 - SSpersistence.average_dynamic_threat) / 10 GLOB.dynamic_forced_threat_level = forced_threat_level /datum/dynamic_storyteller/proc/get_midround_cooldown() @@ -230,7 +233,7 @@ Property weights are: curve_width = 1.5 weight = 2 min_players = 30 - flags = WAROPS_ALWAYS_ALLOWED + flags = WAROPS_ALWAYS_ALLOWED | USE_PREV_ROUND_WEIGHTS property_weights = list("valid" = 3, "trust" = 5) /datum/dynamic_storyteller/team/get_injection_chance(dry_run = FALSE) @@ -268,9 +271,6 @@ Property weights are: /datum/dynamic_storyteller/random/get_injection_chance() return 50 // i would do rand(0,100) but it's actually the same thing when you do the math -/datum/dynamic_storyteller/random/calculate_threat() - return 0 // what IS threat - /datum/dynamic_storyteller/random/roundstart_draft() var/list/drafted_rules = list() for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules) @@ -324,6 +324,7 @@ Property weights are: desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies. Has a buildup-climax-falling action threat curve." weight = 2 curve_width = 2 + flags = USE_PREV_ROUND_WEIGHTS property_weights = list("story_potential" = 2) @@ -336,7 +337,7 @@ Property weights are: name = "Classic" config_tag = "classic" desc = "No special antagonist weights. Good variety, but not like random. Uses your chaos preference to weight." - flags = USE_PREF_WEIGHTS + flags = USE_PREF_WEIGHTS | USE_PREV_ROUND_WEIGHTS /datum/dynamic_storyteller/suspicion name = "Intrigue" @@ -345,6 +346,7 @@ Property weights are: weight = 2 curve_width = 2 dead_player_weight = 2 + flags = USE_PREV_ROUND_WEIGHTS property_weights = list("trust" = -3) /datum/dynamic_storyteller/liteextended diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index c8b8e7c9cd..e386674b9e 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -381,14 +381,12 @@ for(var/obj/machinery/camera/C in oview(4, M)) if(C.can_use()) // check if camera disabled return C - break return null /proc/near_range_camera(var/mob/M) for(var/obj/machinery/camera/C in range(4, M)) if(C.can_use()) // check if camera disabled return C - break return null diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 648c227c0a..bc0fec68ba 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -144,6 +144,8 @@ return FALSE if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding. return FALSE + if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker + return FALSE if(clonemind.active) //somebody is using that mind if( ckey(clonemind.key)!=ckey ) return FALSE @@ -159,8 +161,6 @@ mess = TRUE update_icon() return FALSE - if(isvamp(clonemind)) //If the mind is a bloodsucker - return FALSE attempting = TRUE //One at a time!! countdown.start() diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index b561224668..f78a05244e 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -55,7 +55,7 @@ /obj/item/stack/tile/fakespace/loaded = ARCADE_WEIGHT_TRICK, /obj/item/stack/tile/fakepit/loaded = ARCADE_WEIGHT_TRICK, /obj/item/restraints/handcuffs/fake = ARCADE_WEIGHT_TRICK, - /obj/item/clothing/gloves/rapid/hug = ARCADE_WEIGHT_TRICK, + /obj/item/clothing/gloves/fingerless/pugilist/rapid/hug = ARCADE_WEIGHT_TRICK, /obj/item/grenade/chem_grenade/glitter/pink = ARCADE_WEIGHT_TRICK, /obj/item/grenade/chem_grenade/glitter/blue = ARCADE_WEIGHT_TRICK, diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 47c761fa52..eb7f194229 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -45,11 +45,11 @@ if (ismob(user) && !isliving(user)) // ghosts don't need cameras return if (!network) - CRASH("No camera network") + stack_trace("No camera network") user.unset_machine() return FALSE if (!(islist(network))) - CRASH("Camera network is not a list") + stack_trace("Camera network is not a list") user.unset_machine() return FALSE diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index bd81b79694..4c3d85a162 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -292,6 +292,10 @@ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) CentCom_announce(input, usr) to_chat(usr, "Message transmitted to Central Command.") + for(var/client/X in GLOB.admins) + if(X.prefs.toggles & SOUND_ADMINHELP) + SEND_SOUND(X, sound('sound/effects/printer.ogg')) + window_flash(X, ignorepref = FALSE) usr.log_talk(input, LOG_SAY, tag="CentCom announcement") deadchat_broadcast("[usr.real_name] has messaged CentCom, \"[input]\" at [get_area_name(usr, TRUE)].", usr) CM.lastTimeUsed = world.time @@ -309,6 +313,10 @@ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) Syndicate_announce(input, usr) to_chat(usr, "SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.") + for(var/client/X in GLOB.admins) + if(X.prefs.toggles & SOUND_ADMINHELP) + SEND_SOUND(X, sound('sound/effects/printer.ogg')) + window_flash(X, ignorepref = FALSE) usr.log_talk(input, LOG_SAY, tag="Syndicate announcement") deadchat_broadcast("[usr.real_name] has messaged the Syndicate, \"[input]\" at [get_area_name(usr, TRUE)].", usr) CM.lastTimeUsed = world.time diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index 0f5e51215d..d01f7e3e40 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -57,7 +57,7 @@ var/turf/target = locate(target_x, target_y, z) ghost.forceMove(target) -/obj/machinery/launchpad/proc/isAvailable() +/obj/machinery/launchpad/proc/isAvailable(silent = FALSE) if(stat & NOPOWER) return FALSE if(panel_open) @@ -198,7 +198,7 @@ QDEL_NULL(briefcase) return ..() -/obj/machinery/launchpad/briefcase/isAvailable() +/obj/machinery/launchpad/briefcase/isAvailable(silent = FALSE) if(closed) return FALSE return ..() diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index c05fbe229c..000585a4be 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -469,7 +469,6 @@ GLOBAL_LIST_EMPTY(allConsoles) if(newmessagepriority < EXTREME_MESSAGE_PRIORITY) newmessagepriority = EXTREME_MESSAGE_PRIORITY update_icon() - if(1) playsound(src, 'sound/machines/twobeep.ogg', 50, 1) say(title) messages += "!!!Extreme Priority!!!
From: [linkedsender]
[message]" diff --git a/code/game/machinery/telecomms/machines/broadcaster.dm b/code/game/machinery/telecomms/machines/broadcaster.dm index 6b03bcc880..d16835eee7 100644 --- a/code/game/machinery/telecomms/machines/broadcaster.dm +++ b/code/game/machinery/telecomms/machines/broadcaster.dm @@ -17,6 +17,11 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages idle_power_usage = 25 circuit = /obj/item/circuitboard/machine/telecomms/broadcaster +/obj/machinery/telecomms/broadcaster/RefreshParts() + idle_power_usage = 25 + for(var/obj/item/stock_parts/manipulator/P in component_parts) + idle_power_usage -= (P.rating * 1.5) //Has 2 manipulators + /obj/machinery/telecomms/broadcaster/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from) // Don't broadcast rejected signals if(!istype(signal)) diff --git a/code/game/machinery/telecomms/machines/bus.dm b/code/game/machinery/telecomms/machines/bus.dm index ce5ed31094..4732c5bddd 100644 --- a/code/game/machinery/telecomms/machines/bus.dm +++ b/code/game/machinery/telecomms/machines/bus.dm @@ -19,6 +19,11 @@ circuit = /obj/item/circuitboard/machine/telecomms/bus var/change_frequency = 0 +/obj/machinery/telecomms/bus/RefreshParts() + idle_power_usage = 50 + for(var/obj/item/stock_parts/manipulator/P in component_parts) + idle_power_usage -= (P.rating * 2) //Has 2 manipulators + /obj/machinery/telecomms/bus/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from) if(!istype(signal) || !is_freq_listening(signal)) return diff --git a/code/game/machinery/telecomms/machines/hub.dm b/code/game/machinery/telecomms/machines/hub.dm index e7e3788774..e960dab422 100644 --- a/code/game/machinery/telecomms/machines/hub.dm +++ b/code/game/machinery/telecomms/machines/hub.dm @@ -19,6 +19,11 @@ netspeed = 40 circuit = /obj/item/circuitboard/machine/telecomms/hub +/obj/machinery/telecomms/hub/RefreshParts() + idle_power_usage = 80 + for(var/obj/item/stock_parts/manipulator/P in component_parts) + idle_power_usage -= (P.rating * 5) //Has 2 manipulators + /obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) if(!is_freq_listening(signal)) return diff --git a/code/game/machinery/telecomms/machines/processor.dm b/code/game/machinery/telecomms/machines/processor.dm index a09b3ca8fb..269f5269f3 100644 --- a/code/game/machinery/telecomms/machines/processor.dm +++ b/code/game/machinery/telecomms/machines/processor.dm @@ -16,6 +16,11 @@ circuit = /obj/item/circuitboard/machine/telecomms/processor var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals +/obj/machinery/telecomms/processor/RefreshParts() + idle_power_usage = 30 + for(var/obj/item/stock_parts/manipulator/P in component_parts) + idle_power_usage -= (P.rating * 1.5) //Has 2 manipulators + /obj/machinery/telecomms/processor/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from) if(!is_freq_listening(signal)) return diff --git a/code/game/machinery/telecomms/machines/receiver.dm b/code/game/machinery/telecomms/machines/receiver.dm index 4dd3af036c..0e443bad8f 100644 --- a/code/game/machinery/telecomms/machines/receiver.dm +++ b/code/game/machinery/telecomms/machines/receiver.dm @@ -15,6 +15,11 @@ idle_power_usage = 30 circuit = /obj/item/circuitboard/machine/telecomms/receiver +/obj/machinery/telecomms/receiver/RefreshParts() + idle_power_usage = 30 + for(var/obj/item/stock_parts/manipulator/P in component_parts) + idle_power_usage -= (P.rating * 1.5) //Has 2 manipulators + /obj/machinery/telecomms/receiver/receive_signal(datum/signal/subspace/signal) if(!on || !istype(signal) || !check_receive_level(signal) || signal.transmission_method != TRANSMISSION_SUBSPACE) return diff --git a/code/game/machinery/telecomms/machines/relay.dm b/code/game/machinery/telecomms/machines/relay.dm index 65f70a4f23..10328f0788 100644 --- a/code/game/machinery/telecomms/machines/relay.dm +++ b/code/game/machinery/telecomms/machines/relay.dm @@ -19,6 +19,11 @@ var/broadcasting = 1 var/receiving = 1 +/obj/machinery/telecomms/relay/RefreshParts() + idle_power_usage = 30 + for(var/obj/item/stock_parts/manipulator/P in component_parts) + idle_power_usage -= (P.rating * 1.5) //Has 2 manipulators + /obj/machinery/telecomms/relay/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from) // Add our level and send it back var/turf/T = get_turf(src) diff --git a/code/game/machinery/telecomms/machines/server.dm b/code/game/machinery/telecomms/machines/server.dm index 46b16252c5..ad4599b4c3 100644 --- a/code/game/machinery/telecomms/machines/server.dm +++ b/code/game/machinery/telecomms/machines/server.dm @@ -19,6 +19,11 @@ /obj/machinery/telecomms/server/Initialize() . = ..() +/obj/machinery/telecomms/server/RefreshParts() + idle_power_usage = 15 + for(var/obj/item/stock_parts/manipulator/P in component_parts) + idle_power_usage -= (P.rating) //has 2 manipulators + /obj/machinery/telecomms/server/receive_information(datum/signal/subspace/vocal/signal, obj/machinery/telecomms/machine_from) // can't log non-vocal signals if(!istype(signal) || !signal.data["message"] || !is_freq_listening(signal)) diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index ff5ba14810..26220d4d89 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -1,3 +1,111 @@ +//dye registry, add dye colors and their resulting output here if you want the sprite to change instead of just the color. +GLOBAL_LIST_INIT(dye_registry, list( + DYE_REGISTRY_UNDER = list( + DYE_RED = /obj/item/clothing/under/color/red, + DYE_ORANGE = /obj/item/clothing/under/color/orange, + DYE_YELLOW = /obj/item/clothing/under/color/yellow, + DYE_GREEN = /obj/item/clothing/under/color/green, + DYE_BLUE = /obj/item/clothing/under/color/blue, + DYE_PURPLE = /obj/item/clothing/under/color/lightpurple, + DYE_BLACK = /obj/item/clothing/under/color/black, + DYE_WHITE = /obj/item/clothing/under/color/white, + DYE_RAINBOW = /obj/item/clothing/under/color/rainbow, + DYE_MIME = /obj/item/clothing/under/rank/civilian/mime, + DYE_CLOWN = /obj/item/clothing/under/rank/civilian/clown, + DYE_QM = /obj/item/clothing/under/rank/cargo/qm, + DYE_LAW = /obj/item/clothing/under/suit/black, + DYE_CAPTAIN = /obj/item/clothing/under/rank/captain, + DYE_HOP = /obj/item/clothing/under/rank/civilian/head_of_personnel, + DYE_HOS = /obj/item/clothing/under/rank/security/head_of_security, + DYE_CE = /obj/item/clothing/under/rank/engineering/chief_engineer, + DYE_RD = /obj/item/clothing/under/rank/rnd/research_director, + DYE_CMO = /obj/item/clothing/under/rank/medical/chief_medical_officer, + DYE_REDCOAT = /obj/item/clothing/under/costume/redcoat + ), + DYE_REGISTRY_JUMPSKIRT = list( + DYE_RED = /obj/item/clothing/under/color/jumpskirt/red, + DYE_ORANGE = /obj/item/clothing/under/color/jumpskirt/orange, + DYE_YELLOW = /obj/item/clothing/under/color/jumpskirt/yellow, + DYE_GREEN = /obj/item/clothing/under/color/jumpskirt/green, + DYE_BLUE = /obj/item/clothing/under/color/jumpskirt/blue, + DYE_PURPLE = /obj/item/clothing/under/color/jumpskirt/lightpurple, + DYE_BLACK = /obj/item/clothing/under/color/jumpskirt/black, + DYE_WHITE = /obj/item/clothing/under/color/jumpskirt/white, + DYE_RAINBOW = /obj/item/clothing/under/color/jumpskirt/rainbow + ), + DYE_REGISTRY_GLOVES = list( + DYE_RED = /obj/item/clothing/gloves/color/red, + DYE_ORANGE = /obj/item/clothing/gloves/color/orange, + DYE_YELLOW = /obj/item/clothing/gloves/color/yellow, + DYE_GREEN = /obj/item/clothing/gloves/color/green, + DYE_BLUE = /obj/item/clothing/gloves/color/blue, + DYE_PURPLE = /obj/item/clothing/gloves/color/purple, + DYE_BLACK = /obj/item/clothing/gloves/color/black, + DYE_WHITE = /obj/item/clothing/gloves/color/white, + DYE_RAINBOW = /obj/item/clothing/gloves/color/rainbow, + DYE_MIME = /obj/item/clothing/gloves/color/white, + DYE_CLOWN = /obj/item/clothing/gloves/color/rainbow, + DYE_QM = /obj/item/clothing/gloves/color/brown, + DYE_CAPTAIN = /obj/item/clothing/gloves/color/captain, + DYE_HOP = /obj/item/clothing/gloves/color/grey, + DYE_HOS = /obj/item/clothing/gloves/color/black, + DYE_CE = /obj/item/clothing/gloves/color/black, + DYE_RD = /obj/item/clothing/gloves/color/grey, + DYE_CMO = /obj/item/clothing/gloves/color/latex/nitrile, + DYE_REDCOAT = /obj/item/clothing/gloves/color/white + ), + DYE_REGISTRY_SNEAKERS = list( + DYE_RED = /obj/item/clothing/shoes/sneakers/red, + DYE_ORANGE = /obj/item/clothing/shoes/sneakers/orange, + DYE_YELLOW = /obj/item/clothing/shoes/sneakers/yellow, + DYE_GREEN = /obj/item/clothing/shoes/sneakers/green, + DYE_BLUE = /obj/item/clothing/shoes/sneakers/blue, + DYE_PURPLE = /obj/item/clothing/shoes/sneakers/purple, + DYE_BLACK = /obj/item/clothing/shoes/sneakers/black, + DYE_WHITE = /obj/item/clothing/shoes/sneakers/white, + DYE_RAINBOW = /obj/item/clothing/shoes/sneakers/rainbow, + DYE_MIME = /obj/item/clothing/shoes/sneakers/black, + DYE_QM = /obj/item/clothing/shoes/sneakers/brown, + DYE_CAPTAIN = /obj/item/clothing/shoes/sneakers/brown, + DYE_HOP = /obj/item/clothing/shoes/sneakers/brown, + DYE_CE = /obj/item/clothing/shoes/sneakers/brown, + DYE_RD = /obj/item/clothing/shoes/sneakers/brown, + DYE_CMO = /obj/item/clothing/shoes/sneakers/brown + ), + DYE_REGISTRY_FANNYPACK = list( + DYE_RED = /obj/item/storage/belt/fannypack/red, + DYE_ORANGE = /obj/item/storage/belt/fannypack/orange, + DYE_YELLOW = /obj/item/storage/belt/fannypack/yellow, + DYE_GREEN = /obj/item/storage/belt/fannypack/green, + DYE_BLUE = /obj/item/storage/belt/fannypack/blue, + DYE_PURPLE = /obj/item/storage/belt/fannypack/purple, + DYE_BLACK = /obj/item/storage/belt/fannypack/black, + DYE_WHITE = /obj/item/storage/belt/fannypack/white + ), + DYE_REGISTRY_BEDSHEET = list( + DYE_RED = /obj/item/bedsheet/red, + DYE_ORANGE = /obj/item/bedsheet/orange, + DYE_YELLOW = /obj/item/bedsheet/yellow, + DYE_GREEN = /obj/item/bedsheet/green, + DYE_BLUE = /obj/item/bedsheet/blue, + DYE_PURPLE = /obj/item/bedsheet/purple, + DYE_BLACK = /obj/item/bedsheet/black, + DYE_WHITE = /obj/item/bedsheet, + DYE_RAINBOW = /obj/item/bedsheet/rainbow, + DYE_MIME = /obj/item/bedsheet/mime, + DYE_CLOWN = /obj/item/bedsheet/clown, + DYE_QM = /obj/item/bedsheet/qm, + DYE_LAW = /obj/item/bedsheet/black, + DYE_CAPTAIN = /obj/item/bedsheet/captain, + DYE_HOP = /obj/item/bedsheet/hop, + DYE_HOS = /obj/item/bedsheet/hos, + DYE_CE = /obj/item/bedsheet/ce, + DYE_RD = /obj/item/bedsheet/rd, + DYE_CMO = /obj/item/bedsheet/cmo, + DYE_COSMIC = /obj/item/bedsheet/cosmos + ) +)) + /obj/machinery/washing_machine name = "washing machine" desc = "Gets rid of those pesky bloodstains, or your money back!" @@ -13,27 +121,22 @@ /obj/machinery/washing_machine/examine(mob/user) . = ..() - . += "Alt-click it to start a wash cycle." + if(!busy) + . += "Alt-click it to start a wash cycle." /obj/machinery/washing_machine/AltClick(mob/user) . = ..() if(!user.canUseTopic(src)) return - if(busy) return - if(state_open) to_chat(user, "Close the door first") return TRUE - if(bloody_mess) to_chat(user, "[src] must be cleaned up first.") return TRUE - if(has_corgi) - bloody_mess = 1 - busy = TRUE update_icon() addtimer(CALLBACK(src, .proc/wash_cycle), 200) @@ -76,6 +179,28 @@ color_source = null update_icon() +/obj/item/proc/dye_item(dye_color) + if(undyeable) + return FALSE + if(dying_key) + if(!GLOB.dye_registry[dying_key]) + log_runtime("Item just tried to be dyed with an invalid registry key: [dying_key]") + return FALSE + var/obj/item/target_type = GLOB.dye_registry[dying_key][dye_color] + if(target_type) + icon = initial(target_type.icon) + icon_state = initial(target_type.icon_state) + lefthand_file = initial(target_type.lefthand_file) + righthand_file = initial(target_type.righthand_file) + item_state = initial(target_type.item_state) + mob_overlay_icon = initial(target_type.mob_overlay_icon) + inhand_x_dimension = initial(target_type.inhand_x_dimension) + inhand_y_dimension = initial(target_type.inhand_y_dimension) + name = initial(target_type.name) + desc = "[initial(target_type.desc)] The colors look a little dodgy." + return target_type //successfully "appearance copy" dyed something; returns the target type as a hacky way of extending + add_atom_colour(dye_color, FIXED_COLOUR_PRIORITY) + return FALSE //what happens to this object when washed inside a washing machine /atom/movable/proc/machine_wash(obj/machinery/washing_machine/WM) @@ -89,105 +214,27 @@ new /obj/item/reagent_containers/food/snacks/meat/slab/corgi(loc) qdel(src) -/obj/item/paper/machine_wash(obj/machinery/washing_machine/WM) - if(WM.color_source) - if(istype(WM.color_source, /obj/item/toy/crayon)) - var/obj/item/toy/crayon/CR = WM.color_source - add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY) - -/obj/item/reagents_containers/rag/towel/machine_wash(obj/machinery/washing_machine/WM) - if(WM.color_source) - if(istype(WM.color_source, /obj/item/toy/crayon)) - var/obj/item/toy/crayon/CR = WM.color_source - add_atom_colour(CR.paint_color, WASHABLE_COLOUR_PRIORITY) - /mob/living/simple_animal/pet/dog/corgi/machine_wash(obj/machinery/washing_machine/WM) gib() -/obj/item/clothing/under/color/machine_wash(obj/machinery/washing_machine/WM) - jumpsuit_wash(WM) - -/obj/item/clothing/under/rank/machine_wash(obj/machinery/washing_machine/WM) - jumpsuit_wash(WM) - -/obj/item/clothing/under/proc/jumpsuit_wash(obj/machinery/washing_machine/WM) +/obj/item/machine_wash(obj/machinery/washing_machine/WM) if(WM.color_source) - var/wash_color = WM.color_source.item_color - var/obj/item/clothing/under/U - for(var/T in typesof(/obj/item/clothing/under/color)) - var/obj/item/clothing/under/color/J = T - if(wash_color == initial(J.item_color)) - U = J - break - if(!U) - for(var/T in typesof(/obj/item/clothing/under/rank)) - var/obj/item/clothing/under/rank/R = T - if(wash_color == initial(R.item_color)) - U = R - break - if(U) - item_state = initial(U.item_state) - icon_state = initial(U.icon_state) - item_color = wash_color - name = initial(U.name) - desc = "The colors are a bit dodgy." - can_adjust = initial(U.can_adjust) - if(!can_adjust && adjusted) //we deadjust the uniform if it's now unadjustable - toggle_jumpsuit_adjust() + dye_item(WM.color_source.dye_color) -/obj/item/clothing/gloves/color/machine_wash(obj/machinery/washing_machine/WM) - if(WM.color_source) - var/wash_color = WM.color_source.item_color - for(var/T in typesof(/obj/item/clothing/gloves/color)) - var/obj/item/clothing/gloves/color/G = T - if(wash_color == initial(G.item_color)) - item_state = initial(G.item_state) - icon_state = initial(G.icon_state) - item_color = wash_color - name = initial(G.name) - desc = "The colors are a bit dodgy." - break +/obj/item/clothing/under/dye_item(dye_color, dye_key) + . = ..() + if(.) + var/obj/item/clothing/under/U = . + can_adjust = initial(U.can_adjust) + if(!can_adjust && adjusted) //we deadjust the uniform if it's now unadjustable + toggle_jumpsuit_adjust() /obj/item/clothing/shoes/sneakers/machine_wash(obj/machinery/washing_machine/WM) if(chained) chained = 0 slowdown = SHOES_SLOWDOWN new /obj/item/restraints/handcuffs(loc) - if(WM.color_source) - var/wash_color = WM.color_source.item_color - for(var/T in typesof(/obj/item/clothing/shoes/sneakers)) - var/obj/item/clothing/shoes/sneakers/S = T - if(wash_color == initial(S.item_color)) - icon_state = initial(S.icon_state) - item_color = wash_color - name = initial(S.name) - desc = "The colors are a bit dodgy." - break - -/obj/item/bedsheet/machine_wash(obj/machinery/washing_machine/WM) - if(WM.color_source) - var/wash_color = WM.color_source.item_color - for(var/T in typesof(/obj/item/bedsheet)) - var/obj/item/bedsheet/B = T - if(wash_color == initial(B.item_color)) - icon_state = initial(B.icon_state) - item_color = wash_color - name = initial(B.name) - desc = "The colors are a bit dodgy." - break - -/obj/item/clothing/head/soft/machine_wash(obj/machinery/washing_machine/WM) - if(WM.color_source) - var/wash_color = WM.color_source.item_color - for(var/T in typesof(/obj/item/clothing/head/soft)) - var/obj/item/clothing/head/soft/H = T - if(wash_color == initial(H.item_color)) - icon_state = initial(H.icon_state) - item_color = wash_color - name = initial(H.name) - desc = "The colors are a bit dodgy." - break - + ..() /obj/machinery/washing_machine/relaymove(mob/user) container_resist(user) @@ -223,27 +270,27 @@ if(istype(W, /obj/item/clothing/head/mob_holder)) to_chat(user, "It's too unwieldly to put in this way.") - return 1 + return TRUE else if(user.a_intent != INTENT_HARM) if (!state_open) to_chat(user, "Open the door first!") - return 1 + return TRUE if(bloody_mess) to_chat(user, "[src] must be cleaned up first.") - return 1 + return TRUE if(contents.len >= max_wash_capacity) to_chat(user, "The washing machine is full!") - return 1 + return TRUE if(!user.transferItemToLoc(W, src)) to_chat(user, "\The [W] is stuck to your hand, you cannot put it in the washing machine!") - return 1 + return TRUE - if(istype(W, /obj/item/toy/crayon) || istype(W, /obj/item/stamp)) + if(W.dye_color) color_source = W update_icon() diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index bf053432a5..8a7bf65f84 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -2,6 +2,7 @@ icon = 'icons/effects/landmarks_static.dmi' icon_state = "random_loot" layer = OBJ_LAYER + var/spawn_on_turf = TRUE var/lootcount = 1 //how many items will be spawned var/lootdoubles = TRUE //if the same item can be spawned twice var/list/loot //a list of possible items to spawn e.g. list(/obj/item, /obj/structure, /obj/effect) @@ -10,7 +11,7 @@ /obj/effect/spawner/lootdrop/Initialize(mapload) ..() if(loot && loot.len) - var/turf/T = get_turf(src) + var/atom/A = spawn_on_turf ? get_turf(src) : loc var/loot_spawned = 0 while((lootcount-loot_spawned) && loot.len) var/lootspawn = pickweight(loot) @@ -18,7 +19,7 @@ loot.Remove(lootspawn) if(lootspawn) - var/atom/movable/spawned_loot = new lootspawn(T) + var/atom/movable/spawned_loot = new lootspawn(A) if (!fan_out_items) if (pixel_x != 0) spawned_loot.pixel_x = pixel_x @@ -448,6 +449,7 @@ /obj/effect/spawner/lootdrop/low_loot_toilet name = "random low toilet spawner" lootcount = 1 + spawn_on_turf = FALSE //Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that //This is ment for "low" loot that anyone could fine in a toilet, for better gear use high loot toilet loot = list("" = 30, @@ -457,41 +459,42 @@ /obj/item/clothing/glasses/sunglasses/blindfold = 4, /obj/item/clothing/glasses/sunglasses = 1, /obj/item/toy/plush/random = 5, - /obj/effect/spawner/lootdrop/gloves = 5, - /obj/effect/spawner/lootdrop/glowstick = 5, - /obj/effect/spawner/lootdrop/coin = 3, - /obj/effect/spawner/lootdrop/cig_packs = 10, - /obj/effect/spawner/lootdrop/cigars_cases = 2, - /obj/effect/spawner/lootdrop/space_cash = 5, + /obj/effect/spawner/lootdrop/gloves/no_turf = 5, + /obj/effect/spawner/lootdrop/glowstick/no_turf = 5, + /obj/effect/spawner/lootdrop/coin/no_turf = 3, + /obj/effect/spawner/lootdrop/cig_packs/no_turf = 10, + /obj/effect/spawner/lootdrop/cigars_cases/no_turf = 2, + /obj/effect/spawner/lootdrop/space_cash/no_turf = 5, /obj/item/reagent_containers/food/snacks/grown/cannabis = 5, /obj/item/storage/pill_bottle/dice = 5, /obj/item/toy/cards/deck = 5, - /obj/effect/spawner/lootdrop/druggie_pill = 5 + /obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5 ) /obj/effect/spawner/lootdrop/prison_loot_toilet name = "random prison toilet spawner" lootcount = 1 + spawn_on_turf = FALSE //Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that //This is ment for "prison" loot that is rather rare and ment for "prisoners if they get a crowbar to fine, or sec. loot = list("" = 10, /obj/item/lighter = 5, /obj/item/poster/random_contraband = 5, /obj/item/clothing/glasses/sunglasses = 5, - /obj/effect/spawner/lootdrop/coin = 5, - /obj/effect/spawner/lootdrop/cig_packs = 10, - /obj/effect/spawner/lootdrop/cigars_cases = 5, + /obj/effect/spawner/lootdrop/coin/no_turf = 5, + /obj/effect/spawner/lootdrop/cig_packs/no_turf = 10, + /obj/effect/spawner/lootdrop/cigars_cases/no_turf = 5, /obj/item/reagent_containers/food/snacks/grown/cannabis = 5, /obj/item/storage/pill_bottle/dice = 5, /obj/item/toy/cards/deck = 5, - /obj/effect/spawner/lootdrop/druggie_pill = 5, + /obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5, /obj/item/kitchen/knife = 5, /obj/item/screwdriver = 5, - /obj/item/crowbar/red = 0.5, //Dont you need a crowbar to open this? + /obj/item/crowbar/red = 1, //Dont you need a crowbar to open this? /obj/item/stack/medical/bruise_pack = 3, /obj/item/reagent_containers/food/drinks/bottle/vodka = 2, /obj/item/radio = 5, - /obj/item/flashlight = 4.5, + /obj/item/flashlight = 4, /obj/item/clothing/mask/breath = 2, /obj/item/tank/internals/emergency_oxygen = 3, /obj/item/storage/box/mre/menu4/safe = 3, @@ -501,13 +504,14 @@ /obj/effect/spawner/lootdrop/high_loot_toilet name = "random high toilet spawner" lootcount = 1 + spawn_on_turf = FALSE //Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that //The items inside are always going to be something usefull, illegal and likely traitorous. loot = list( /obj/item/clothing/glasses/sunglasses = 5, - /obj/effect/spawner/lootdrop/coin = 5, - /obj/effect/spawner/lootdrop/space_cash = 5, - /obj/effect/spawner/lootdrop/druggie_pill = 5, + /obj/effect/spawner/lootdrop/coin/no_turf = 5, + /obj/effect/spawner/lootdrop/space_cash/no_turf = 5, + /obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5, /obj/item/storage/fancy/cigarettes/cigpack_syndicate = 5, /obj/item/suppressor = 5, /obj/item/toy/cards/deck/syndicate = 5, @@ -607,3 +611,30 @@ /obj/item/clothing/mask/breath = 5, /obj/item/clothing/mask/breath/medical = 1 ) + +/obj/effect/spawner/lootdrop/breathing_tanks/no_turf + spawn_on_turf = FALSE + +/obj/effect/spawner/lootdrop/breathing_masks/no_turf + spawn_on_turf = FALSE + +/obj/effect/spawner/lootdrop/coin/no_turf + spawn_on_turf = FALSE + +/obj/effect/spawner/lootdrop/space_cash/no_turf + spawn_on_turf = FALSE + +/obj/effect/spawner/lootdrop/druggie_pill/no_turf + spawn_on_turf = FALSE + +/obj/effect/spawner/lootdrop/gloves/no_turf + spawn_on_turf = FALSE + +/obj/effect/spawner/lootdrop/cig_packs/no_turf + spawn_on_turf = FALSE + +/obj/effect/spawner/lootdrop/cigars_cases/no_turf + spawn_on_turf = FALSE + +/obj/effect/spawner/lootdrop/glowstick/no_turf + spawn_on_turf = FALSE diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 222b82d134..22769b05b1 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -8,9 +8,20 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) name = "item" icon = 'icons/obj/items_and_weapons.dmi' blocks_emissive = EMISSIVE_BLOCK_GENERIC + + ///icon state name for inhand overlays var/item_state = null + ///Icon file for left hand inhand overlays var/lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + ///Icon file for right inhand overlays var/righthand_file = 'icons/mob/inhands/items_righthand.dmi' + + ///Icon file for mob worn overlays. + ///no var for state because it should *always* be the same as icon_state + var/icon/mob_overlay_icon + //Forced mob worn layer instead of the standard preferred ssize. + var/alternate_worn_layer + var/list/alternate_screams = list() //REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE //Dimensions of the icon file used when this item is worn, eg: hats.dmi @@ -22,10 +33,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/inhand_x_dimension = 32 var/inhand_y_dimension = 32 - //Not on /clothing because for some reason any /obj/item can technically be "worn" with enough fuckery. - var/icon/alternate_worn_icon = null//If this is set, update_icons() will find on mob (WORN, NOT INHANDS) states in this file instead, primary use: badminnery/events - var/alternate_worn_layer = null//If this is set, update_icons() will force the on mob state (WORN, NOT INHANDS) onto this layer, instead of it's default - max_integrity = 200 obj_flags = NONE @@ -34,7 +41,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/hitsound = null var/usesound = null var/throwhitsound = null + + /// Weight class for how much storage capacity it uses and how big it physically is meaning storages can't hold it if their maximum weight class isn't as high as it. var/w_class = WEIGHT_CLASS_NORMAL + /// Volume override for the item, otherwise automatically calculated from w_class. + var/w_volume /// The amount of stamina it takes to swing an item in a normal melee attack do not lie to me and say it's for realism because it ain't. If null it will autocalculate from w_class. var/total_mass //Total mass in arbitrary pound-like values. If there's no balance reasons for an item to have otherwise, this var should be the item's weight in pounds. @@ -61,8 +72,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) //Citadel Edit for digitigrade stuff var/mutantrace_variation = NONE //Are there special sprites for specific situations? Don't use this unless you need to. - var/item_color = null //this needs deprecating, soonish - var/body_parts_covered = 0 //see setup.dm for appropriate bit flags var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets) var/permeability_coefficient = 1 // for chemicals/diseases @@ -93,8 +102,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/tool_behaviour = NONE var/toolspeed = 1 - var/block_chance = 0 - var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom var/reach = 1 //In tiles, how far this weapon can reach; 1 for adjacent, which is default //The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot. @@ -111,6 +118,13 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/trigger_guard = TRIGGER_GUARD_NONE + ///Used as the dye color source in the washing machine only (at the moment). Can be a hex color or a key corresponding to a registry entry, see washing_machine.dm + var/dye_color + ///Whether the item is unaffected by standard dying. + var/undyeable = FALSE + ///What dye registry should be looked at when dying this item; see washing_machine.dm + var/dying_key + //Grinder vars var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder! @@ -365,13 +379,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) // afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency -/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args) - if(prob(final_block_chance)) - owner.visible_message("[owner] blocks [attack_text] with [src]!") - return 1 - return 0 - /obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language) return ITALICS | REDUCE_RANGE @@ -431,6 +438,13 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) item_flags |= IN_INVENTORY user.update_equipment_speed_mods() +//Overlays for the worn overlay so you can overlay while you overlay +//eg: ammo counters, primed grenade flashing, etc. +//"icon_file" is used automatically for inhands etc. to make sure it gets the right inhand file +/obj/item/proc/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = list() + SEND_SIGNAL(src, COMSIG_ITEM_WORN_OVERLAYS, isinhands, icon_file, used_state, style_flags, .) + //sometimes we only want to grant the item's action if it's equipped in a specific slot. /obj/item/proc/item_action_slot_check(slot, mob/user, datum/action/A) if(slot == SLOT_IN_BACKPACK || slot == SLOT_LEGCUFFED) //these aren't true slots, so avoid granting actions there @@ -464,9 +478,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) /obj/item/proc/ui_action_click(mob/user, actiontype) attack_self(user) -/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit - return 0 - /obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user) if(HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm [M]!") @@ -857,6 +868,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) return return ..() +/// Get an item's volume that it uses when being stored. +/obj/item/proc/get_w_volume() + // if w_volume is 0 you fucked up anyways lol + return w_volume || AUTO_SCALE_VOLUME(w_class) + /obj/item/proc/embedded(mob/living/carbon/human/embedded_mob) return diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm index 72e6ccbbe2..f3ea461c74 100644 --- a/code/game/objects/items/RCL.dm +++ b/code/game/objects/items/RCL.dm @@ -113,7 +113,7 @@ cable_overlay.color = GLOB.cable_colors[colors[current_color_index]] . += cable_overlay -/obj/item/twohanded/rcl/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/twohanded/rcl/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands || !(loaded?.amount)) return @@ -201,7 +201,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) return //If we've run out, display message and exit else last = null - loaded.item_color = colors[current_color_index] + loaded.color = colors[current_color_index] last = loaded.place_turf(get_turf(src), user, turn(user.dir, 180)) is_empty(user) //If we've run out, display message update_icon() @@ -223,7 +223,6 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) continue if(C.d1 == 0) return C - break return @@ -277,7 +276,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) if(T.intact || !T.can_have_cabling()) return - loaded.item_color = colors[current_color_index] + loaded.color = colors[current_color_index] var/obj/structure/cable/linkingCable = findLinkingCable(user) if(linkingCable) @@ -299,7 +298,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) var/cwname = colors[current_color_index] to_chat(user, "Color changed to [cwname]!") if(loaded) - loaded.item_color= colors[current_color_index] + loaded.color = colors[current_color_index] update_icon() if(wiring_gui_menu) wiringGuiUpdate(user) diff --git a/code/game/objects/items/balls.dm b/code/game/objects/items/balls.dm index c24f58208b..2e5a385ead 100644 --- a/code/game/objects/items/balls.dm +++ b/code/game/objects/items/balls.dm @@ -15,7 +15,7 @@ lefthand_file = 'modular_citadel/icons/mob/inhands/balls_left.dmi' righthand_file = 'modular_citadel/icons/mob/inhands/balls_right.dmi' item_state = "tennis_classic" - alternate_worn_icon = 'modular_citadel/icons/mob/mouthball.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/mouthball.dmi' slot_flags = ITEM_SLOT_HEAD | ITEM_SLOT_NECK | ITEM_SLOT_EARS //Fluff item, put it wherever you want! throw_range = 14 w_class = WEIGHT_CLASS_SMALL diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index e93bfb9976..dbc66b1899 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -38,7 +38,6 @@ /obj/item/bodybag/bluespace name = "bluespace body bag" desc = "A folded bluespace body bag designed for the storage and transportation of cadavers." - icon = 'icons/obj/bodybag.dmi' icon_state = "bluebodybag_folded" unfoldedbag_path = /obj/structure/closet/body_bag/bluespace w_class = WEIGHT_CLASS_SMALL @@ -81,3 +80,13 @@ return loc.visible_message("[user] suddenly appears in front of [loc]!", "[user] breaks free of [src]!") qdel(src) + +// Containment bodybag + +/obj/item/bodybag/containment + name = "radiation containment body bag" + desc = "A folded heavy body bag designed for the storage and transportation of heavily irradiated cadavers." + icon_state = "radbodybag_folded" + unfoldedbag_path = /obj/structure/closet/body_bag/containment + w_class = WEIGHT_CLASS_NORMAL + rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 5b7c70b1b6..2303278f5c 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -706,11 +706,11 @@ CIGARETTE PACKETS ARE IN FANCY.DM name = "\improper E-Cigarette" desc = "A classy and highly sophisticated electronic cigarette, for classy and dignified gentlemen. A warning label reads \"Warning: Do not fill with flammable materials.\""//<<< i'd vape to that. icon = 'icons/obj/clothing/masks.dmi' - icon_state = null - item_state = null + icon_state = "black_vape" + item_state = "black_vape" w_class = WEIGHT_CLASS_TINY var/chem_volume = 100 - var/vapetime = FALSE //this so it won't puff out clouds every tick + var/vapetime = FALSE //this so it won't puff out clouds every tick var/screw = FALSE // kinky var/super = FALSE //for the fattest vapes dude. @@ -723,11 +723,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM . = ..() create_reagents(chem_volume, NO_REACT, NO_REAGENTS_VALUE) // so it doesn't react until you light it reagents.add_reagent(/datum/reagent/drug/nicotine, 50) - if(!icon_state) - if(!param_color) - param_color = pick("red","blue","black","white","green","purple","yellow","orange") - icon_state = "[param_color]_vape" - item_state = "[param_color]_vape" + if(!param_color) + param_color = pick("red","blue","black","white","green","purple","yellow","orange") + icon_state = "[param_color]_vape" + item_state = "[param_color]_vape" /obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params) if(O.tool_behaviour == TOOL_SCREWDRIVER) @@ -1067,4 +1066,4 @@ CIGARETTE PACKETS ARE IN FANCY.DM name = "coconut bong" icon_off = "coconut_bong" icon_on = "coconut_bong_lit" - desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo." \ No newline at end of file + desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo." diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index f5b13d4e3e..09c045497c 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -26,7 +26,7 @@ var/icon_uncapped var/use_overlays = FALSE - item_color = "red" + var/crayon_color = "red" w_class = WEIGHT_CLASS_TINY attack_verb = list("attacked", "coloured") grind_results = list() @@ -83,7 +83,9 @@ . = ..() // Makes crayons identifiable in things like grinders if(name == "crayon") - name = "[item_color] crayon" + name = "[crayon_color] crayon" + + dye_color = crayon_color drawtype = pick(all_drawables) @@ -484,65 +486,75 @@ /obj/item/toy/crayon/red icon_state = "crayonred" paint_color = "#DA0000" - item_color = "red" + crayon_color = "red" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/red = 1) + dye_color = DYE_RED /obj/item/toy/crayon/orange icon_state = "crayonorange" paint_color = "#FF9300" - item_color = "orange" + crayon_color = "orange" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/orange = 1) + dye_color = DYE_ORANGE /obj/item/toy/crayon/yellow icon_state = "crayonyellow" paint_color = "#FFF200" - item_color = "yellow" + crayon_color = "yellow" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/yellow = 1) + dye_color = DYE_YELLOW /obj/item/toy/crayon/green icon_state = "crayongreen" paint_color = "#A8E61D" - item_color = "green" + crayon_color = "green" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/green = 1) + dye_color = DYE_GREEN /obj/item/toy/crayon/blue icon_state = "crayonblue" paint_color = "#00B7EF" - item_color = "blue" + crayon_color = "blue" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/blue = 1) + dye_color = DYE_BLUE /obj/item/toy/crayon/purple icon_state = "crayonpurple" paint_color = "#DA00FF" - item_color = "purple" + crayon_color = "purple" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/purple = 1) + dye_color = DYE_PURPLE /obj/item/toy/crayon/black icon_state = "crayonblack" paint_color = "#1C1C1C" //Not completely black because total black looks bad. So Mostly Black. - item_color = "black" + crayon_color = "black" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/black = 1) + dye_color = DYE_BLACK /obj/item/toy/crayon/white icon_state = "crayonwhite" paint_color = "#FFFFFF" - item_color = "white" + crayon_color = "white" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/white = 1) + dye_color = DYE_WHITE /obj/item/toy/crayon/mime icon_state = "crayonmime" desc = "A very sad-looking crayon." paint_color = "#FFFFFF" - item_color = "mime" + crayon_color = "mime" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent/crayonpowder/invisible = 1) charges = -1 + dye_color = DYE_MIME /obj/item/toy/crayon/rainbow icon_state = "crayonrainbow" paint_color = "#FFF000" - item_color = "rainbow" + crayon_color = "rainbow" reagent_contents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent = 1) drawtype = RANDOM_ANY // just the default starter. + dye_color = DYE_RAINBOW charges = -1 @@ -580,12 +592,12 @@ /obj/item/storage/crayons/update_overlays() . = ..() for(var/obj/item/toy/crayon/crayon in contents) - add_overlay(mutable_appearance('icons/obj/crayons.dmi', crayon.item_color)) + add_overlay(mutable_appearance('icons/obj/crayons.dmi', crayon.crayon_color)) /obj/item/storage/crayons/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/toy/crayon)) var/obj/item/toy/crayon/C = W - switch(C.item_color) + switch(C.crayon_color) if("mime") to_chat(usr, "This crayon is too sad to be contained in this box.") return diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 157cd451d4..2dabcca29f 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -807,9 +807,9 @@ GLOBAL_LIST_EMPTY(PDAs) // If it didn't reach, note that fact if (!signal.data["done"]) to_chat(user, "ERROR: Server isn't responding.") - return if (!silent) playsound(src, 'sound/machines/terminal_error.ogg', 15, 1) + return var/target_text = signal.format_target() if(allow_emojis) @@ -998,9 +998,9 @@ GLOBAL_LIST_EMPTY(PDAs) var/obj/item/card/id/idcard = C if(!idcard.registered_name) to_chat(user, "\The [src] rejects the ID!") - return if (!silent) playsound(src, 'sound/machines/terminal_error.ogg', 15, 1) + return if(!owner) owner = idcard.registered_name diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 1006fe9146..6eae9f127a 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -692,14 +692,14 @@ Code: return GLOB.news_network.SubmitArticle(message,host_pda.owner,current_channel) host_pda.Topic(null,list("choice"=num2text(host_pda.mode))) - return playsound(src, 'sound/machines/terminal_select.ogg', 50, 1) + return if("Newscaster Switch Channel") current_channel = host_pda.msg_input() host_pda.Topic(null,list("choice"=num2text(host_pda.mode))) - return playsound(src, 'sound/machines/terminal_select.ogg', 50, 1) + return //emoji previews if(href_list["emoji"]) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index a3cfdb9177..9c94348fc2 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -18,7 +18,6 @@ var/recharge_locked = FALSE var/obj/item/stock_parts/micro_laser/diode //used for upgrading! - /obj/item/laser_pointer/red pointer_icon_state = "red_laser" /obj/item/laser_pointer/green @@ -28,6 +27,9 @@ /obj/item/laser_pointer/purple pointer_icon_state = "purple_laser" +/obj/item/laser_pointer/blue/handmade + diode = null + /obj/item/laser_pointer/New() ..() diode = new(src) diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm index 914f2a149a..1eee083c80 100644 --- a/code/game/objects/items/devices/radio/electropack.dm +++ b/code/game/objects/items/devices/radio/electropack.dm @@ -149,7 +149,7 @@ Code: name = "shock collar" desc = "A reinforced metal collar. It seems to have some form of wiring near the front. Strange.." icon = 'modular_citadel/icons/obj/clothing/cit_neck.dmi' - alternate_worn_icon = 'modular_citadel/icons/mob/citadel/neck.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/citadel/neck.dmi' icon_state = "shockcollar" item_state = "shockcollar" body_parts_covered = NECK diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 634ca4d637..b6cab8b438 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -275,10 +275,8 @@ SLIME SCANNER //LIVER else if(istype(O, /obj/item/organ/liver)) var/obj/item/organ/liver/L = O - if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated + if(L.organ_flags & ORGAN_FAILING && H.stat != DEAD) //might be depreciated temp_message += "Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!" - if(L.swelling > 20) - temp_message += " Subject is suffering from an enlarged liver." //i.e. shrink their liver or give them a transplant. //HEART else if(ishuman(M) && (istype(O, /obj/item/organ/heart))) diff --git a/code/game/objects/items/documents.dm b/code/game/objects/items/documents.dm index ea24e77832..1172b50377 100644 --- a/code/game/objects/items/documents.dm +++ b/code/game/objects/items/documents.dm @@ -51,8 +51,8 @@ to_chat(user, "You have already forged a seal on [src]!") else var/obj/item/toy/crayon/C = O - name = "[C.item_color] secret documents" - icon_state = "docs_[C.item_color]" - forgedseal = C.item_color - to_chat(user, "You forge the official seal with a [C.item_color] crayon. No one will notice... right?") - update_icon() \ No newline at end of file + name = "[C.crayon_color] secret documents" + icon_state = "docs_[C.crayon_color]" + forgedseal = C.crayon_color + to_chat(user, "You forge the official seal with a [C.crayon_color] crayon. No one will notice... right?") + update_icon() diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index b0882b6e5d..e2140bd0fd 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -234,15 +234,16 @@ /obj/item/flamethrower/full/tank create_with_tank = TRUE -/obj/item/flamethrower/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - var/obj/item/projectile/P = hitby - if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(15)) - owner.visible_message("\The [attack_text] hits the fueltank on [owner]'s [name], rupturing it! What a shot!") - var/target_turf = get_turf(owner) - igniter.ignite_turf(src,target_turf, release_amount = 100) - qdel(ptank) - return 1 //It hit the flamethrower, not them - +/obj/item/flamethrower/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(attack_type & ATTACK_TYPE_PROJECTILE) + var/obj/item/projectile/P = object + if(istype(P) && (P.damage_type != STAMINA) && damage && !P.nodamage && prob(15)) + owner.visible_message("\The [attack_text] hits the fueltank on [owner]'s [name], rupturing it! What a shot!") + var/target_turf = get_turf(owner) + igniter.ignite_turf(src,target_turf, release_amount = 100) + qdel(ptank) + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return ..() /obj/item/assembly/igniter/proc/flamethrower_process(turf/open/location) location.hotspot_expose(700,2) diff --git a/code/game/objects/items/grenades/grenade.dm b/code/game/objects/items/grenades/grenade.dm index 77b4b33a8c..8a41ee4601 100644 --- a/code/game/objects/items/grenades/grenade.dm +++ b/code/game/objects/items/grenades/grenade.dm @@ -115,12 +115,14 @@ /obj/item/grenade/attack_paw(mob/user) return attack_hand(user) -/obj/item/grenade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - var/obj/item/projectile/P = hitby - if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(15)) - owner.visible_message("[attack_text] hits [owner]'s [src], setting it off! What a shot!") - prime() - return TRUE //It hit the grenade, not them +/obj/item/grenade/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(attack_type & ATTACK_TYPE_PROJECTILE) + var/obj/item/projectile/P = object + if(damage && !P.nodamage && (P.damage_type != STAMINA) && prob(15)) + owner.visible_message("[attack_text] hits [owner]'s [src], setting it off! What a shot!") + prime() + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return ..() /obj/item/proc/grenade_prime_react(obj/item/grenade/nade) return diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index a12847ccf7..22c9bdc451 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -113,7 +113,7 @@ desc = "Looks like some cables tied together. Could be used to tie something up." icon_state = "cuff" item_state = "coil" - color = "red" + color = "#ff0000" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' custom_materials = list(/datum/material/iron=150, /datum/material/glass=75) @@ -132,35 +132,28 @@ to_chat(user, "You unwind the cable restraints back into coil") /obj/item/restraints/handcuffs/cable/red - item_color = "red" color = "#ff0000" /obj/item/restraints/handcuffs/cable/yellow - item_color = "yellow" color = "#ffff00" /obj/item/restraints/handcuffs/cable/blue - item_color = "blue" color = "#1919c8" /obj/item/restraints/handcuffs/cable/green - item_color = "green" color = "#00aa00" /obj/item/restraints/handcuffs/cable/pink - item_color = "pink" color = "#ff3ccd" /obj/item/restraints/handcuffs/cable/orange - item_color = "orange" color = "#ff8000" /obj/item/restraints/handcuffs/cable/cyan - item_color = "cyan" color = "#00ffff" /obj/item/restraints/handcuffs/cable/white - item_color = "white" + color = null /obj/item/restraints/handcuffs/cable/random @@ -209,7 +202,7 @@ custom_materials = null breakouttime = 450 //Deciseconds = 45s trashtype = /obj/item/restraints/handcuffs/cable/zipties/used - item_color = "white" + color = null /obj/item/restraints/handcuffs/cable/zipties/used desc = "A pair of broken zipties." diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index b8f15ec295..ac60a322d8 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -122,7 +122,7 @@ /obj/item/clothing/head/helmet/chaplain/cage name = "cage" desc = "A cage that restrains the will of the self, allowing one to see the profane world for what it is." - alternate_worn_icon = 'icons/mob/large-worn-icons/64x64/head.dmi' + mob_overlay_icon = 'icons/mob/large-worn-icons/64x64/head.dmi' icon_state = "cage" item_state = "cage" worn_x_dimension = 64 @@ -303,8 +303,8 @@ block_chance = 50 var/shield_icon = "shield-red" -/obj/item/nullrod/staff/worn_overlays(isinhands, icon_file, style_flags = NONE) - . = list() +/obj/item/nullrod/staff/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) + . = ..() if(isinhands) . += mutable_appearance('icons/effects/effects.dmi', shield_icon, MOB_LAYER + 0.01) @@ -328,9 +328,9 @@ hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") -/obj/item/nullrod/claymore/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(attack_type == PROJECTILE_ATTACK) - final_block_chance = 0 //Don't bring a sword to a gunfight +/obj/item/nullrod/claymore/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(attack_type & ATTACK_TYPE_PROJECTILE) // Don't bring a sword to a gunfight + return NONE return ..() /obj/item/nullrod/claymore/darkblade diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index c1983b6b8c..cc2ae3631e 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -5,7 +5,7 @@ actions_types = list(/datum/action/item_action/hands_free/activate) var/activated = TRUE //1 for implant types that can be activated, 0 for ones that are "always on" like mindshield implants var/mob/living/imp_in = null - item_color = "b" + var/implant_color = "b" var/allow_multiple = FALSE var/uses = -1 item_flags = DROPDEL diff --git a/code/game/objects/items/implants/implant_freedom.dm b/code/game/objects/items/implants/implant_freedom.dm index f3e66d2c08..280fbb7cd3 100644 --- a/code/game/objects/items/implants/implant_freedom.dm +++ b/code/game/objects/items/implants/implant_freedom.dm @@ -2,7 +2,7 @@ name = "freedom implant" desc = "Use this to escape from those evil Red Shirts." icon_state = "freedom" - item_color = "r" + implant_color = "r" uses = 4 diff --git a/code/game/objects/items/implants/implant_storage.dm b/code/game/objects/items/implants/implant_storage.dm index 1dfc0b4580..4dc0263fa7 100644 --- a/code/game/objects/items/implants/implant_storage.dm +++ b/code/game/objects/items/implants/implant_storage.dm @@ -2,7 +2,7 @@ name = "storage implant" desc = "Stores up to two big items in a bluespace pocket." icon_state = "storage" - item_color = "r" + implant_color = "r" var/max_slot_stacking = 4 var/obj/item/storage/bluespace_pocket/pocket diff --git a/code/game/objects/items/implants/implantcase.dm b/code/game/objects/items/implants/implantcase.dm index 481f1a4181..8573324b56 100644 --- a/code/game/objects/items/implants/implantcase.dm +++ b/code/game/objects/items/implants/implantcase.dm @@ -15,7 +15,7 @@ /obj/item/implantcase/update_icon_state() if(imp) - icon_state = "implantcase-[imp.item_color]" + icon_state = "implantcase-[imp.implant_color]" else icon_state = "implantcase-0" diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index aba07c9120..e4cfeab20f 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -5,12 +5,15 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) resistance_flags = FIRE_PROOF var/brightness_on = 3 + var/sword_color total_mass = 0.4 //Survival flashlights typically weigh around 5 ounces. /obj/item/melee/transforming/energy/Initialize() . = ..() total_mass_on = (total_mass_on ? total_mass_on : (w_class_on * 0.75)) if(active) + if(sword_color) + icon_state = "sword[sword_color]" set_light(brightness_on) START_PROCESSING(SSobj, src) @@ -37,8 +40,8 @@ . = ..() if(.) if(active) - if(item_color) - icon_state = "sword[item_color]" + if(sword_color) + icon_state = "sword[sword_color]" START_PROCESSING(SSobj, src) set_light(brightness_on) else @@ -103,23 +106,32 @@ embedding = list("embed_chance" = 75, "embedded_impact_pain_multiplier" = 10) armour_penetration = 35 block_chance = 50 + var/list/possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER) + +/obj/item/melee/transforming/energy/sword/Initialize(mapload) + . = ..() + set_sword_color() + +/obj/item/melee/transforming/energy/sword/proc/set_sword_color() + if(LAZYLEN(possible_colors)) + light_color = possible_colors[pick(possible_colors)] /obj/item/melee/transforming/energy/sword/transform_weapon(mob/living/user, supress_message_text) . = ..() if(active) - if(. && item_color) - icon_state = "sword[item_color]" AddElement(/datum/element/sword_point) else RemoveElement(/datum/element/sword_point) -/obj/item/melee/transforming/energy/sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(active) - return ..() - return 0 +/obj/item/melee/transforming/energy/sword/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!active) + return NONE + return ..() /obj/item/melee/transforming/energy/sword/cyborg - item_color = "red" + sword_color = "red" + light_color = "#ff0000" + possible_colors = null var/hitcost = 50 /obj/item/melee/transforming/energy/sword/cyborg/attack(mob/M, var/mob/living/silicon/robot/R) @@ -140,7 +152,7 @@ icon = 'icons/obj/surgery.dmi' icon_state = "esaw_0" icon_state_on = "esaw_1" - item_color = null //stops icon from breaking when turned on. + sword_color = null //stops icon from breaking when turned on. hitcost = 75 //Costs more than a standard cyborg esword w_class = WEIGHT_CLASS_NORMAL sharpness = IS_SHARP @@ -148,19 +160,17 @@ tool_behaviour = TOOL_SAW toolspeed = 0.7 -/obj/item/melee/transforming/energy/sword/cyborg/saw/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - return 0 +/obj/item/melee/transforming/energy/sword/cyborg/saw/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + return NONE /obj/item/melee/transforming/energy/sword/saber - var/list/possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER) + possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER) var/hacked = FALSE -/obj/item/melee/transforming/energy/sword/saber/Initialize(mapload) - . = ..() +/obj/item/melee/transforming/energy/sword/saber/set_sword_color() if(LAZYLEN(possible_colors)) - var/set_color = pick(possible_colors) - item_color = set_color - light_color = possible_colors[set_color] + sword_color = pick(possible_colors) + light_color = possible_colors[sword_color] /obj/item/melee/transforming/energy/sword/saber/process() . = ..() @@ -185,7 +195,7 @@ if(istype(W, /obj/item/multitool)) if(!hacked) hacked = TRUE - item_color = "rainbow" + sword_color = "rainbow" to_chat(user, "RNBW_ENGAGE") if(active) @@ -204,6 +214,7 @@ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' icon_state_on = "cutlass1" light_color = "#ff0000" + possible_colors = null /obj/item/melee/transforming/energy/blade name = "energy blade" @@ -271,32 +282,8 @@ return TRUE /obj/item/melee/transforming/energy/sword/cx/transform_weapon(mob/living/user, supress_message_text) - active = !active //I'd use a ..() here but it'd inherit from the regular esword's proc instead, so SPAGHETTI CODE - if(active) //also I'd need to rip out the iconstate changing bits - force = force_on - throwforce = throwforce_on - hitsound = hitsound_on - throw_speed = 4 - if(attack_verb_on.len) - attack_verb = attack_verb_on - w_class = w_class_on - START_PROCESSING(SSobj, src) - set_light(brightness_on) - update_icon() - else - force = initial(force) - throwforce = initial(throwforce) - hitsound = initial(hitsound) - throw_speed = initial(throw_speed) - if(attack_verb_off.len) - attack_verb = attack_verb_off - w_class = initial(w_class) - STOP_PROCESSING(SSobj, src) - set_light(0) - update_icon() - transform_messages(user, supress_message_text) - add_fingerprint(user) - return TRUE + . = ..() + update_icon() /obj/item/melee/transforming/energy/sword/cx/transform_messages(mob/living/user, supress_message_text) playsound(user, active ? 'sound/weapons/nebon.ogg' : 'sound/weapons/neboff.ogg', 65, 1) @@ -337,7 +324,7 @@ . = ..() . += "Alt-click to recolor it." -/obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(active) if(isinhands) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index cbbd50b573..011837d48b 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -2,13 +2,12 @@ item_flags = NEEDS_PERMIT /obj/item/melee/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user) - if(target.check_block()) + if(target.check_martial_melee_block()) target.visible_message("[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!", "You block the attack!") user.Stun(40) return TRUE - /obj/item/melee/chainofcommand name = "chain of command" desc = "A tool used by great men to placate the frothing masses." @@ -75,9 +74,9 @@ AddComponent(/datum/component/butchering, 30, 95, 5) //fast and effective, but as a sword, it might damage the results. AddElement(/datum/element/sword_point) -/obj/item/melee/sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(attack_type == PROJECTILE_ATTACK) - final_block_chance = 0 //Don't bring a sword to a gunfight +/obj/item/melee/sabre/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(attack_type & ATTACK_TYPE_PROJECTILE) // Don't bring a sword to a gunfight. + return BLOCK_NONE return ..() /obj/item/melee/sabre/on_exit_storage(datum/component/storage/S) @@ -165,8 +164,8 @@ . = ..() AddComponent(/datum/component/butchering, 20, 65, 0) -/obj/item/melee/rapier/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(attack_type == PROJECTILE_ATTACK) +/obj/item/melee/rapier/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(attack_type == ATTACK_TYPE_PROJECTILE) final_block_chance = 0 return ..() @@ -305,7 +304,7 @@ return else if(cooldown_check < world.time) - if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) + if(target.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS) playsound(target, 'sound/weapons/genhit.ogg', 50, 1) return if(ishuman(target)) diff --git a/code/game/objects/items/paint.dm b/code/game/objects/items/paint.dm index cc2f5e9be7..bdf9ab4270 100644 --- a/code/game/objects/items/paint.dm +++ b/code/game/objects/items/paint.dm @@ -7,7 +7,7 @@ desc = "Used to recolor floors and walls. Can be removed by the janitor." icon = 'icons/obj/items_and_weapons.dmi' icon_state = "paint_neutral" - item_color = "FFFFFF" + var/paint_color = "FFFFFF" item_state = "paintcan" w_class = WEIGHT_CLASS_NORMAL resistance_flags = FLAMMABLE @@ -16,37 +16,37 @@ /obj/item/paint/red name = "red paint" - item_color = "C73232" //"FF0000" + paint_color = "C73232" //"FF0000" icon_state = "paint_red" /obj/item/paint/green name = "green paint" - item_color = "2A9C3B" //"00FF00" + paint_color = "2A9C3B" //"00FF00" icon_state = "paint_green" /obj/item/paint/blue name = "blue paint" - item_color = "5998FF" //"0000FF" + paint_color = "5998FF" //"0000FF" icon_state = "paint_blue" /obj/item/paint/yellow name = "yellow paint" - item_color = "CFB52B" //"FFFF00" + paint_color = "CFB52B" //"FFFF00" icon_state = "paint_yellow" /obj/item/paint/violet name = "violet paint" - item_color = "AE4CCD" //"FF00FF" + paint_color = "AE4CCD" //"FF00FF" icon_state = "paint_violet" /obj/item/paint/black name = "black paint" - item_color = "333333" + paint_color = "333333" icon_state = "paint_black" /obj/item/paint/white name = "white paint" - item_color = "FFFFFF" + paint_color = "FFFFFF" icon_state = "paint_white" @@ -61,31 +61,31 @@ return switch(t1) if("red") - item_color = "C73232" + paint_color = "C73232" if("pink") - item_color = "FFC0CD" + paint_color = "FFC0CD" if("blue") - item_color = "5998FF" + paint_color = "5998FF" if("cyan") - item_color = "00FFFF" + paint_color = "00FFFF" if("green") - item_color = "2A9C3B" + paint_color = "2A9C3B" if("lime") - item_color = "00FF00" + paint_color = "00FF00" if("yellow") - item_color = "CFB52B" + paint_color = "CFB52B" if("orange") - item_color = "fFA700" + paint_color = "fFA700" if("violet") - item_color = "AE4CCD" + paint_color = "AE4CCD" if("purple") - item_color = "800080" + paint_color = "800080" if("white") - item_color = "FFFFFF" + paint_color = "FFFFFF" if("gray") - item_color = "808080" + paint_color = "808080" if("black") - item_color = "333333" + paint_color = "333333" icon_state = "paint_[t1]" add_fingerprint(user) @@ -99,7 +99,7 @@ return if(!isturf(target) || isspaceturf(target)) return - var/newcolor = "#" + item_color + var/newcolor = "#" + paint_color target.add_atom_colour(newcolor, WASHABLE_COLOUR_PRIORITY) /obj/item/paint/paint_remover diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index 498990fcf3..a564d7f9f9 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -434,7 +434,15 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths()) can_random_spawn = FALSE /obj/item/toy/plush/random/Initialize() - var/newtype = prob(CONFIG_GET(number/snowflake_plushie_prob))? /obj/item/toy/plush/random_snowflake : pick(GLOB.valid_plushie_paths) + var/newtype + var/list/snowflake_list = CONFIG_GET(keyed_list/snowflake_plushies) + + /// If there are no snowflake plushies we'll default to base plush, so we grab from the valid list + if (snowflake_list.len) + newtype = prob(CONFIG_GET(number/snowflake_plushie_prob)) ? /obj/item/toy/plush/random_snowflake : pick(GLOB.valid_plushie_paths) + else + newtype = pick(GLOB.valid_plushie_paths) + new newtype(loc) return INITIALIZE_HINT_QDEL diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index b89a2983f5..136d58ba41 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -214,7 +214,7 @@ /obj/item/clothing/head/helmet/plate/crusader/prophet name = "Prophet's Hat" desc = "A religious-looking hat." - alternate_worn_icon = 'icons/mob/large-worn-icons/64x64/head.dmi' + mob_overlay_icon = 'icons/mob/large-worn-icons/64x64/head.dmi' flags_1 = 0 armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 50, "bomb" = 70, "bio" = 50, "rad" = 50, "fire" = 60, "acid" = 60) //religion protects you from disease and radiation, honk. worn_x_dimension = 64 diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 0ca2fbd386..318753e4ad 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -11,7 +11,7 @@ var/charge_cost = 30 /obj/item/borg/stun/attack(mob/living/M, mob/living/user) - if(M.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK)) + if(M.run_block(src, 0, "[M]'s [name]", ATTACK_TYPE_MELEE, 0, user, ran_zone(user.zone_selected)) & BLOCK_SUCCESS) playsound(M, 'sound/weapons/genhit.ogg', 50, 1) return FALSE if(iscyborg(user)) diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index b137c5c0f3..08ce73109c 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -663,21 +663,19 @@ var/maxReduction = 1 -/obj/effect/proc_holder/silicon/cyborg/vtecControl/Click(mob/living/silicon/robot/user) - var/mob/living/silicon/robot/self = usr - +/obj/effect/proc_holder/silicon/cyborg/vtecControl/Trigger(mob/living/silicon/robot/user) currentState = (currentState + 1) % 3 - if(istype(self)) + if(istype(user)) switch(currentState) if (0) - self.speed = initial(self.speed) + user.speed = initial(user.speed) if (1) - self.speed = initial(self.speed) - maxReduction * 0.5 + user.speed = initial(user.speed) - maxReduction * 0.5 if (2) - self.speed = initial(self.speed) - maxReduction * 1 + user.speed = initial(user.speed) - maxReduction * 1 action.button_icon_state = "Chevron_State_[currentState]" action.UpdateButtonIcon() - return + return TRUE diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 07f4cb4e40..37dfc417d5 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -5,7 +5,7 @@ armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70) var/transparent = FALSE // makes beam projectiles pass through the shield -/obj/item/shield/proc/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK) +/obj/item/shield/proc/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance) return TRUE /obj/item/shield/riot @@ -26,16 +26,18 @@ transparent = TRUE max_integrity = 75 -/obj/item/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(transparent && (hitby.pass_flags & PASSGLASS)) - return FALSE - if(attack_type == THROWN_PROJECTILE_ATTACK) +/obj/item/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(ismovableatom(object)) + var/atom/movable/AM = object + if(transparent && (AM.pass_flags & PASSGLASS)) + return BLOCK_NONE + if(attack_type & ATTACK_TYPE_THROWN) final_block_chance += 30 - if(attack_type == LEAP_ATTACK) + if(attack_type & ATTACK_TYPE_TACKLE) final_block_chance = 100 . = ..() - if(.) - on_shield_block(owner, hitby, attack_text, damage, attack_type) + if(. & BLOCK_SUCCESS) + on_shield_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return) /obj/item/shield/riot/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/melee/baton)) @@ -69,10 +71,10 @@ playsound(owner, 'sound/effects/glassbr3.ogg', 100) new /obj/item/shard((get_turf(src))) -/obj/item/shield/riot/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK) +/obj/item/shield/riot/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(obj_integrity <= damage) var/turf/T = get_turf(owner) - T.visible_message("[hitby] destroys [src]!") + T.visible_message("[attack_text] destroys [src]!") shatter(owner) qdel(src) return FALSE @@ -139,11 +141,11 @@ . = ..() icon_state = "[base_icon_state]0" -/obj/item/shield/energy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - return 0 - -/obj/item/shield/energy/IsReflect() - return (active) +/obj/item/shield/energy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object)) + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT + return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT + return ..() /obj/item/shield/energy/attack_self(mob/living/carbon/human/user) if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) @@ -182,10 +184,10 @@ w_class = WEIGHT_CLASS_NORMAL var/active = 0 -/obj/item/shield/riot/tele/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(active) - return ..() - return 0 +/obj/item/shield/riot/tele/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!active) + return BLOCK_NONE + return ..() /obj/item/shield/riot/tele/attack_self(mob/living/user) active = !active @@ -249,7 +251,7 @@ transparent = FALSE item_flags = SLOWS_WHILE_IN_HAND -/obj/item/shield/riot/implant/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(attack_type == PROJECTILE_ATTACK) +/obj/item/shield/riot/implant/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(attack_type & ATTACK_TYPE_PROJECTILE) final_block_chance = 60 //Massive shield return ..() diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm index f864df5a21..00e48fd12a 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -5,6 +5,7 @@ icon = 'icons/obj/telescience.dmi' icon_state = "bluespace_crystal" singular_name = "bluespace crystal" + dye_color = DYE_COSMIC w_class = WEIGHT_CLASS_TINY custom_materials = list(/datum/material/bluespace=MINERAL_MATERIAL_AMOUNT) points = 50 diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 205ce57251..50e9b94e97 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -72,6 +72,8 @@ to_chat(user, " [M] is at full health.") return FALSE user.visible_message("[user] applies \the [src] on [M].", "You apply \the [src] on [M].") + if(AmBloodsucker(M)) + return M.heal_bodypart_damage((heal_brute/2)) return TRUE if(iscarbon(M)) @@ -148,6 +150,8 @@ return if(iscarbon(M)) return heal_carbon(M, user, 0, heal_burn) + if(AmBloodsucker(M)) + return to_chat(user, "You can't heal [M] with the \the [src]!") /obj/item/stack/medical/ointment/suicide_act(mob/living/user) diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 75db89f616..c8ee6b05c7 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -22,6 +22,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \ new/datum/stack_recipe("spout flask", /obj/item/glasswork/glass_base/spouty, 20), \ new/datum/stack_recipe("small bulb flask", /obj/item/glasswork/glass_base/flask_small, 5), \ new/datum/stack_recipe("large bottle flask", /obj/item/glasswork/glass_base/flask_large, 15), \ + new/datum/stack_recipe("tea cup", /obj/item/glasswork/glass_base/tea_plate, 5), \ + new/datum/stack_recipe("tea plate", /obj/item/glasswork/glass_base/tea_cup, 5), \ )), \ )) @@ -137,7 +139,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \ return ..() /obj/item/stack/sheet/plasmaglass/on_solar_construction(obj/machinery/power/solar/S) - S.obj_integrity *= 1.2 + S.max_integrity *= 1.2 S.efficiency *= 1.2 /* @@ -170,7 +172,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \ ..() /obj/item/stack/sheet/rglass/on_solar_construction(obj/machinery/power/solar/S) - S.obj_integrity *= 2 + S.max_integrity *= 2 /obj/item/stack/sheet/rglass/cyborg custom_materials = null @@ -218,7 +220,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \ . += GLOB.prglass_recipes /obj/item/stack/sheet/plasmarglass/on_solar_construction(obj/machinery/power/solar/S) - S.obj_integrity *= 2.2 + S.max_integrity *= 2.2 S.efficiency *= 1.2 GLOBAL_LIST_INIT(titaniumglass_recipes, list( @@ -242,7 +244,7 @@ GLOBAL_LIST_INIT(titaniumglass_recipes, list( . += GLOB.titaniumglass_recipes /obj/item/stack/sheet/titaniumglass/on_solar_construction(obj/machinery/power/solar/S) - S.obj_integrity *= 2.5 + S.max_integrity *= 2.5 S.efficiency *= 1.5 GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( @@ -270,7 +272,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( . += GLOB.plastitaniumglass_recipes /obj/item/stack/sheet/titaniumglass/on_solar_construction(obj/machinery/power/solar/S) - S.obj_integrity *= 2 + S.max_integrity *= 2 S.efficiency *= 2 /obj/item/shard diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index b0aad8b498..6ddd7c136a 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -179,8 +179,21 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ GLOBAL_LIST_INIT(plasteel_recipes, list ( \ new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \ new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \ - new/datum/stack_recipe("crate", /obj/structure/closet/crate, 5, time = 90, one_per_turf = TRUE), \ - null, \ + new /datum/stack_recipe_list("crates", list( \ + new /datum/stack_recipe("gray crate", /obj/structure/closet/crate, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("internals crate", /obj/structure/closet/crate/internals, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("trash cart", /obj/structure/closet/crate/trashcart, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("medical crate", /obj/structure/closet/crate/medical, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("freezer crate", /obj/structure/closet/crate/freezer, 8, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("blood bag crate", /obj/structure/closet/crate/freezer/blood, 8, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("surplus limbs crate", /obj/structure/closet/crate/freezer/surplus_limbs, 8, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("radiation containment crate", /obj/structure/closet/crate/radiation, 8, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("hydroponics crate", /obj/structure/closet/crate/hydroponics, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("engineering crate", /obj/structure/closet/crate/engineering, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("eletrical crate", /obj/structure/closet/crate/engineering/electrical, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("RCD storage crate", /obj/structure/closet/crate/rcd, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("science crate", /obj/structure/closet/crate/science, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + )), \ new /datum/stack_recipe_list("airlock assemblies", list( \ new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 50, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("vault door assembly", /obj/structure/door_assembly/door_assembly_vault, 6, time = 50, one_per_turf = 1, on_floor = 1), \ @@ -769,6 +782,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list( new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \ new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \ new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \ new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2))) /obj/item/stack/sheet/plastic @@ -846,4 +860,3 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra merge_type = /obj/item/stack/sheet/cotton/durathread pull_effort = 70 loom_result = /obj/item/stack/sheet/durathread - diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 5f2795c857..70b00c72ec 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -240,8 +240,7 @@ else if(istype(O, /obj/item/restraints/handcuffs/cable)) var/obj/item/cuffs = O - cuffs.item_color = item_color - cuffs.update_icon() + cuffs.color = color if (QDELETED(O)) return //It's a stack and has already been merged diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 0a29562d6b..dc6f5f701e 100755 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -22,7 +22,7 @@ for(var/obj/item/I in contents) . += I.get_belt_overlay() -/obj/item/storage/belt/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/storage/belt/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands && onmob_overlays) for(var/obj/item/I in contents) @@ -708,6 +708,7 @@ desc = "A dorky fannypack for keeping small items in." icon_state = "fannypack_leather" item_state = "fannypack_leather" + dying_key = DYE_REGISTRY_FANNYPACK /obj/item/storage/belt/fannypack/ComponentInitialize() . = ..() @@ -804,3 +805,4 @@ attack_verb = list("bashed", "slashes", "prods", "pokes") fitting_swords = list(/obj/item/melee/rapier) starting_sword = /obj/item/melee/rapier + diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index 037ae51e30..874c858b3f 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -404,6 +404,12 @@ new /obj/item/gun/ballistic/revolver(src) new /obj/item/ammo_box/a357(src) +/obj/item/storage/box/syndie_kit/pistol + +/obj/item/storage/box/syndie_kit/pistol/PopulateContents() + new /obj/item/gun/ballistic/automatic/pistol(src) + new /obj/item/ammo_box/magazine/m10mm(src) + /obj/item/storage/box/syndie_kit/contract_kit name = "contractor kit" desc = "Supplied to Syndicate contractors in active mission areas." @@ -494,4 +500,4 @@ new item1(src) // Create three, non repeat items from the list. new item2(src) new item3(src) - new /obj/item/paper/contractor_guide(src) //Paper guide \ No newline at end of file + new /obj/item/paper/contractor_guide(src) //Paper guide diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index 64a0026424..0fc47f649a 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -170,7 +170,7 @@ return disarming || (user.a_intent != INTENT_HARM) /obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user, disarming = FALSE) - if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that + if(L.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS) //No message; check_shields() handles that playsound(L, 'sound/weapons/genhit.ogg', 50, 1) return FALSE var/stunpwr = stamforce diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index c1cbf534ca..6ff5dfc8ad 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -376,8 +376,8 @@ filling.color = mix_color_from_reagents(reagents.reagent_list) add_overlay(filling) -/obj/item/reagent_containers/chemtank/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) //apply chemcolor and level - . = list() +/obj/item/reagent_containers/chemtank/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) //apply chemcolor and level + . = ..() //inhands + reagent_filling if(!isinhands && reagents.total_volume) var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "backpackmob-10") diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index 0d2892cb4a..e9f517a9f1 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -53,8 +53,8 @@ base_overlay.appearance_flags = RESET_COLOR . += base_overlay -/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() +/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(isinhands && random_color) var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") M.appearance_flags = RESET_COLOR diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index ba51fa3d65..9291b72467 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -273,15 +273,12 @@ var/obj/item/twohanded/dualsaber/toy/newSaber = new /obj/item/twohanded/dualsaber/toy(user.loc) if(hacked) // That's right, we'll only check the "original" "sword". newSaber.hacked = TRUE - newSaber.item_color = "rainbow" qdel(W) qdel(src) else if(istype(W, /obj/item/multitool)) if(!hacked) hacked = TRUE - item_color = "rainbow" to_chat(user, "RNBW_ENGAGE") - if(active) update_icon() user.update_inv_hands() @@ -352,7 +349,7 @@ update_light() return TRUE -/obj/item/toy/sword/cx/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/toy/sword/cx/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(active) if(isinhands) @@ -454,11 +451,8 @@ total_mass_on = TOTAL_MASS_TOY_SWORD sharpness = IS_BLUNT -/obj/item/twohanded/dualsaber/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - return FALSE - -/obj/item/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles - return FALSE +/obj/item/twohanded/dualsaber/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + return BLOCK_NONE /obj/item/twohanded/dualsaber/hypereutactic/toy name = "\improper DX Hyper-Euplastic LightSword" @@ -474,11 +468,8 @@ slowdown_wielded = 0 sharpness = IS_BLUNT -/obj/item/twohanded/dualsaber/hypereutactic/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - return FALSE - -/obj/item/twohanded/dualsaber/hypereutactic/toy/IsReflect()//Stops it from reflecting energy projectiles - return FALSE +/obj/item/twohanded/dualsaber/hypereutactic/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + return BLOCK_NONE /obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow name = "\improper Hyper-Euclidean Reciprocating Trigonometric Zweihander" diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index b188250fff..2b6a91eb51 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -281,7 +281,7 @@ hitsound = "swing_hit" var/hitsound_on = 'sound/weapons/blade1.ogg' armour_penetration = 35 - item_color = "green" + var/saber_color = "green" light_color = "#00ff00"//green attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 75 @@ -289,6 +289,8 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70) resistance_flags = FIRE_PROOF var/hacked = FALSE + /// Can this reflect all energy projectiles? + var/can_reflect = TRUE var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD var/list/possible_colors = list("red", "blue", "green", "purple") var/list/rainbow_colors = list(LIGHT_COLOR_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_LIGHT_CYAN, LIGHT_COLOR_LAVENDER) @@ -324,8 +326,8 @@ /obj/item/twohanded/dualsaber/Initialize() . = ..() if(LAZYLEN(possible_colors)) - item_color = pick(possible_colors) - switch(item_color) + saber_color = pick(possible_colors) + switch(saber_color) if("red") light_color = LIGHT_COLOR_RED if("green") @@ -341,7 +343,7 @@ /obj/item/twohanded/dualsaber/update_icon_state() if(wielded) - icon_state = "dualsaber[item_color][wielded]" + icon_state = "dualsaber[saber_color][wielded]" else icon_state = "dualsaber0" clean_blood() @@ -373,10 +375,13 @@ else user.adjustStaminaLoss(25) -/obj/item/twohanded/dualsaber/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(wielded) - return ..() - return 0 +/obj/item/twohanded/dualsaber/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!wielded) + return NONE + if(can_reflect && is_energy_reflectable_projectile(object) && (attack_type & ATTACK_TYPE_PROJECTILE)) + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER //no you + return BLOCK_SHOULD_REDIRECT | BLOCK_SUCCESS | BLOCK_REDIRECTED + return ..() /obj/item/twohanded/dualsaber/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) //In case thats just so happens that it is still activated on the groud, prevents hulk from picking it up if(wielded) @@ -419,10 +424,6 @@ /obj/item/twohanded/dualsaber/proc/rainbow_process() light_color = pick(rainbow_colors) -/obj/item/twohanded/dualsaber/IsReflect() - if(wielded) - return 1 - /obj/item/twohanded/dualsaber/ignition_effect(atom/A, mob/user) // same as /obj/item/melee/transforming/energy, mostly if(!wielded) @@ -456,7 +457,7 @@ if(!hacked) hacked = TRUE to_chat(user, "2XRNBW_ENGAGE") - item_color = "rainbow" + saber_color = "rainbow" update_icon() else to_chat(user, "It's starting to look like a triple rainbow - no, nevermind.") @@ -530,7 +531,7 @@ update_light() return TRUE -/obj/item/twohanded/dualsaber/hypereutactic/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/twohanded/dualsaber/hypereutactic/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(isinhands) var/mutable_appearance/gem_inhand = mutable_appearance(icon_file, "hypereutactic_gem") @@ -560,15 +561,13 @@ block_chance = 50 armour_penetration = 0 var/chaplain_spawnable = TRUE + can_reflect = FALSE obj_flags = UNIQUE_RENAME /obj/item/twohanded/dualsaber/hypereutactic/chaplain/ComponentInitialize() . = ..() AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE) -/obj/item/twohanded/dualsaber/hypereutactic/chaplain/IsReflect() - return FALSE - //spears /obj/item/twohanded/spear icon_state = "spearglass0" @@ -752,12 +751,16 @@ armour_penetration = 100 force_on = 30 -/obj/item/twohanded/required/chainsaw/doomslayer/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(attack_type == PROJECTILE_ATTACK) +/obj/item/twohanded/required/chainsaw/doomslayer/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] = 100 + return ..() + +/obj/item/twohanded/required/chainsaw/doomslayer/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(attack_type & ATTACK_TYPE_PROJECTILE) owner.visible_message("Ranged attacks just make [owner] angrier!") playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) - return 1 - return 0 + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return ..() //GREY TIDE /obj/item/twohanded/spear/grey_tide @@ -897,19 +900,20 @@ AddComponent(/datum/component/butchering, 20, 105) AddElement(/datum/element/sword_point) -/obj/item/twohanded/vibro_weapon/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) +/obj/item/twohanded/vibro_weapon/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(wielded) final_block_chance *= 2 - if(wielded || attack_type != PROJECTILE_ATTACK) + if(wielded || !(attack_type & ATTACK_TYPE_PROJECTILE)) if(prob(final_block_chance)) - if(attack_type == PROJECTILE_ATTACK) + if(attack_type & ATTACK_TYPE_PROJECTILE) owner.visible_message("[owner] deflects [attack_text] with [src]!") playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) - return 1 + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT + return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL else owner.visible_message("[owner] parries [attack_text] with [src]!") - return 1 - return 0 + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return NONE /obj/item/twohanded/vibro_weapon/update_icon_state() icon_state = "hfrequency[wielded]" @@ -1055,11 +1059,9 @@ var/mob/living/silicon/robot/R = loc . = R.get_cell() -/obj/item/twohanded/electrostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(!on) - return FALSE - if((attack_type == PROJECTILE_ATTACK) && !can_block_projectiles) - return FALSE +/obj/item/twohanded/electrostaff/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!on || (!can_block_projectiles && (attack_type & ATTACK_TYPE_PROJECTILE))) + return BLOCK_NONE return ..() /obj/item/twohanded/electrostaff/proc/min_hitcost() @@ -1180,7 +1182,7 @@ if(iscyborg(target)) ..() return - if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that + if(target.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS) //No message; run_block() handles that playsound(target, 'sound/weapons/genhit.ogg', 50, 1) return FALSE if(user.a_intent != INTENT_HARM) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 7f40e3d698..8496a8a216 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -84,6 +84,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 name = "purified longsword" desc = "A hastily-purified longsword. While not as holy as it could be, it's still a formidable weapon against those who would rather see you dead." force = 25 + block_chance = 0 /obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." @@ -155,8 +156,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 return to_chat(user, "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))].") -/obj/item/claymore/highlander/IsReflect() - return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME? +/obj/item/claymore/highlander/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object)) + return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED + return ..() /obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE notches++ @@ -607,14 +610,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 force = 12 throwforce = 15 -/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers - var/picksound = rand(1,2) - var/turf = get_turf(src) - if(picksound == 1) - playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1) - if(picksound == 2) - playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1) - return 1 +/obj/item/melee/baseball_bat/ablative/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + //some day this will reflect thrown items instead of lasers + if(is_energy_reflectable_projectile(object) && (attack_type == ATTACK_TYPE_PROJECTILE)) + var/turf = get_turf(src) + playsound(turf, pick('sound/weapons/effects/batreflect1.ogg', 'sound/weapons/effects/batreflect2.ogg'), 50, 1) + return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED + return ..() /obj/item/melee/baseball_bat/ablative/syndi name = "syndicate major league bat" diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 06c1d96711..c593451c24 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -317,7 +317,7 @@ throwforce = 10 throw_range = 3 hitsound = 'sound/items/trayhit1.ogg' - hit_reaction_chance = 50 + block_chance = 50 custom_materials = list(/datum/material/iron = 2000) var/break_chance = 5 //Likely hood of smashing the chair. var/obj/structure/chair/origin_type = /obj/structure/chair @@ -362,18 +362,17 @@ new stack_type(get_turf(loc)) qdel(src) -/obj/item/chair/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(attack_type == UNARMED_ATTACK && prob(hit_reaction_chance)) - owner.visible_message("[owner] fends off [attack_text] with [src]!") - return 1 - return 0 +/obj/item/chair/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!(attack_type & ATTACK_TYPE_UNARMED)) + return NONE + return ..() /obj/item/chair/afterattack(atom/target, mob/living/carbon/user, proximity) . = ..() if(!proximity) return if(prob(break_chance)) - user.visible_message("[user] smashes \the [src] to pieces against \the [target]") + user.visible_message("[user] smashes [src] to pieces against [target]") if(iscarbon(target)) var/mob/living/carbon/C = target if(C.health < C.maxHealth*0.5) diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 0991351102..57d7e08862 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -16,8 +16,8 @@ LINEN BINS throw_speed = 1 throw_range = 2 w_class = WEIGHT_CLASS_TINY - item_color = "white" resistance_flags = FLAMMABLE + dying_key = DYE_REGISTRY_BEDSHEET dog_fashion = /datum/dog_fashion/head/ghost var/list/dream_messages = list("white") @@ -52,79 +52,66 @@ LINEN BINS /obj/item/bedsheet/blue icon_state = "sheetblue" - item_color = "blue" dream_messages = list("blue") /obj/item/bedsheet/green icon_state = "sheetgreen" - item_color = "green" dream_messages = list("green") /obj/item/bedsheet/grey icon_state = "sheetgrey" - item_color = "grey" dream_messages = list("grey") /obj/item/bedsheet/orange icon_state = "sheetorange" - item_color = "orange" dream_messages = list("orange") /obj/item/bedsheet/purple icon_state = "sheetpurple" - item_color = "purple" dream_messages = list("purple") /obj/item/bedsheet/patriot name = "patriotic bedsheet" desc = "You've never felt more free than when sleeping on this." icon_state = "sheetUSA" - item_color = "sheetUSA" dream_messages = list("America", "freedom", "fireworks", "bald eagles") /obj/item/bedsheet/rainbow name = "rainbow bedsheet" desc = "A multicolored blanket. It's actually several different sheets cut up and sewn together." icon_state = "sheetrainbow" - item_color = "rainbow" dream_messages = list("red", "orange", "yellow", "green", "blue", "purple", "a rainbow") /obj/item/bedsheet/red icon_state = "sheetred" - item_color = "red" dream_messages = list("red") /obj/item/bedsheet/yellow icon_state = "sheetyellow" - item_color = "yellow" dream_messages = list("yellow") /obj/item/bedsheet/mime name = "mime's blanket" desc = "A very soothing striped blanket. All the noise just seems to fade out when you're under the covers in this." icon_state = "sheetmime" - item_color = "mime" dream_messages = list("silence", "gestures", "a pale face", "a gaping mouth", "the mime") /obj/item/bedsheet/clown name = "clown's blanket" desc = "A rainbow blanket with a clown mask woven in. It smells faintly of bananas." icon_state = "sheetclown" - item_color = "clown" dream_messages = list("honk", "laughter", "a prank", "a joke", "a smiling face", "the clown") /obj/item/bedsheet/captain name = "captain's bedsheet" desc = "It has a Nanotrasen symbol on it, and was woven with a revolutionary new kind of thread guaranteed to have 0.01% permeability for most non-chemical substances, popular among most modern captains." icon_state = "sheetcaptain" - item_color = "captain" dream_messages = list("authority", "a golden ID", "sunglasses", "a green disc", "an antique gun", "the captain") /obj/item/bedsheet/rd name = "research director's bedsheet" desc = "It appears to have a beaker emblem, and is made out of fire-resistant material, although it probably won't protect you in the event of fires you're familiar with every day." icon_state = "sheetrd" - item_color = "director" dream_messages = list("authority", "a silvery ID", "a bomb", "a mech", "a facehugger", "maniacal laughter", "the research director") // for Free Golems. @@ -137,111 +124,94 @@ LINEN BINS name = "medical blanket" desc = "It's a sterilized* blanket commonly used in the Medbay. *Sterilization is voided if a virologist is present onboard the station." icon_state = "sheetmedical" - item_color = "medical" dream_messages = list("healing", "life", "surgery", "a doctor") /obj/item/bedsheet/cmo name = "chief medical officer's bedsheet" desc = "It's a sterilized blanket that has a cross emblem. There's some cat fur on it, likely from Runtime." icon_state = "sheetcmo" - item_color = "cmo" dream_messages = list("authority", "a silvery ID", "healing", "life", "surgery", "a cat", "the chief medical officer") /obj/item/bedsheet/hos name = "head of security's bedsheet" desc = "It is decorated with a shield emblem. While crime doesn't sleep, you do, but you are still THE LAW!" icon_state = "sheethos" - item_color = "hosred" dream_messages = list("authority", "a silvery ID", "handcuffs", "a baton", "a flashbang", "sunglasses", "the head of security") /obj/item/bedsheet/hop name = "head of personnel's bedsheet" desc = "It is decorated with a key emblem. For those rare moments when you can rest and cuddle with Ian without someone screaming for you over the radio." icon_state = "sheethop" - item_color = "hop" dream_messages = list("authority", "a silvery ID", "obligation", "a computer", "an ID", "a corgi", "the head of personnel") /obj/item/bedsheet/ce name = "chief engineer's bedsheet" desc = "It is decorated with a wrench emblem. It's highly reflective and stain resistant, so you don't need to worry about ruining it with oil." icon_state = "sheetce" - item_color = "chief" dream_messages = list("authority", "a silvery ID", "the engine", "power tools", "an APC", "a parrot", "the chief engineer") /obj/item/bedsheet/qm name = "quartermaster's bedsheet" desc = "It is decorated with a crate emblem in silver lining. It's rather tough, and just the thing to lie on after a hard day of pushing paper." icon_state = "sheetqm" - item_color = "qm" dream_messages = list("a grey ID", "a shuttle", "a crate", "a sloth", "the quartermaster") /obj/item/bedsheet/brown icon_state = "sheetbrown" - item_color = "cargo" dream_messages = list("brown") /obj/item/bedsheet/black icon_state = "sheetblack" - item_color = "black" dream_messages = list("black") /obj/item/bedsheet/centcom name = "\improper CentCom bedsheet" desc = "Woven with advanced nanothread for warmth as well as being very decorated, essential for all officials." icon_state = "sheetcentcom" - item_color = "centcom" dream_messages = list("a unique ID", "authority", "artillery", "an ending") /obj/item/bedsheet/syndie name = "syndicate bedsheet" desc = "It has a syndicate emblem and it has an aura of evil." icon_state = "sheetsyndie" - item_color = "syndie" dream_messages = list("a green disc", "a red crystal", "a glowing blade", "a wire-covered ID") /obj/item/bedsheet/cult name = "cultist's bedsheet" desc = "You might dream of Nar'Sie if you sleep with this. It seems rather tattered and glows of an eldritch presence." icon_state = "sheetcult" - item_color = "cult" dream_messages = list("a tome", "a floating red crystal", "a glowing sword", "a bloody symbol", "a massive humanoid figure") /obj/item/bedsheet/wiz name = "wizard's bedsheet" desc = "A special fabric enchanted with magic so you can have an enchanted night. It even glows!" icon_state = "sheetwiz" - item_color = "wiz" dream_messages = list("a book", "an explosion", "lightning", "a staff", "a skeleton", "a robe", "magic") /obj/item/bedsheet/nanotrasen name = "nanotrasen bedsheet" desc = "It has the Nanotrasen logo on it and has an aura of duty." icon_state = "sheetNT" - item_color = "nanotrasen" dream_messages = list("authority", "an ending") /obj/item/bedsheet/ian icon_state = "sheetian" - item_color = "ian" dream_messages = list("a dog", "a corgi", "woof", "bark", "arf") /obj/item/bedsheet/runtime icon_state = "sheetruntime" - item_color = "runtime" dream_messages = list("a kitty", "a cat", "meow", "purr", "nya~") /obj/item/bedsheet/pirate name = "pirate's bedsheet" desc = "It has a Jolly Roger emblem on it and has a faint scent of grog." icon_state = "sheetpirate" - item_color = "black" dream_messages = list("doing whatever oneself wants", "cause a pirate is free", "being a pirate", "stealing", "landlubbers", "gold", "a buried treasure", "yarr", "avast", "a swashbuckler", "sailing the Seven Seas", "a parrot", "a monkey", "an island", "a talking skull") /obj/item/bedsheet/gondola name = "gondola bedsheet" desc = "A precious bedsheet made from the hide of a rare and peculiar critter." icon_state = "sheetgondola" - item_color = "cargo" var/g_mouth var/g_eyes @@ -252,7 +222,7 @@ LINEN BINS add_overlay(g_mouth) add_overlay(g_eyes) -/obj/item/bedsheet/gondola/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) +/obj/item/bedsheet/gondola/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) . += mutable_appearance(icon_file, g_mouth) @@ -262,14 +232,12 @@ LINEN BINS name = "cosmic space bedsheet" desc = "Made from the dreams of those who wonder at the stars." icon_state = "sheetcosmos" - item_color = "cosmos" dream_messages = list("the infinite cosmos", "Hans Zimmer music", "a flight through space", "the galaxy", "being fabulous", "shooting stars") light_power = 2 light_range = 1.4 /obj/item/bedsheet/random icon_state = "random_bedsheet" - item_color = "rainbow" name = "random bedsheet" desc = "If you're reading this description ingame, something has gone wrong! Honk!" diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index 5ec3851128..e51aeafdc1 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -100,3 +100,12 @@ if(isliving(A)) to_chat(A, "You're suddenly forced into a tiny, compressed space!") qdel(src) + +/obj/structure/closet/body_bag/containment + name = "containment body bag" + desc = "A folded heavy body bag designed for the storage and transportation of cadavers with heavy radiation." + icon = 'icons/obj/bodybag.dmi' + icon_state = "radbodybag" + mob_storage_capacity = 1 + foldedbag_path = /obj/item/bodybag/containment + rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index b0dfec6318..2c977a34d6 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -179,6 +179,7 @@ desc = "A crate with a radiation sign on it." name = "radiation crate" icon_state = "radiation" + rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE /obj/structure/closet/crate/hydroponics name = "hydroponics crate" diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm deleted file mode 100644 index bba51035fe..0000000000 --- a/code/game/objects/structures/musician.dm +++ /dev/null @@ -1,383 +0,0 @@ - -#define MUSICIAN_HEARCHECK_MINDELAY 4 -#define MUSIC_MAXLINES 600 -#define MUSIC_MAXLINECHARS 150 - -/datum/song - var/name = "Untitled" - var/list/lines = new() - var/tempo = 5 // delay between notes - - var/playing = 0 // if we're playing - var/help = 0 // if help is open - var/edit = 1 // if we're in editing mode - var/repeat = 0 // number of times remaining to repeat - var/max_repeats = 10 // maximum times we can repeat - - var/instrumentDir = "piano" // the folder with the sounds - var/instrumentExt = "ogg" // the file extension - var/obj/instrumentObj = null // the associated obj playing the sound - var/last_hearcheck = 0 - var/list/hearing_mobs - -/datum/song/New(dir, obj, ext = "ogg") - tempo = sanitize_tempo(tempo) - instrumentDir = dir - instrumentObj = obj - instrumentExt = ext - -/datum/song/Destroy() - instrumentObj = null - return ..() - -// note is a number from 1-7 for A-G -// acc is either "b", "n", or "#" -// oct is 1-8 (or 9 for C) -/datum/song/proc/playnote(note, acc as text, oct) - // handle accidental -> B<>C of E<>F - if(acc == "b" && (note == 3 || note == 6)) // C or F - if(note == 3) - oct-- - note-- - acc = "n" - else if(acc == "#" && (note == 2 || note == 5)) // B or E - if(note == 2) - oct++ - note++ - acc = "n" - else if(acc == "#" && (note == 7)) //G# - note = 1 - acc = "b" - else if(acc == "#") // mass convert all sharps to flats, octave jump already handled - acc = "b" - note++ - - // check octave, C is allowed to go to 9 - if(oct < 1 || (note == 3 ? oct > 9 : oct > 8)) - return - - // now generate name - var/soundfile = "sound/instruments/[instrumentDir]/[ascii2text(note+64)][acc][oct].[instrumentExt]" - soundfile = file(soundfile) - // make sure the note exists - if(!fexists(soundfile)) - return - // and play - var/turf/source = get_turf(instrumentObj) - if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck) - LAZYCLEARLIST(hearing_mobs) - for(var/mob/M in get_hearers_in_view(15, source)) - if(!M.client || !(M.client.prefs.toggles & SOUND_INSTRUMENTS)) - continue - LAZYADD(hearing_mobs, M) - last_hearcheck = world.time - - var/sound/music_played = sound(soundfile) - for(var/i in hearing_mobs) - var/mob/M = i - M.playsound_local(source, null, 100, falloff = 5, S = music_played) - -/datum/song/proc/updateDialog(mob/user) - instrumentObj.updateDialog() // assumes it's an object in world, override if otherwise - -/datum/song/proc/shouldStopPlaying(mob/user) - if(instrumentObj) - if(!user.canUseTopic(instrumentObj, TRUE, FALSE, FALSE, FALSE)) - return TRUE - return !instrumentObj.anchored // add special cases to stop in subclasses - else - return TRUE - -/datum/song/proc/playsong(mob/user) - while(repeat >= 0) - var/cur_oct[7] - var/cur_acc[7] - for(var/i = 1 to 7) - cur_oct[i] = 3 - cur_acc[i] = "n" - - for(var/line in lines) - for(var/beat in splittext(lowertext(line), ",")) - var/list/notes = splittext(beat, "/") - for(var/note in splittext(notes[1], "-")) - if(!playing || shouldStopPlaying(user))//If the instrument is playing, or special case - playing = FALSE - hearing_mobs = null - return - if(!length(note)) - continue - var/cur_note = text2ascii(note) - 96 - if(cur_note < 1 || cur_note > 7) - continue - var/notelen = length(note) - var/ni = "" - for(var/i = length(note[1]) + 1, i <= notelen, i += length(ni)) - ni = note[i] - if(!text2num(ni)) - if(ni == "#" || ni == "b" || ni == "n") - cur_acc[cur_note] = ni - else if(ni == "s") - cur_acc[cur_note] = "#" // so shift is never required - else - cur_oct[cur_note] = text2num(ni) - if(user.dizziness > 0 && prob(user.dizziness / 2)) - cur_note = CLAMP(cur_note + rand(round(-user.dizziness / 10), round(user.dizziness / 10)), 1, 7) - if(user.dizziness > 0 && prob(user.dizziness / 5)) - if(prob(30)) - cur_acc[cur_note] = "#" - else if(prob(42)) - cur_acc[cur_note] = "b" - else if(prob(75)) - cur_acc[cur_note] = "n" - playnote(cur_note, cur_acc[cur_note], cur_oct[cur_note]) - if(notes.len >= 2 && text2num(notes[2])) - sleep(sanitize_tempo(tempo / text2num(notes[2]))) - else - sleep(tempo) - repeat-- - hearing_mobs = null - playing = FALSE - repeat = 0 - updateDialog(user) - -/datum/song/proc/interact(mob/user) - var/dat = "" - - if(lines.len > 0) - dat += "

Playback

" - if(!playing) - dat += "Play Stop

" - dat += "Repeat Song: " - dat += repeat > 0 ? "--" : "--" - dat += " [repeat] times " - dat += repeat < max_repeats ? "++" : "++" - dat += "
" - else - dat += "Play Stop
" - dat += "Repeats left: [repeat]
" - if(!edit) - dat += "
Show Editor
" - else - dat += "

Editing

" - dat += "Hide Editor" - dat += " Start a New Song" - dat += " Import a Song

" - var/bpm = round(600 / tempo) - dat += "Tempo: - [bpm] BPM +

" - var/linecount = 0 - for(var/line in lines) - linecount += 1 - dat += "Line [linecount]: Edit X [line]
" - dat += "Add Line

" - if(help) - dat += "Hide Help
" - dat += {" - Lines are a series of chords, separated by commas (,), each with notes separated by hyphens (-).
- Every note in a chord will play together, with chord timed by the tempo.
-
- Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.
- By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.
- Example: C,D,E,F,G,A,B will play a C major scale.
- After a note has an accidental placed, it will be remembered: C,C4,C,C3 is C3,C4,C4,C3
- Chords can be played simply by seperating each note with a hyphon: A-C#,Cn-E,E-G#,Gn-B
- A pause may be denoted by an empty chord: C,E,,C,G
- To make a chord be a different time, end it with /x, where the chord length will be length
- defined by tempo / x: C,G/2,E/4
- Combined, an example is: E-E4/4,F#/2,G#/8,B/8,E3-E4/4 -
- Lines may be up to [MUSIC_MAXLINECHARS] characters.
- A song may only contain up to [MUSIC_MAXLINES] lines.
- "} - else - dat += "Show Help
" - - var/datum/browser/popup = new(user, "instrument", instrumentObj.name, 700, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(instrumentObj.icon, instrumentObj.icon_state)) - popup.open() - -/datum/song/proc/ParseSong(text) - set waitfor = FALSE - //split into lines - lines = splittext(text, "\n") - if(lines.len) - var/bpm_string = "BPM: " - if(findtext(lines[1], bpm_string, 1, length(bpm_string) + 1)) - var/divisor = text2num(copytext(lines[1], length(bpm_string) + 1)) || 120 // default - tempo = sanitize_tempo(600 / round(divisor, 1)) - lines.Cut(1, 2) - else - tempo = sanitize_tempo(5) // default 120 BPM - if(lines.len > MUSIC_MAXLINES) - to_chat(usr, "Too many lines!") - lines.Cut(MUSIC_MAXLINES + 1) - var/linenum = 1 - for(var/l in lines) - if(length_char(l) > MUSIC_MAXLINECHARS) - to_chat(usr, "Line [linenum] too long!") - lines.Remove(l) - else - linenum++ - updateDialog(usr) // make sure updates when complete - -/datum/song/Topic(href, href_list) - if(!usr.canUseTopic(instrumentObj, TRUE, FALSE, FALSE, FALSE)) - usr << browse(null, "window=instrument") - usr.unset_machine() - return - - instrumentObj.add_fingerprint(usr) - - if(href_list["newsong"]) - lines = new() - tempo = sanitize_tempo(5) // default 120 BPM - name = "" - - else if(href_list["import"]) - var/t = "" - do - t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", name), t) as message) - if(!in_range(instrumentObj, usr)) - return - - if(length_char(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS) - var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") - if(cont == "no") - break - while(length_char(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS) - ParseSong(t) - - else if(href_list["help"]) - help = text2num(href_list["help"]) - 1 - - else if(href_list["edit"]) - edit = text2num(href_list["edit"]) - 1 - - if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. - if(playing) - return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. - repeat += round(text2num(href_list["repeat"])) - if(repeat < 0) - repeat = 0 - if(repeat > max_repeats) - repeat = max_repeats - - else if(href_list["tempo"]) - tempo = sanitize_tempo(tempo + text2num(href_list["tempo"])) - - else if(href_list["play"]) - playing = TRUE - spawn() - playsong(usr) - - else if(href_list["newline"]) - var/newline = html_encode(input("Enter your line: ", instrumentObj.name) as text|null) - if(!newline || !in_range(instrumentObj, usr)) - return - if(lines.len > MUSIC_MAXLINES) - return - if(length(newline) > MUSIC_MAXLINECHARS) - newline = copytext(newline, 1, MUSIC_MAXLINECHARS) - lines.Add(newline) - - else if(href_list["deleteline"]) - var/num = round(text2num(href_list["deleteline"])) - if(num > lines.len || num < 1) - return - lines.Cut(num, num+1) - - else if(href_list["modifyline"]) - var/num = round(text2num(href_list["modifyline"]),1) - var/content = stripped_input(usr, "Enter your line: ", instrumentObj.name, lines[num], MUSIC_MAXLINECHARS) - if(!content || !in_range(instrumentObj, usr)) - return - if(num > lines.len || num < 1) - return - lines[num] = content - - else if(href_list["stop"]) - playing = FALSE - hearing_mobs = null - - updateDialog(usr) - return - -/datum/song/proc/sanitize_tempo(new_tempo) - new_tempo = abs(new_tempo) - return max(round(new_tempo, world.tick_lag), world.tick_lag) - -// subclass for handheld instruments, like violin -/datum/song/handheld - -/datum/song/handheld/updateDialog(mob/user) - instrumentObj.interact(user) - -/datum/song/handheld/shouldStopPlaying() - if(instrumentObj) - return !isliving(instrumentObj.loc) - else - return TRUE - - -////////////////////////////////////////////////////////////////////////// - - -/obj/structure/piano - name = "space minimoog" - icon = 'icons/obj/musician.dmi' - icon_state = "minimoog" - anchored = TRUE - density = TRUE - var/datum/song/song - -/obj/structure/piano/unanchored - anchored = FALSE - -/obj/structure/piano/New() - ..() - song = new("piano", src) - - if(prob(50) && icon_state == initial(icon_state)) - name = "space minimoog" - desc = "This is a minimoog, like a space piano, but more spacey!" - icon_state = "minimoog" - else - name = "space piano" - desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't." - icon_state = "piano" - -/obj/structure/piano/Destroy() - qdel(song) - song = null - return ..() - -/obj/structure/piano/Initialize(mapload) - . = ..() - if(mapload) - song.tempo = song.sanitize_tempo(song.tempo) // tick_lag isn't set when the map is loaded - -/obj/structure/piano/attack_hand(mob/user) - . = ..() - if(.) - return - interact(user) - -/obj/structure/piano/attack_paw(mob/user) - return attack_hand(user) - -/obj/structure/piano/interact(mob/user) - ui_interact(user) - -/obj/structure/piano/ui_interact(mob/user) - if(!user || !anchored) - return - - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return 1 - user.set_machine(src) - song.interact(user) - -/obj/structure/piano/wrench_act(mob/living/user, obj/item/I) - default_unfasten_wrench(user, I, 40) - return TRUE diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index f225723fc3..95edd15951 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -64,7 +64,7 @@ else I.forceMove(drop_location()) to_chat(user, "You find [I] in the cistern.") - w_items -= I.w_class + w_items = max(w_items - I.w_class, 0) else open = !open update_icon() @@ -112,12 +112,14 @@ . = ..() if (secret_type) secret = new secret_type(src) - secret.desc += " It's a secret!" - w_items += secret.w_class + secret.desc += "" //In case you want to add something to the item that spawns contents += secret -/obj/structure/toilet/secret/prison - secret_type = /obj/effect/spawner/lootdrop/prison_loot_toilet +/obj/structure/toilet/secret/LateInitialize() + . = ..() + w_items = 0 //recalculate total weight thanks to the secret. + for(var/obj/item/I in contents) + w_items += I.w_class /obj/structure/toilet/secret/low_loot secret_type = /obj/effect/spawner/lootdrop/low_loot_toilet @@ -125,6 +127,9 @@ /obj/structure/toilet/secret/high_loot secret_type = /obj/effect/spawner/lootdrop/high_loot_toilet +/obj/structure/toilet/secret/prison + secret_type = /obj/effect/spawner/lootdrop/prison_loot_toilet + /obj/structure/urinal name = "urinal" desc = "The HU-452, an experimental urinal. Comes complete with experimental urinal cake." diff --git a/code/game/sound.dm b/code/game/sound.dm index c285026d5b..577b058178 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -8,7 +8,7 @@ return //allocate a channel if necessary now so its the same for everyone - channel = channel || open_sound_channel() + channel = channel || SSsounds.random_available_channel() // Looping through the player list has the added bonus of working for mobs inside containers var/sound/S = sound(get_sfx(soundin)) @@ -26,10 +26,10 @@ if(get_dist(M, turf_source) <= maxdistance) M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, soundenvwet, soundenvdry) -/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S, envwet = -10000, envdry = 0, manual_x, manual_y) +/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S, envwet = -10000, envdry = 0, manual_x, manual_y, distance_multiplier = 1) if(audiovisual_redirect) var/turf/T = get_turf(src) - audiovisual_redirect.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, 0, -1000, turf_source.x - T.x, turf_source.y - T.y) + audiovisual_redirect.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, 0, -1000, turf_source.x - T.x, turf_source.y - T.y, distance_multiplier) if(!client || !can_hear()) return @@ -37,7 +37,7 @@ S = sound(get_sfx(soundin)) S.wait = 0 //No queue - S.channel = channel || open_sound_channel() + S.channel = channel || SSsounds.random_available_channel() S.volume = vol S.environment = 7 @@ -55,6 +55,8 @@ if(!manual_x && !manual_y) distance = get_dist(T, turf_source) + distance *= distance_multiplier + S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff. if(pressure_affected) @@ -86,13 +88,13 @@ dx = turf_source.x - T.x else dx = manual_x - S.x = dx + S.x = dx * distance_multiplier var/dz = 0 // Hearing from infront/behind if(!manual_x) dz = turf_source.y - T.y else dz = manual_y - S.z = dz + S.z = dz * distance_multiplier // The y value is for above your head, but there is no ceiling in 2d spessmens. S.y = 1 S.falloff = (falloff ? falloff : FALLOFF_SOUNDS) @@ -107,15 +109,14 @@ var/mob/M = m M.playsound_local(M, null, volume, vary, frequency, falloff, channel, pressure_affected, S) -/proc/open_sound_channel() - var/static/next_channel = 1 //loop through the available 1024 - (the ones we reserve) channels and pray that its not still being used - . = ++next_channel - if(next_channel > CHANNEL_HIGHEST_AVAILABLE) - next_channel = 1 - /mob/proc/stop_sound_channel(chan) SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = chan)) +/mob/proc/set_sound_channel_volume(channel, volume) + var/sound/S = sound(null, FALSE, FALSE, channel, volume) + S.status = SOUND_UPDATE + SEND_SOUND(src, S) + /client/proc/playtitlemusic(vol = 85) set waitfor = FALSE UNTIL(SSticker.login_music) //wait for SSticker init to set the login music diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index c61ac8972c..7e1b39cb39 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -173,6 +173,16 @@ /turf/closed/mineral/silver = 12, /turf/closed/mineral/plasma = 20, /turf/closed/mineral/iron = 40, /turf/closed/mineral/titanium = 11, /turf/closed/mineral/gibtonite = 4, /turf/closed/mineral/bscrystal = 1) +/turf/closed/mineral/random/no_caves/earth_like + icon_state = "rock_oxy" + turf_type = /turf/open/floor/plating/asteroid + baseturfs = /turf/open/floor/plating/asteroid + mineralSpawnChanceList = list(/turf/closed/mineral/uranium/earth_like = 5, /turf/closed/mineral/diamond/earth_like = 1, /turf/closed/mineral/gold/earth_like = 10, + /turf/closed/mineral/silver/earth_like = 12, /turf/closed/mineral/plasma/earth_like = 20, /turf/closed/mineral/iron/earth_like = 40, + /turf/closed/mineral/titanium/earth_like = 11, /turf/closed/mineral/gibtonite/earth_like = 4, /turf/closed/mineral/bscrystal/earth_like = 1) + initial_gas_mix = OPENTURF_DEFAULT_ATMOS + defer_change = TRUE + /turf/closed/mineral/random/high_chance icon_state = "rock_highchance" mineralChance = 25 @@ -194,6 +204,10 @@ icon_state = "rock_highchance_oxy" turf_type = /turf/open/floor/plating/asteroid baseturfs = /turf/open/floor/plating/asteroid + mineralSpawnChanceList = list( + /turf/closed/mineral/uranium/earth_like = 35, /turf/closed/mineral/diamond/earth_like = 30, /turf/closed/mineral/gold/earth_like = 45, + /turf/closed/mineral/titanium/earth_like = 45, /turf/closed/mineral/silver/earth_like = 50, /turf/closed/mineral/plasma/earth_like = 50, + /turf/closed/mineral/bscrystal/earth_like = 20) initial_gas_mix = OPENTURF_DEFAULT_ATMOS defer_change = TRUE @@ -211,6 +225,10 @@ turf_type = /turf/open/floor/plating/asteroid baseturfs = /turf/open/floor/plating/asteroid initial_gas_mix = OPENTURF_DEFAULT_ATMOS + mineralSpawnChanceList = list( + /turf/closed/mineral/uranium/earth_like = 2, /turf/closed/mineral/diamond/earth_like = 1, /turf/closed/mineral/gold/earth_like = 4, + /turf/closed/mineral/titanium/earth_like = 4, /turf/closed/mineral/silver/earth_like = 6, /turf/closed/mineral/plasma/earth_like = 15, + /turf/closed/mineral/iron/earth_like = 40, /turf/closed/mineral/gibtonite/earth_like = 2, /turf/closed/mineral/bscrystal/earth_like = 1) defer_change = TRUE /turf/closed/mineral/random/volcanic @@ -246,13 +264,6 @@ /turf/closed/mineral/silver/volcanic = 20, /turf/closed/mineral/plasma/volcanic = 30, /turf/closed/mineral/bscrystal/volcanic = 1, /turf/closed/mineral/gibtonite/volcanic = 2, /turf/closed/mineral/iron/volcanic = 95) -/turf/closed/mineral/random/earth_like - icon_state = "rock_oxy" - turf_type = /turf/open/floor/plating/asteroid - baseturfs = /turf/open/floor/plating/asteroid - initial_gas_mix = OPENTURF_DEFAULT_ATMOS - defer_change = TRUE - /turf/closed/mineral/iron mineralType = /obj/item/stack/ore/iron @@ -624,3 +635,10 @@ baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface initial_gas_mix = LAVALAND_DEFAULT_ATMOS defer_change = 1 + +/turf/closed/mineral/gibtonite/earth_like + icon_state = "rock_oxy" + turf_type = /turf/open/floor/plating/asteroid + baseturfs = /turf/open/floor/plating/asteroid + initial_gas_mix = OPENTURF_DEFAULT_ATMOS + defer_change = TRUE diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index d86211f216..62c2dc900c 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1732,9 +1732,8 @@ var/mob/M = locate(href_list["makeeligible"]) if(!ismob(M)) to_chat(usr, "this can only be used on instances of type /mob.") - var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility)) - if(M.ckey in eli.timeouts) - eli.timeouts -= M.ckey + if(M.ckey in GLOB.client_ghost_timeouts) + GLOB.client_ghost_timeouts -= M.ckey else if(href_list["sendtoprison"]) if(!check_rights(R_ADMIN)) diff --git a/code/modules/admin/verbs/borgpanel.dm b/code/modules/admin/verbs/borgpanel.dm index 8cfd53b300..83f2839438 100644 --- a/code/modules/admin/verbs/borgpanel.dm +++ b/code/modules/admin/verbs/borgpanel.dm @@ -23,8 +23,8 @@ /datum/borgpanel/New(to_user, mob/living/silicon/robot/to_borg) if(!istype(to_borg)) - CRASH("Borg panel is only available for borgs") qdel(src) + CRASH("Borg panel is only available for borgs") user = CLIENT_FROM_VAR(to_user) diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index 39cdf8a5fa..a9f97942a1 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -92,10 +92,8 @@ M.cut_overlays() M.regenerate_icons() -/obj/item/clothing/suit/armor/abductor/vest/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - DeactivateStealth() - -/obj/item/clothing/suit/armor/abductor/vest/IsReflect() +/obj/item/clothing/suit/armor/abductor/vest/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + . = ..() DeactivateStealth() /obj/item/clothing/suit/armor/abductor/vest/ui_action_click() @@ -493,7 +491,7 @@ user.do_attack_animation(L) - if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) + if(L.run_block(src, 0, "[user]'s [src]", ATTACK_TYPE_MELEE, 0, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS) playsound(L, 'sound/weapons/genhit.ogg', 50, TRUE) return FALSE diff --git a/code/modules/antagonists/abductor/machinery/experiment.dm b/code/modules/antagonists/abductor/machinery/experiment.dm index ca6481bcfe..f92cb987d0 100644 --- a/code/modules/antagonists/abductor/machinery/experiment.dm +++ b/code/modules/antagonists/abductor/machinery/experiment.dm @@ -209,7 +209,6 @@ open_machine() SendBack(H) return "Specimen braindead - disposed." - return "ERROR" /obj/machinery/abductor/experiment/proc/SendBack(mob/living/carbon/human/H) diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm b/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm index 3a6b4efedb..98fb69e52c 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm @@ -1,12 +1,6 @@ // INTEGRATION: Adding Procs and Datums to existing "classes" -/mob/living/proc/AmBloodsucker(falseIfInDisguise=FALSE) - // No Datum - if(!mind || !mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) - return FALSE - return TRUE - -/mob/living/proc/HaveBloodsuckerBodyparts(var/displaymessage="") // displaymessage can be something such as "rising from death" for Torpid Sleep. givewarningto is the person receiving messages. +/mob/living/proc/HaveBloodsuckerBodyparts(displaymessage = "") // displaymessage can be something such as "rising from death" for Torpid Sleep. givewarningto is the person receiving messages. if(!getorganslot(ORGAN_SLOT_HEART)) if(displaymessage != "") to_chat(src, "Without a heart, you are incapable of [displaymessage].") @@ -21,33 +15,6 @@ return FALSE return TRUE - - -// GET DAMAGE - - -// Do NOT count the damage on prosthetics for this. -/mob/living/proc/getBruteLoss_nonProsthetic() - return getBruteLoss() - -/mob/living/proc/getFireLoss_nonProsthetic() - return getFireLoss() - -/mob/living/carbon/getBruteLoss_nonProsthetic() - var/amount = 0 - for(var/obj/item/bodypart/BP in bodyparts) - if(BP.status < 2) - amount += BP.brute_dam - return amount - -/mob/living/carbon/getFireLoss_nonProsthetic() - var/amount = 0 - for(var/obj/item/bodypart/BP in bodyparts) - if(BP.status < 2) - amount += BP.burn_dam - return amount - -/mob/living/carbon // EXAMINING /mob/living/carbon/human/proc/ReturnVampExamine(var/mob/viewer) if(!mind || !viewer.mind) diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm index e774cf4250..efccb5591e 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm @@ -12,10 +12,10 @@ /datum/antagonist/bloodsucker/proc/LifeTick()// Should probably run from life.dm, same as handle_changeling, but will be an utter pain to move set waitfor = FALSE // Don't make on_gain() wait for this function to finish. This lets this code run on the side. - var/notice_healing = FALSE + var/notice_healing while(owner && !AmFinalDeath()) // owner.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) == src if(owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_DEATHCOMA)) // Deduct Blood - AddBloodVolume(-0.1) // -.15 (before tick went from 10 to 30, but we also charge more for faking life now) + AddBloodVolume(passive_blood_drain) // -.1 currently if(HandleHealing(1)) // Heal if(notice_healing == FALSE && owner.current.blood_volume > 0) to_chat(owner, "The power of your blood begins knitting your wounds...") @@ -25,7 +25,7 @@ HandleStarving() // Death HandleDeath() // Standard Update update_hud()// Daytime Sleep in Coffin - if (SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker")) + if(SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker")) if(istype(owner.current.loc, /obj/structure/closet/crate/coffin)) Torpor_Begin() // Wait before next pass @@ -39,12 +39,12 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /datum/antagonist/bloodsucker/proc/AddBloodVolume(value) - owner.current.blood_volume = CLAMP(owner.current.blood_volume + value, 0, maxBloodVolume) + owner.current.blood_volume = CLAMP(owner.current.blood_volume + value, 0, max_blood_volume) update_hud() /datum/antagonist/bloodsucker/proc/HandleFeeding(mob/living/carbon/target, mult=1) // mult: SILENT feed is 1/3 the amount - var/blood_taken = min(feedAmount, target.blood_volume) * mult // Starts at 15 (now 8 since we doubled the Feed time) + var/blood_taken = min(feed_amount, target.blood_volume) * mult // Starts at 15 (now 8 since we doubled the Feed time) target.blood_volume -= blood_taken // Simple Animals lose a LOT of blood, and take damage. This is to keep cats, cows, and so forth from giving you insane amounts of blood. if(!ishuman(target)) @@ -82,38 +82,40 @@ /datum/antagonist/bloodsucker/proc/HandleHealing(mult = 1) // NOTE: Mult of 0 is just a TEST to see if we are injured and need to go into Torpor! //It is called from your coffin on close (by you only) + var/actual_regen = regen_rate + additional_regen if(poweron_masquerade == TRUE || owner.current.AmStaked()) return FALSE - owner.current.adjustStaminaLoss(-1.5 + (regenRate * -7) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more. - owner.current.adjustCloneLoss(-0.1 * (regenRate * 2) * mult, 0) - owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (regenRate * 4) * mult) //adjustBrainLoss(-1 * (regenRate * 4) * mult, 0) + if(owner.current.reagents.has_reagent(/datum/reagent/consumable/garlic)) + return FALSE + if(istype(owner.current.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace)) + return FALSE + owner.current.adjustStaminaLoss(-1.5 + (actual_regen * -7) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more. + owner.current.adjustCloneLoss(-0.1 * (actual_regen * 2) * mult, 0) + owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (actual_regen * 4) * mult) // No Bleeding - if(ishuman(owner.current)) //NOTE Current bleeding is horrible, not to count the amount of blood ballistics delete. + /*if(ishuman(owner.current)) //NOTE Current bleeding is horrible, not to count the amount of blood ballistics delete. var/mob/living/carbon/human/H = owner.current - H.bleed_rate = 0 + if(H.bleed_rate > 0) //Only heal bleeding if we are actually bleeding + H.bleed_rate =- 0.5 + actual_regen * 0.2 */ if(iscarbon(owner.current)) // Damage Heal: Do I have damage to ANY bodypart? var/mob/living/carbon/C = owner.current var/costMult = 1 // Coffin makes it cheaper var/fireheal = 0 // BURN: Heal in Coffin while Fakedeath, or when damage above maxhealth (you can never fully heal fire) - var/amInCoffinWhileTorpor = istype(C.loc, /obj/structure/closet/crate/coffin) && (mult == 0 || HAS_TRAIT(C, TRAIT_DEATHCOMA)) // Check for mult 0 OR death coma. (mult 0 means we're testing from coffin) + var/amInCoffinWhileTorpor = istype(C.loc, /obj/structure/closet/crate/coffin) && (mult == 0 || HAS_TRAIT(C, TRAIT_FAKEDEATH)) // Check for mult 0 OR death coma. (mult 0 means we're testing from coffin) if(amInCoffinWhileTorpor) mult *= 4 // Increase multiplier if we're sleeping in a coffin. - fireheal = min(C.getFireLoss_nonProsthetic(), regenRate) // NOTE: Burn damage ONLY heals in torpor. - costMult = 0.25 + fireheal = min(C.getFireLoss(), regen_rate) // NOTE: Burn damage ONLY heals in torpor. C.ExtinguishMob() CureDisabilities() // Extinguish Fire C.remove_all_embedded_objects() // Remove Embedded! owner.current.regenerate_organs() // Heal Organs (will respawn original eyes etc. but we replace right away, next) CheckVampOrgans() // Heart, Eyes - else - if(owner.current.blood_volume <= 0) // No Blood? Lower Mult - mult = 0.25 - // Crit from burn? Lower damage to maximum allowed. - //if (C.getFireLoss() > owner.current.getMaxHealth()) - // fireheal = regenRate / 2 + if(check_limbs(costMult)) + return TRUE + // BRUTE: Always Heal - var/bruteheal = min(C.getBruteLoss_nonProsthetic(), regenRate) - var/toxinheal = min(C.getToxLoss(), regenRate) + var/bruteheal = min(C.getBruteLoss(), actual_regen) + var/toxinheal = min(C.getToxLoss(), actual_regen) // Heal if Damaged if(bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return. if(mult == 0) @@ -127,28 +129,29 @@ //C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above. AddBloodVolume((bruteheal * -0.5 + fireheal * -1 + toxinheal * -0.2) / mult * costMult) // Costs blood to heal return TRUE // Healed! Done for this tick. - if(amInCoffinWhileTorpor) // Limbs? (And I have no other healing) - var/list/missing = owner.current.get_missing_limbs() // Heal Missing - if (missing.len) // Cycle through ALL limbs and regen them! - for (var/targetLimbZone in missing) // 1) Find ONE Limb and regenerate it. - owner.current.regenerate_limb(targetLimbZone, 0) // regenerate_limbs() <--- If you want to EXCLUDE certain parts, do it like this ----> regenerate_limbs(0, list("head")) - var/obj/item/bodypart/L = owner.current.get_bodypart( targetLimbZone ) // 2) Limb returns Damaged - AddBloodVolume(50 * costMult) // Costs blood to heal - L.brute_dam = 60 - to_chat(owner.current, "Your flesh knits as it regrows [L]!") - playsound(owner.current, 'sound/magic/demon_consume.ogg', 50, 1) - // DONE! After regenerating ANY number of limbs, we stop here. - return TRUE - /*else // REMOVED: For now, let's just leave prosthetics on. Maybe you WANT to be a robovamp. - // Remove Prosthetic/False Limb - for(var/obj/item/bodypart/BP in C.bodyparts) - message_admins("T1: [BP] ") - if (istype(BP) && BP.status == 2) - message_admins("T2: [BP] ") - BP.drop_limb() - return TRUE */ - // NOTE: Limbs have a "status", like their hosts "stat". 2 is dead (aka Prosthetic). 1 seems to be idle/alive.*/ - return FALSE + + + +/datum/antagonist/bloodsucker/proc/check_limbs(costMult) + var/limb_regen_cost = 50 * costMult + var/mob/living/carbon/C = owner.current + var/list/missing = C.get_missing_limbs() + if(missing.len && C.blood_volume < limb_regen_cost + 5) + return FALSE + for(var/targetLimbZone in missing) // 1) Find ONE Limb and regenerate it. + C.regenerate_limb(targetLimbZone, FALSE) // regenerate_limbs() <--- If you want to EXCLUDE certain parts, do it like this ----> regenerate_limbs(0, list("head")) + AddBloodVolume(50) + var/obj/item/bodypart/L = C.get_bodypart(targetLimbZone) // 2) Limb returns Damaged + L.brute_dam = 60 + to_chat(C, "Your flesh knits as it regrows your [L]!") + playsound(C, 'sound/magic/demon_consume.ogg', 50, TRUE) + return TRUE + /*for(var/obj/item/bodypart/BP in C.bodyparts) + if(!istype(BP) && !BP.status == 2) + return FALSE + to_chat(C, "Your body expels the [BP]!") + BP.drop_limb() + return TRUE */ /datum/antagonist/bloodsucker/proc/CureDisabilities() var/mob/living/carbon/C = owner.current @@ -179,7 +182,16 @@ 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.nutrition = min(owner.current.blood_volume, NUTRITION_LEVEL_FED) // <-- 350 //NUTRITION_LEVEL_FULL + owner.current.nutrition = clamp(owner.current.blood_volume, 545, 0) //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 + else if(owner.current.blood_volume < BLOOD_VOLUME_NORMAL) + additional_regen = 0.3 + else if(owner.current.blood_volume < BLOOD_VOLUME_OKAY) + additional_regen = 0.2 + else if(owner.current.blood_volume < BLOOD_VOLUME_BAD) + additional_regen = 0.1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // DEATH @@ -189,7 +201,7 @@ /datum/antagonist/bloodsucker/proc/HandleDeath() // FINAL DEATH // Fire Damage? (above double health) - if(owner.current.getFireLoss_nonProsthetic() >= owner.current.maxHealth * 2.5) + if(owner.current.getFireLoss() >= owner.current.maxHealth * 3) FinalDeath() return // Staked while "Temp Death" or Asleep @@ -209,8 +221,8 @@ // for (var/datum/action/bloodsucker/masquerade/P in powers) // P.Deactivate() // TEMP DEATH - var/total_brute = owner.current.getBruteLoss_nonProsthetic() - var/total_burn = owner.current.getFireLoss_nonProsthetic() + var/total_brute = owner.current.getBruteLoss() + var/total_burn = owner.current.getFireLoss() var/total_toxloss = owner.current.getToxLoss() //This is neater than just putting it in total_damage var/total_damage = total_brute + total_burn + total_toxloss // Died? Convert to Torpor (fake death) @@ -218,27 +230,25 @@ Torpor_Begin() to_chat(owner, "Your immortal body will not yet relinquish your soul to the abyss. You enter Torpor.") sleep(30) //To avoid spam - if (poweron_masquerade == TRUE) + if(poweron_masquerade == TRUE) to_chat(owner, "Your wounds will not heal until you disable the Masquerade power.") // End Torpor: else // No damage, OR toxin healed AND brute healed and NOT in coffin (since you cannot heal burn) if(total_damage <= 0 || total_toxloss <= 0 && total_brute <= 0 && !istype(owner.current.loc, /obj/structure/closet/crate/coffin)) // Not Daytime, Not in Torpor - if(!SSticker.mode.is_daylight() && HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker")) + if(!SSticker.mode.is_daylight() && HAS_TRAIT_FROM(owner.current, TRAIT_FAKEDEATH, "bloodsucker")) Torpor_End() // Fake Unconscious if(poweron_masquerade == TRUE && total_damage >= owner.current.getMaxHealth() - HEALTH_THRESHOLD_FULLCRIT) - owner.current.Unconscious(20,1) - //HEALTH_THRESHOLD_CRIT 0 - //HEALTH_THRESHOLD_FULLCRIT -30 - //HEALTH_THRESHOLD_DEAD -100 + owner.current.Unconscious(20, 1) -/datum/antagonist/bloodsucker/proc/Torpor_Begin(amInCoffin=FALSE) +/datum/antagonist/bloodsucker/proc/Torpor_Begin(amInCoffin = FALSE) owner.current.stat = UNCONSCIOUS - owner.current.fakedeath("bloodsucker") // Come after UNCONSCIOUS or else it fails + owner.current.apply_status_effect(STATUS_EFFECT_UNCONSCIOUS) + ADD_TRAIT(owner.current, TRAIT_FAKEDEATH, "bloodsucker") // Come after UNCONSCIOUS or else it fails ADD_TRAIT(owner.current, TRAIT_NODEATH, "bloodsucker") // Without this, you'll just keep dying while you recover. - ADD_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") // So you can heal in 0 G. otherwise you just...heal forever. - ADD_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") // So you can heal in 0 G. otherwise you just...heal forever. + ADD_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") // So you can heal in space. Otherwise you just...heal forever. + ADD_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") // Visuals owner.current.update_sight() owner.current.reload_fullscreen() @@ -247,10 +257,10 @@ if(power.active && !power.can_use_in_torpor) power.DeactivatePower() - /datum/antagonist/bloodsucker/proc/Torpor_End() owner.current.stat = SOFT_CRIT - owner.current.cure_fakedeath("bloodsucker") // Come after SOFT_CRIT or else it fails + owner.current.remove_status_effect(STATUS_EFFECT_UNCONSCIOUS) + REMOVE_TRAIT(owner.current, TRAIT_FAKEDEATH, "bloodsucker") REMOVE_TRAIT(owner.current, TRAIT_NODEATH, "bloodsucker") REMOVE_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") REMOVE_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") @@ -283,18 +293,19 @@ // Free my Vassals! FreeAllVassals() // Elders get Dusted - if(vamplevel >= 4) // (vamptitle) + if(bloodsucker_level >= 4) // (bloodsucker_title) owner.current.visible_message("[owner.current]'s skin crackles and dries, their skin and bones withering to dust. A hollow cry whips from what is now a sandy pile of remains.", \ "Your soul escapes your withering body as the abyss welcomes you to your Final Death.", \ "You hear a dry, crackling sound.") + sleep(50) owner.current.dust() // Fledglings get Gibbed else owner.current.visible_message("[owner.current]'s skin bursts forth in a spray of gore and detritus. A horrible cry echoes from what is now a wet pile of decaying meat.", \ "Your soul escapes your withering body as the abyss welcomes you to your Final Death.", \ "You hear a wet, bursting sound.") - owner.current.gib(TRUE, FALSE, FALSE)//Brain cloning is wierd and allows hellbounds. Lets destroy the brain for safety. - playsound(owner.current.loc, 'sound/effects/tendril_destroyed.ogg', 40, 1) + owner.current.gib(TRUE, FALSE, FALSE) //Brain cloning is wierd and allows hellbounds. Lets destroy the brain for safety. + playsound(owner.current, 'sound/effects/tendril_destroyed.ogg', 40, TRUE) @@ -304,15 +315,15 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/mob/proc/CheckBloodsuckerEatFood(var/food_nutrition) - if (!isliving(src)) +/mob/proc/CheckBloodsuckerEatFood(food_nutrition) + if(!isliving(src)) return var/mob/living/L = src - if(!L.AmBloodsucker()) + if(!AmBloodsucker(L)) return - // We're a vamp? Try to eat food... - var/datum/antagonist/bloodsucker/bloodsuckerdatum = mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - bloodsuckerdatum.handle_eat_human_food(food_nutrition) + // We're a bloodsucker? Try to eat food... + var/datum/antagonist/bloodsucker/B = L.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + B.handle_eat_human_food(food_nutrition) /datum/antagonist/bloodsucker/proc/handle_eat_human_food(food_nutrition, puke_blood = TRUE, masquerade_override) // Called from snacks.dm and drinks.dm diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm index 507e1f2739..5c4b1f2b9f 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm @@ -93,6 +93,14 @@ if(display_error) to_chat(owner, "You have a stake in your chest! Your powers are useless.") return FALSE + if(istype(owner.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace)) + if(display_error) + to_chat(owner, "") + return FALSE + if(owner.reagents?.has_reagent(/datum/reagent/consumable/garlic)) + if(display_error) + to_chat(owner, "Garlic in your blood is interfering with your powers!") + return FALSE // Incap? if(must_be_capacitated) var/mob/living/L = owner diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm b/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm index 263f91a9a6..b7d98c6783 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm @@ -141,23 +141,23 @@ if(!bloodsuckerdatum.warn_sun_locker) to_chat(M, "Your skin sizzles. The [M.current.loc] doesn't protect well against UV bombardment.") bloodsuckerdatum.warn_sun_locker = TRUE - M.current.adjustFireLoss(0.5 + bloodsuckerdatum.vamplevel / 2) // M.current.fireloss += 0.5 + bloodsuckerdatum.vamplevel / 2 // Do DIRECT damage. Being spaced was causing this to not occur. setFireLoss(bloodsuckerdatum.vamplevel) + M.current.adjustFireLoss(0.5 + bloodsuckerdatum.bloodsucker_level / 2) // M.current.fireloss += 0.5 + bloodsuckerdatum.bloodsucker_level / 2 // Do DIRECT damage. Being spaced was causing this to not occur. setFireLoss(bloodsuckerdatum.bloodsucker_level) M.current.updatehealth() SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_1) // Out in the Open? Buh Bye else if(!bloodsuckerdatum.warn_sun_burn) - if(bloodsuckerdatum.vamplevel > 0) + if(bloodsuckerdatum.bloodsucker_level > 0) to_chat(M, "The solar flare sets your skin ablaze!") else to_chat(M, "The solar flare scalds your neophyte skin!") bloodsuckerdatum.warn_sun_burn = TRUE if(M.current.fire_stacks <= 0) M.current.fire_stacks = 0 - if(bloodsuckerdatum.vamplevel > 0) - M.current.adjust_fire_stacks(0.2 + bloodsuckerdatum.vamplevel / 10) + if(bloodsuckerdatum.bloodsucker_level > 0) + M.current.adjust_fire_stacks(0.2 + bloodsuckerdatum.bloodsucker_level / 10) M.current.IgniteMob() - M.current.adjustFireLoss(2 + bloodsuckerdatum.vamplevel) // M.current.fireloss += 2 + bloodsuckerdatum.vamplevel // Do DIRECT damage. Being spaced was causing this to not occur. //setFireLoss(2 + bloodsuckerdatum.vamplevel) + M.current.adjustFireLoss(2 + bloodsuckerdatum.bloodsucker_level) // M.current.fireloss += 2 + bloodsuckerdatum.bloodsucker_level // Do DIRECT damage. Being spaced was causing this to not occur. //setFireLoss(2 + bloodsuckerdatum.bloodsucker_level) M.current.updatehealth() SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_2) diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 94c62df696..946be31ed6 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -8,9 +8,9 @@ job_rank = ROLE_BLOODSUCKER threat = 5 // NAME - var/vampname // My Dracula name - var/vamptitle // My Dracula title - var/vampreputation // My "Surname" or description of my deeds + var/bloodsucker_name // My Dracula style name + var/bloodsucker_title // My Dracula style title + var/bloodsucker_reputation // My "Surname" or description of my deeds // CLAN var/datum/team/vampireclan/clan var/list/datum/antagonist/vassal/vassals = list()// Vassals under my control. Periodically remove the dead ones. @@ -20,35 +20,33 @@ var/poweron_feed = FALSE // Am I feeding? var/poweron_masquerade = FALSE // STATS - var/vamplevel = 0 - var/vamplevel_unspent = 1 - var/regenRate = 0.4 // How many points of Brute do I heal per tick? - var/feedAmount = 15 // Amount of blood drawn from a target per tick. - var/maxBloodVolume = 600 // Maximum blood a Vamp can hold via feeding. // BLOOD_VOLUME_NORMAL 550 // BLOOD_VOLUME_SAFE 475 //BLOOD_VOLUME_OKAY 336 //BLOOD_VOLUME_BAD 224 // BLOOD_VOLUME_SURVIVE 122 + var/bloodsucker_level + var/bloodsucker_level_unspent = 1 + var/regen_rate = 0.3 // How fast do I regenerate? + var/additional_regen // How much additional blood regen we gain from bonuses such as high blood. + var/feed_amount = 15 // Amount of blood drawn from a target per tick. + var/max_blood_volume = 600 // Maximum blood a Vamp can hold via feeding. // OBJECTIVES var/list/datum/objective/objectives_given = list() // For removal if needed. var/area/lair var/obj/structure/closet/crate/coffin // TRACKING - var/foodInGut = 0 // How much food to throw up later. You shouldn't have eaten that. - var/warn_sun_locker = FALSE // So we only get the locker burn message once per day. - var/warn_sun_burn = FALSE // So we only get the sun burn message once per day. - var/had_toxlover = FALSE + var/foodInGut // How much food to throw up later. You shouldn't have eaten that. + var/warn_sun_locker // So we only get the locker burn message once per day. + var/warn_sun_burn // So we only get the sun burn message once per day. + var/had_toxlover var/level_bloodcost + 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) - // NOTES: TRAIT_AGEUSIA <-- Doesn't like flavors. - // REMOVED: TRAIT_NODEATH - // TO ADD: - //var/static/list/defaultOrgans = list (/obj/item/organ/heart/vampheart,/obj/item/organ/heart/vampeyes) /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) SSticker.mode.check_start_sunlight()// Start Sunlight? (if first Vamp) SelectFirstName()// Name & Title - SelectTitle(am_fledgling=TRUE) // If I have a creator, then set as Fledgling. - SelectReputation(am_fledgling=TRUE) + SelectTitle(am_fledgling = TRUE) // If I have a creator, then set as Fledgling. + SelectReputation(am_fledgling = TRUE) AssignStarterPowersAndStats()// Give Powers & Stats forge_bloodsucker_objectives()// Objectives & Team update_bloodsucker_icons_added(owner.current, "bloodsucker") // Add Antag HUD @@ -68,18 +66,18 @@ /datum/antagonist/bloodsucker/greet() var/fullname = ReturnFullName(TRUE) - to_chat(owner, "You are [fullname], a bloodsucking vampire!
") + to_chat(owner, "You are [fullname], a strain of vampire dubbed bloodsucker!
") owner.announce_objectives() to_chat(owner, "* You regenerate your health slowly, you're weak to fire, and you depend on blood to survive. Allow your stolen blood to run too low, and you will find yourself at \ risk of being discovered!
") //to_chat(owner, "As an immortal, your power is linked to your age. The older you grow, the more abilities you will have access to.") - var/vamp_greet - vamp_greet += "* Other Bloodsuckers are not necessarily your friends, but your survival may depend on cooperation. Betray them at your own discretion and peril.
" - vamp_greet += "* Use \",b\" to speak your ancient Bloodsucker language.
" - vamp_greet += "Bloodsucker Tip: Rest in a Coffin to claim it, and that area, as your lair.
" - vamp_greet += "Bloodsucker Tip: Fear the daylight! Solar flares will bombard the station periodically, and only your coffin can guarantee your safety.
" - vamp_greet += "Bloodsucker Tip: You wont loose blood if you are unconcious or sleeping. Use this to your advantage to conserve blood.
" - to_chat(owner, vamp_greet) + var/bloodsucker_greet + bloodsucker_greet += "* Other Bloodsuckers are not necessarily your friends, but your survival may depend on cooperation. Betray them at your own discretion and peril.
" + bloodsucker_greet += "* Use \",b\" to speak your ancient Bloodsucker language.
" + bloodsucker_greet += "Bloodsucker Tip: Rest in a Coffin to claim it, and that area, as your lair.
" + bloodsucker_greet += "Bloodsucker Tip: Fear the daylight! Solar flares will bombard the station periodically, and only your coffin can guarantee your safety.
" + bloodsucker_greet += "Bloodsucker Tip: You wont loose blood if you are unconcious or sleeping. Use this to your advantage to conserve blood.
" + to_chat(owner, bloodsucker_greet) owner.current.playsound_local(null, 'sound/bloodsucker/BloodsuckerAlert.ogg', 100, FALSE, pressure_affected = FALSE) antag_memory += "Although you were born a mortal, in un-death you earned the name [fullname].
" @@ -92,13 +90,13 @@ owner.current.blood_volume = max(owner.current.blood_volume,BLOOD_VOLUME_SAFE) /datum/antagonist/bloodsucker/threat() - return ..()+3*vamplevel + return ..() + 3 * bloodsucker_level /datum/antagonist/bloodsucker/proc/SelectFirstName() // Names (EVERYONE gets one)) if(owner.current.gender == MALE) - vampname = pick("Desmond","Rudolph","Dracul","Vlad","Pyotr","Gregor","Cristian","Christoff","Marcu","Andrei","Constantin","Gheorghe","Grigore","Ilie","Iacob","Luca","Mihail","Pavel","Vasile","Octavian","Sorin", \ + bloodsucker_name = pick("Desmond","Rudolph","Dracul","Vlad","Pyotr","Gregor","Cristian","Christoff","Marcu","Andrei","Constantin","Gheorghe","Grigore","Ilie","Iacob","Luca","Mihail","Pavel","Vasile","Octavian","Sorin", \ "Sveyn","Aurel","Alexe","Iustin","Theodor","Dimitrie","Octav","Damien","Magnus","Caine","Abel", // Romanian/Ancient "Lucius","Gaius","Otho","Balbinus","Arcadius","Romanos","Alexios","Vitellius", // Latin "Melanthus","Teuthras","Orchamus","Amyntor","Axion", // Greek @@ -106,7 +104,7 @@ "Dio") else - vampname = pick("Islana","Tyrra","Greganna","Pytra","Hilda","Andra","Crina","Viorela","Viorica","Anemona","Camelia","Narcisa","Sorina","Alessia","Sophia","Gladda","Arcana","Morgan","Lasarra","Ioana","Elena", \ + bloodsucker_name = pick("Islana","Tyrra","Greganna","Pytra","Hilda","Andra","Crina","Viorela","Viorica","Anemona","Camelia","Narcisa","Sorina","Alessia","Sophia","Gladda","Arcana","Morgan","Lasarra","Ioana","Elena", \ "Alina","Rodica","Teodora","Denisa","Mihaela","Svetla","Stefania","Diyana","Kelssa","Lilith", // Romanian/Ancient "Alexia","Athanasia","Callista","Karena","Nephele","Scylla","Ursa", // Latin "Alcestis","Damaris","Elisavet","Khthonia","Teodora", // Greek @@ -114,57 +112,57 @@ /datum/antagonist/bloodsucker/proc/SelectTitle(am_fledgling = 0, forced = FALSE) // Already have Title - if (!forced && vamptitle != null) + if(!forced && bloodsucker_title != null) return // Titles [Master] - if (!am_fledgling) + if(!am_fledgling) if(owner.current.gender == MALE) - vamptitle = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master") + bloodsucker_title = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master") else - vamptitle = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress") + bloodsucker_title = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress") to_chat(owner, "You have earned a title! You are now known as [ReturnFullName(TRUE)]!") // Titles [Fledgling] else - vamptitle = null + bloodsucker_title = null /datum/antagonist/bloodsucker/proc/SelectReputation(am_fledgling = 0, forced=FALSE) // Already have Reputation - if(!forced && vampreputation != null) + if(!forced && bloodsucker_reputation != null) return // Reputations [Master] if(!am_fledgling) - vampreputation = pick("Butcher","Blood Fiend","Crimson","Red","Black","Terror","Nightman","Feared","Ravenous","Fiend","Malevolent","Wicked","Ancient","Plaguebringer","Sinister","Forgotten","Wretched","Baleful", \ + bloodsucker_reputation = pick("Butcher","Blood Fiend","Crimson","Red","Black","Terror","Nightman","Feared","Ravenous","Fiend","Malevolent","Wicked","Ancient","Plaguebringer","Sinister","Forgotten","Wretched","Baleful", \ "Inqisitor","Harvester","Reviled","Robust","Betrayer","Destructor","Damned","Accursed","Terrible","Vicious","Profane","Vile","Depraved","Foul","Slayer","Manslayer","Sovereign","Slaughterer", \ "Forsaken","Mad","Dragon","Savage","Villainous","Nefarious","Inquisitor","Marauder","Horrible","Immortal","Undying","Overlord","Corrupt","Hellspawn","Tyrant","Sanguineous") if(owner.current.gender == MALE) if(prob(10)) // Gender override - vampreputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King") + bloodsucker_reputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King") else if(prob(10)) // Gender override - vampreputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen") + bloodsucker_reputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen") to_chat(owner, "You have earned a reputation! You are now known as [ReturnFullName(TRUE)]!") // Reputations [Fledgling] else - vampreputation = pick ("Crude","Callow","Unlearned","Neophyte","Novice","Unseasoned","Fledgling","Young","Neonate","Scrapling","Untested","Unproven","Unknown","Newly Risen","Born","Scavenger","Unknowing",\ + bloodsucker_reputation = pick ("Crude","Callow","Unlearned","Neophyte","Novice","Unseasoned","Fledgling","Young","Neonate","Scrapling","Untested","Unproven","Unknown","Newly Risen","Born","Scavenger","Unknowing",\ "Unspoiled","Disgraced","Defrocked","Shamed","Meek","Timid","Broken")//,"Fresh") /datum/antagonist/bloodsucker/proc/AmFledgling() - return !vamptitle + return !bloodsucker_title /datum/antagonist/bloodsucker/proc/ReturnFullName(var/include_rep=0) var/fullname // Name First - fullname = (vampname ? vampname : owner.current.name) + fullname = (bloodsucker_name ? bloodsucker_name : owner.current.name) // Title - if(vamptitle) - fullname = vamptitle + " " + fullname + if(bloodsucker_title) + fullname = bloodsucker_title + " " + fullname // Rep - if(include_rep && vampreputation) - fullname = fullname + " the " + vampreputation + if(include_rep && bloodsucker_reputation) + fullname = fullname + " the " + bloodsucker_reputation return fullname @@ -199,15 +197,12 @@ var/mob/living/carbon/human/H = owner.current var/datum/species/S = H.dna.species // Make Changes - H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank! + H.physiology.brute_mod *= 0.8 H.physiology.cold_mod = 0 H.physiology.stun_mod *= 0.5 H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1 - //S.heatmod += 0.5 // Heat shouldn't affect. Only Fire. - //S.punchstunthreshold = 8 //damage at which punches from this race will stun 9 S.punchdamagelow += 1 //lowest possible punch damage 0 S.punchdamagehigh += 1 //highest possible punch damage 9 - // Clown if(istype(H) && owner.assigned_role == "Clown") H.dna.remove_mutation(CLOWNMUT) to_chat(H, "As a vampiric clown, you are no longer a danger to yourself. Your nature is subdued.") @@ -215,8 +210,6 @@ CheckVampOrgans() // Heart, Eyes // Language owner.current.grant_language(/datum/language/vampiric) - // Soul - //owner.current.hellbound = TRUE Causes wierd stuff owner.hasSoul = FALSE // If false, renders the character unable to sell their soul. owner.isholy = FALSE // is this person a chaplain or admin role allowed to use bibles // Disabilities @@ -248,7 +241,6 @@ // Clown if(istype(H) && owner.assigned_role == "Clown") H.dna.add_mutation(CLOWNMUT) - // NOTE: Use initial() to return things to default! // Physiology owner.current.regenerate_organs() // Update Health @@ -264,13 +256,13 @@ set waitfor = FALSE if(!owner || !owner.current) return - vamplevel_unspent ++ + bloodsucker_level_unspent ++ // Spend Rank Immediately? if(istype(owner.current.loc, /obj/structure/closet/crate/coffin)) SpendRank() else to_chat(owner, "You have grown more ancient! Sleep in a coffin that you have claimed to thicken your blood and become more powerful.") - if(vamplevel_unspent >= 2) + if(bloodsucker_level_unspent >= 2) to_chat(owner, "Bloodsucker Tip: If you cannot find or steal a coffin to use, you can build one from wooden planks.
") /datum/antagonist/bloodsucker/proc/LevelUpPowers() @@ -279,10 +271,10 @@ /datum/antagonist/bloodsucker/proc/SpendRank() set waitfor = FALSE - if(vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current)) + if(bloodsucker_level_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current)) return var/mob/living/L = owner.current - level_bloodcost = maxBloodVolume * 0.2 + level_bloodcost = max_blood_volume * 0.2 //If the blood volume of the bloodsucker is lower than the cost to level up, return and inform the bloodsucker //TODO: Make this into a radial, or perhaps a tgui next UI @@ -298,7 +290,7 @@ if(options.len > 1) var/choice = input(owner.current, "You have the opportunity to grow more ancient at the cost of [level_bloodcost] units of blood. Select a power to advance your Rank.", "Your Blood Thickens...") in options // Cheat-Safety: Can't keep opening/closing coffin to spam levels - if(vamplevel_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal. + if(bloodsucker_level_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal. return if(!istype(owner.current.loc, /obj/structure/closet/crate/coffin)) to_chat(owner.current, "Return to your coffin to advance your Rank.") @@ -329,20 +321,20 @@ // More Health owner.current.setMaxHealth(owner.current.maxHealth + 10) // Vamp Stats - regenRate += 0.05 // Points of brute healed (starts at 0.3) - feedAmount += 2 // Increase how quickly I munch down vics (15) - maxBloodVolume += 100 // Increase my max blood (600) + regen_rate += 0.05 // Points of brute healed (starts at 0.3) + feed_amount += 2 // Increase how quickly I munch down vics (15) + max_blood_volume += 100 // Increase my max blood (600) ///////// - vamplevel ++ - vamplevel_unspent -- + bloodsucker_level ++ + bloodsucker_level_unspent -- // Assign True Reputation - if(vamplevel == 4) + if(bloodsucker_level == 4) SelectReputation(am_fledgling = FALSE, forced = TRUE) - to_chat(owner.current, "You are now a rank [vamplevel] Bloodsucker. Your strength, health, feed rate, regen rate, and maximum blood have all increased!") + to_chat(owner.current, "You are now a rank [bloodsucker_level] Bloodsucker. Your strength, health, feed rate, regen rate, can have up to [bloodsucker_level - count_vassals(owner.current.mind)] vassals, and maximum blood have all increased!") to_chat(owner.current, "Your existing powers have all ranked up as well!") update_hud(TRUE) - owner.current.playsound_local(null, 'sound/effects/pope_entry.ogg', 25, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head. + owner.current.playsound_local(null, 'sound/effects/pope_entry.ogg', 25, TRUE, pressure_affected = FALSE) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -654,13 +646,13 @@ var/datum/antagonist/vassal/mob_V = M.mind.has_antag_datum(ANTAG_DATUM_VASSAL) // Check 2) If they are a BLOODSUCKER, then are they my Master? if (mob_V && atom_B == mob_V.master) - return TRUE // SUCCESS! + return TRUE // Check 3) If I am a BLOODSUCKER, then are they my Vassal? if (mob_B && atom_V && (atom_V in mob_B.vassals)) - return TRUE // SUCCESS! + return TRUE // Check 4) If we are both VASSAL, then do we have the same master? if (atom_V && mob_V && atom_V.master == mob_V.master) - return TRUE // SUCCESS! + return TRUE return FALSE @@ -705,10 +697,10 @@ // Update Rank Counter if(owner.current.hud_used.vamprank_display) - var/valuecolor = vamplevel_unspent ? "#FFFF00" : "#FF0000" - owner.current.hud_used.vamprank_display.update_counter(vamplevel, valuecolor) + var/valuecolor = bloodsucker_level_unspent ? "#FFFF00" : "#FF0000" + owner.current.hud_used.vamprank_display.update_counter(bloodsucker_level, valuecolor) if(updateRank) // Only change icon on special request. - owner.current.hud_used.vamprank_display.icon_state = (vamplevel_unspent > 0) ? "rank_up" : "rank" + owner.current.hud_used.vamprank_display.icon_state = (bloodsucker_level_unspent > 0) ? "rank_up" : "rank" /obj/screen/bloodsucker @@ -718,12 +710,12 @@ invisibility = INVISIBILITY_ABSTRACT /obj/screen/bloodsucker/proc/update_counter(value, valuecolor) - invisibility = 0 // Make Visible + invisibility = 0 -/obj/screen/bloodsucker/blood_counter // NOTE: Look up /obj/screen/devil/soul_counter in _onclick / hud / human.dm - icon = 'icons/mob/actions/bloodsucker.dmi'//'icons/mob/screen_gen.dmi' +/obj/screen/bloodsucker/blood_counter + icon = 'icons/mob/actions/bloodsucker.dmi' name = "Blood Consumed" - icon_state = "blood_display"//"power_display" + icon_state = "blood_display" screen_loc = ui_blood_display /obj/screen/bloodsucker/blood_counter/update_counter(value, valuecolor) @@ -748,22 +740,27 @@ /datum/antagonist/bloodsucker/proc/update_sunlight(value, amDay = FALSE) // No Hud? Get out. - if (!owner.current.hud_used) + if(!owner.current.hud_used) return // Update Sun Time - if (owner.current.hud_used.sunlight_display) + if(owner.current.hud_used.sunlight_display) var/valuecolor = "#BBBBFF" - if (amDay) + if(amDay) valuecolor = "#FF5555" else if(value <= 25) valuecolor = "#FFCCCC" else if(value < 10) valuecolor = "#FF5555" - var/value_string = (value >= 60) ? "[round(value / 60, 1)] m" : "[round(value,1)] s" + var/value_string = (value >= 60) ? "[round(value / 60, 1)] m" : "[round(value, 1)] s" owner.current.hud_used.sunlight_display.update_counter( value_string, valuecolor ) owner.current.hud_used.sunlight_display.icon_state = "sunlight_" + (amDay ? "day":"night") /obj/screen/bloodsucker/sunlight_counter/update_counter(value, valuecolor) ..() - maptext = "
[value]
" + maptext = "
[value]
" + +/datum/antagonist/bloodsucker/proc/count_vassals(datum/mind/master) + var/datum/antagonist/bloodsucker/B = master.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + var/vassal_amount = B.vassals.len + return vassal_amount diff --git a/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm b/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm index e4e26fe034..640c53946f 100644 --- a/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm +++ b/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm @@ -5,7 +5,8 @@ var/obj/item/organ/O // Heart O = owner.current.getorganslot(ORGAN_SLOT_HEART) - if(!istype(O, /obj/item/organ/heart/vampheart)) + + if(!istype(O, /obj/item/organ/heart/vampheart) && !istype(O, /obj/item/organ/heart/demon)) qdel(O) var/obj/item/organ/heart/vampheart/H = new H.Insert(owner.current) diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm index a8925dfb7b..7998a33c7b 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm @@ -115,13 +115,15 @@ qdel(src) /obj/structure/bloodsucker/vassalrack/examine(mob/user) + var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) . = ..() - if(isvamp(user) || isobserver(user)) + if(B || isobserver(user)) . += {"This is the vassal rack, which allows you to thrall crewmembers into loyal minions in your service."} . += {"You need to first secure the vassal rack by clicking on it while it is in your lair."} . += {"Simply click and hold on a victim, and then drag their sprite on the vassal rack. Alt click on the vassal rack to unbuckle them."} . += {"Make sure that the victim is handcuffed, or else they can simply run away or resist, as the process is not instant."} . += {"To convert the victim, simply click on the vassal rack itself. Sharp weapons work faster than other tools."} + . += {" You have only the power for [B.bloodsucker_level - B.count_vassals(user.mind)] vassals"} /* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL) . += {"This is the vassal rack, which allows your master to thrall crewmembers into his minions.\n Aid your master in bringing their victims here and keeping them secure.\n @@ -130,7 +132,7 @@ /obj/structure/bloodsucker/vassalrack/MouseDrop_T(atom/movable/O, mob/user) if(!O.Adjacent(src) || O == user || !isliving(O) || !isliving(user) || useLock || has_buckled_mobs() || user.incapacitated()) return - if(!anchored && isvamp(user)) + if(!anchored && AmBloodsucker(user)) to_chat(user, "Until this rack is secured in place, it cannot serve its purpose.") return // PULL TARGET: Remember if I was pullin this guy, so we can restore this @@ -183,7 +185,7 @@ /obj/structure/bloodsucker/vassalrack/user_unbuckle_mob(mob/living/M, mob/user) // Attempt Unbuckle - if(!isvamp(user)) + if(!AmBloodsucker(user)) if(M == user) M.visible_message("[user] tries to release themself from the rack!",\ "You attempt to release yourself from the rack!") // For sound if not seen --> "You hear a squishy wet noise.") @@ -222,15 +224,15 @@ // Go away. Torturing. if(useLock) return - var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) // CHECK ONE: Am I claiming this? Is it in the right place? - if(istype(bloodsuckerdatum) && !owner) - if(!bloodsuckerdatum.lair) + if(istype(B) && !owner) + if(!B.lair) to_chat(user, "You don't have a lair. Claim a coffin to make that location your lair.") - if(bloodsuckerdatum.lair != get_area(src)) - to_chat(user, "You may only activate this structure in your lair: [bloodsuckerdatum.lair].") + if(B.lair != get_area(src)) + to_chat(user, "You may only activate this structure in your lair: [B.lair].") return - switch(alert(user,"Do you wish to afix this structure here? Be aware you wont be able to unsecure it anymore","Secure [src]","Yes", "No")) + switch(alert(user,"Do you wish to afix this structure here? Be aware you wont be able to unsecure it anymore", "Secure [src]", "Yes", "No")) if("Yes") owner = user density = FALSE @@ -241,27 +243,31 @@ return // CHECK TWO: Am I a non-bloodsucker? var/mob/living/carbon/C = pick(buckled_mobs) - if(!istype(bloodsuckerdatum)) + if(!istype(B)) // Try to release this guy user_unbuckle_mob(C, user) return // Bloodsucker Owner! Let the boy go. if(C.mind) - var/datum/antagonist/vassal/vassaldatum = C.mind.has_antag_datum(ANTAG_DATUM_VASSAL) - if(istype(vassaldatum) && vassaldatum.master == bloodsuckerdatum || C.stat >= DEAD) + var/datum/antagonist/vassal/V = C.mind.has_antag_datum(ANTAG_DATUM_VASSAL) + if(istype(V) && V.master == B || C.stat >= DEAD) unbuckle_mob(C) useLock = FALSE // Failsafe return // Just torture the boy torture_victim(user, C) +#define CONVERT_COST 150 + /obj/structure/bloodsucker/vassalrack/proc/torture_victim(mob/living/user, mob/living/target) - var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) // Check Bloodmob/living/M, force = FALSE, check_loc = TRUE - var/convert_cost = 200 + 200 * bloodsuckerdatum.vassals - if(user.blood_volume < convert_cost + 5) + if(user.blood_volume < CONVERT_COST + 5) to_chat(user, "You don't have enough blood to initiate the Dark Communion with [target].") return + if(B.count_vassals(user.mind) > B.bloodsucker_level) + to_chat(user, "Your power is yet too weak to bring more vassals under your control....") + return // Prep... useLock = TRUE // Step One: Tick Down Conversion from 3 to 0 @@ -302,12 +308,13 @@ useLock = FALSE return // Check: Blood - if(user.blood_volume < convert_cost) - to_chat(user, "You don't have enough blood to initiate the Dark Communion with [target], you need [convert_cost - user.blood_volume] units more!") + if(user.blood_volume < CONVERT_COST) + to_chat(user, "You don't have enough blood to initiate the Dark Communion with [target], you need [CONVERT_COST - user.blood_volume] units more!") useLock = FALSE return - bloodsuckerdatum.AddBloodVolume(-convert_cost) - target.add_mob_blood(user) + B.AddBloodVolume(-CONVERT_COST) + target.add_mob_blood(user, "Youve used [CONVERT_COST] amount of blood to gain a new vassal!") + to_chat(user, ) user.visible_message("[user] marks a bloody smear on [target]'s forehead and puts a wrist up to [target.p_their()] mouth!", \ "You paint a bloody marking across [target]'s forehead, place your wrist to [target.p_their()] mouth, and subject [target.p_them()] to the Dark Communion.") if(!do_mob(user, src, 50)) @@ -315,21 +322,22 @@ useLock = FALSE return // Convert to Vassal! - if(bloodsuckerdatum && bloodsuckerdatum.attempt_turn_vassal(target)) + if(B && B.attempt_turn_vassal(target)) //remove_loyalties(target) // In case of Mindshield, or appropriate Antag (Traitor, Internal, etc) //if (!target.buckled) // to_chat(user, "The ritual has been interrupted!") // useLock = FALSE // return - user.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head. - target.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head. - target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head. + user.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE) + target.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE) + target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE) target.Jitter(25) target.emote("laugh") //remove_victim(target) // Remove on CLICK ONLY! useLock = FALSE -/obj/structure/bloodsucker/vassalrack/proc/do_torture(mob/living/user, mob/living/target, mult=1) +#undef CONVERT_COST +/obj/structure/bloodsucker/vassalrack/proc/do_torture(mob/living/user, mob/living/target, mult = 1) var/torture_time = 15 // Fifteen seconds if you aren't using anything. Shorter with weapons and such. var/torture_dmg_brute = 2 var/torture_dmg_burn = 0 @@ -454,7 +462,7 @@ /obj/structure/bloodsucker/candelabrum/examine(mob/user) . = ..() - if((isvamp()) || isobserver(user)) + if((AmBloodsucker(user)) || isobserver(user)) . += {"This is a magical candle which drains at the sanity of mortals who are not under your command while it is active."} . += {"You can alt click on it from any range to turn it on remotely, or simply be next to it and click on it to turn it on and off normally."} /* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL) @@ -463,12 +471,12 @@ /obj/structure/bloodsucker/candelabrum/attack_hand(mob/user) var/datum/antagonist/vassal/T = user.mind.has_antag_datum(ANTAG_DATUM_VASSAL) - if(isvamp(user) || istype(T)) + if(AmBloodsucker(user) || istype(T)) toggle() /obj/structure/bloodsucker/candelabrum/AltClick(mob/user) // Bloodsuckers can turn their candles on from a distance. SPOOOOKY. - if(isvamp(user)) + if(AmBloodsucker(user)) toggle() /obj/structure/bloodsucker/candelabrum/proc/toggle(mob/user) @@ -485,7 +493,7 @@ if(lit) for(var/mob/living/carbon/human/H in viewers(7, src)) var/datum/antagonist/vassal/T = H.mind.has_antag_datum(ANTAG_DATUM_VASSAL) - if(isvamp(H) || T) //We dont want vassals or vampires affected by this + if(AmBloodsucker(H) || T) //We dont want vassals or vampires affected by this return H.hallucination = 20 SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "vampcandle", /datum/mood_event/vampcandle) diff --git a/code/modules/antagonists/bloodsucker/powers/cloak.dm b/code/modules/antagonists/bloodsucker/powers/cloak.dm index 1bb7b02357..a616c39923 100644 --- a/code/modules/antagonists/bloodsucker/powers/cloak.dm +++ b/code/modules/antagonists/bloodsucker/powers/cloak.dm @@ -2,7 +2,7 @@ /datum/action/bloodsucker/cloak name = "Cloak of Darkness" - desc = "Blend into the shadows and become invisible to the untrained eye. Movement is slowed in brightly lit areas." + desc = "Blend into the shadows and become invisible to the untrained eye. Movement is slowed in brightly lit areas, and you cannot dissapear while mortals watch you." button_icon_state = "power_cloak" bloodcost = 5 cooldown = 50 diff --git a/code/modules/antagonists/bloodsucker/powers/feed.dm b/code/modules/antagonists/bloodsucker/powers/feed.dm index bbce221d91..8ac4fcebc1 100644 --- a/code/modules/antagonists/bloodsucker/powers/feed.dm +++ b/code/modules/antagonists/bloodsucker/powers/feed.dm @@ -140,7 +140,7 @@ to_chat(user, "You lean quietly toward [target] and secretly draw out your fangs...") else to_chat(user, "You pull [target] close to you and draw out your fangs...") - if(!do_mob(user, target, feed_time,0,1,extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10) + if(!do_mob(user, target, feed_time, 0, 1, extra_checks = CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10) to_chat(user, "Your feeding was interrupted.") //DeactivatePower(user,target) return @@ -166,7 +166,7 @@ var/deadmessage = target.stat == DEAD ? "" : " [target.p_they(TRUE)] looks dazed, and will not remember this." user.visible_message("[user] puts [target]'s wrist up to [user.p_their()] mouth.", \ "You secretly slip your fangs into [target]'s wrist.[deadmessage]", \ - vision_distance = notice_range, ignored_mobs=target) // Only people who AREN'T the target will notice this action. + vision_distance = notice_range, ignored_mobs = target) // Only people who AREN'T the target will notice this action. // Warn Feeder about Witnesses... var/was_unnoticed = TRUE for(var/mob/living/M in viewers(notice_range, owner)) @@ -257,11 +257,11 @@ to_chat(user, "Your victim is dead. [target.p_their(TRUE)] blood barely nourishes you.") warning_target_dead = TRUE // Full? - if(!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume) + if(!warning_full && user.blood_volume >= bloodsuckerdatum.max_blood_volume) to_chat(user, "You are full. Further blood will be wasted.") warning_full = TRUE // Blood Remaining? (Carbons/Humans only) - if(iscarbon(target) && !target.AmBloodsucker(1)) + if(iscarbon(target) && !AmBloodsucker(target, TRUE)) if(target.blood_volume <= BLOOD_VOLUME_BAD && warning_target_bloodvol > BLOOD_VOLUME_BAD) to_chat(user, "Your victim's blood volume is fatally low!") else if(target.blood_volume <= BLOOD_VOLUME_OKAY && warning_target_bloodvol > BLOOD_VOLUME_OKAY) @@ -275,8 +275,9 @@ break // Blood Gulp Sound - owner.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head. - + owner.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE) + if(!amSilent) + target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE) // DONE! //DeactivatePower(user,target) if(amSilent) @@ -294,12 +295,12 @@ /datum/action/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target) - // Bad Vampire. You shouldn't do that. + // Bad Bloodsucker. You shouldn't do that. if(target && target.stat >= DEAD && ishuman(target)) SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankkilled", /datum/mood_event/drankkilled) // BAD // in bloodsucker_life.dm /datum/action/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target) - return ..() && target && (!target_grappled || user.pulling == target)// Active, and still Antag, + return ..() && target && (!target_grappled || user.pulling == target) && blood_sucking_checks(target, TRUE, TRUE) // Active, and still antag, // NOTE: We only care about pulling if target started off that way. Mostly only important for Aggressive feed. /datum/action/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target) diff --git a/code/modules/antagonists/bloodsucker/powers/fortitude.dm b/code/modules/antagonists/bloodsucker/powers/fortitude.dm index f0724f8204..a58034df0d 100644 --- a/code/modules/antagonists/bloodsucker/powers/fortitude.dm +++ b/code/modules/antagonists/bloodsucker/powers/fortitude.dm @@ -33,6 +33,15 @@ if(was_running) user.toggle_move_intent() while(bloodsuckerdatum && ContinueActive(user) || user.m_intent == MOVE_INTENT_RUN) + if(istype(user.buckled, /obj/vehicle)) //We dont want people using fortitude being able to use vehicles + var/obj/vehicle/V = user.buckled + var/datum/component/riding/VRD = V.GetComponent(/datum/component/riding) + if(VRD) + VRD.force_dismount(user) + to_chat(user, "You trip off the [V], your muscles too heavy for it to support you.") + else + V.unbuckle_mob(user, force = TRUE) + to_chat(user, "You fall off the [V], your weight making you too heavy to be supported by it.") // Pay Blood Toll (if awake) if(user.stat == CONSCIOUS) bloodsuckerdatum.AddBloodVolume(-0.5) // Used to be 0.3 blood per 2 seconds, but we're making it more expensive to keep on. diff --git a/code/modules/antagonists/bloodsucker/powers/haste.dm b/code/modules/antagonists/bloodsucker/powers/haste.dm index 143950b32f..05e2cd0330 100644 --- a/code/modules/antagonists/bloodsucker/powers/haste.dm +++ b/code/modules/antagonists/bloodsucker/powers/haste.dm @@ -8,7 +8,7 @@ desc = "Dash somewhere with supernatural speed. Those nearby may be knocked away, stunned, or left empty-handed." button_icon_state = "power_speed" bloodcost = 6 - cooldown = 50 + cooldown = 120 target_range = 15 power_activates_immediately = TRUE message_Trigger = ""//"Whom will you subvert to your will?" diff --git a/code/modules/antagonists/bloodsucker/powers/mesmerize.dm b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm index 3be5eb02e9..814ad2abd7 100644 --- a/code/modules/antagonists/bloodsucker/powers/mesmerize.dm +++ b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm @@ -64,7 +64,7 @@ to_chat(owner, "Your victim's eyes are glazed over. They cannot perceive you.") return FALSE // Check: Target See Me? (behind wall) - if(!(target in view(target_range, get_turf(owner)))) + if(!(target in viewers(target_range, get_turf(owner)))) // Sub-Check: GET CLOSER //if (!(owner in range(target_range, get_turf(target))) // if (display_error) @@ -90,48 +90,56 @@ /datum/action/bloodsucker/targeted/mesmerize/proc/ContinueTarget(atom/A) var/mob/living/carbon/target = A - var/mob/living/user = owner + var/mob/living/L = owner - var/cancontinue=CheckCanTarget(target) + var/cancontinue = CheckCanTarget(target) if(!cancontinue) success = FALSE target.remove_status_effect(STATUS_EFFECT_MESMERIZE) - user.remove_status_effect(STATUS_EFFECT_MESMERIZE) + L.remove_status_effect(STATUS_EFFECT_MESMERIZE) DeactivatePower() DeactivateRangedAbility() StartCooldown() - to_chat(user, "[target] has escaped your gaze!") + to_chat(L, "[target] has escaped your gaze!") UnregisterSignal(target, COMSIG_MOVABLE_MOVED) /datum/action/bloodsucker/targeted/mesmerize/FireTargetedPower(atom/A) // set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done. var/mob/living/carbon/target = A - var/mob/living/user = owner + var/mob/living/L = owner + L.face_atom(A) + if(!istype(target)) + return + success = TRUE + var/power_time = 138 + level_current * 12 + target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30) + L.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30) + RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/ContinueTarget) + // 5 second windup + addtimer(CALLBACK(src, .proc/apply_effects, L, target, power_time), 6 SECONDS) + ADD_TRAIT(target, TRAIT_COMBAT_MODE_LOCKED, src) + ADD_TRAIT(L, TRAIT_COMBAT_MODE_LOCKED, src) - if(istype(target)) - success = TRUE - var/power_time = 138 + level_current * 12 - target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30) - user.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30) - - RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/ContinueTarget) +/datum/action/bloodsucker/targeted/mesmerize/proc/apply_effects(aggressor, victim, power_time) + var/mob/living/carbon/target = victim + var/mob/living/L = aggressor + if(!success) + return + PowerActivatedSuccessfully() // blood & cooldown only altered if power activated successfully - less "fuck you"-y + target.apply_status_effect(STATUS_EFFECT_MESMERIZE, power_time) + REMOVE_TRAIT(L, TRAIT_COMBAT_MODE_LOCKED, src) + target.face_atom(L) + target.Stun(power_time) + to_chat(L, "[target] is fixed in place by your hypnotic gaze.") + target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm + target.notransform = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze. + spawn(power_time) + if(istype(target) && success) + target.notransform = FALSE + REMOVE_TRAIT(target, TRAIT_COMBAT_MODE_LOCKED, src) + if(istype(L) && target.stat == CONSCIOUS && (target in view(10, get_turf(L)))) // They Woke Up! (Notice if within view) + to_chat(L, "[target] has snapped out of their trance.") - // 3 second windup - sleep(30) - if(success) - PowerActivatedSuccessfully() // blood & cooldown only altered if power activated successfully - less "fuck you"-y - target.face_atom(user) - target.apply_status_effect(STATUS_EFFECT_MESMERIZE, power_time) // pretty much purely cosmetic - target.Stun(power_time) - to_chat(user, "[target] is fixed in place by your hypnotic gaze.") - target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm - target.notransform = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze. - spawn(power_time) - if(istype(target) && success) - target.notransform = FALSE - // They Woke Up! (Notice if within view) - if(istype(user) && target.stat == CONSCIOUS && (target in view(10, get_turf(user))) ) - to_chat(user, "[target] has snapped out of their trance.") /datum/action/bloodsucker/targeted/mesmerize/ContinueActive(mob/living/user, mob/living/target) return ..() && CheckCanUse() && CheckCanTarget(target) diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index cc15147312..967715ce2f 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -31,6 +31,7 @@ var/isabsorbing = 0 var/islinking = 0 var/geneticpoints = 10 + var/maxgeneticpoints = 10 var/purchasedpowers = list() var/mimicing = "" var/canrespec = 0 @@ -98,17 +99,24 @@ to_chat(H, "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself.") H.dna.remove_mutation(CLOWNMUT) -/datum/antagonist/changeling/proc/reset_properties() +/datum/antagonist/changeling/proc/reset_properties(hardReset = FALSE) changeling_speak = 0 chosen_sting = null - geneticpoints = initial(geneticpoints) + + geneticpoints = maxgeneticpoints sting_range = initial(sting_range) - chem_storage = initial(chem_storage) - chem_recharge_rate = initial(chem_recharge_rate) - chem_charges = min(chem_charges, chem_storage) chem_recharge_slowdown = initial(chem_recharge_slowdown) mimicing = "" + if (hardReset) + chem_storage = initial(chem_storage) + chem_recharge_rate = initial(chem_recharge_rate) + geneticpoints = initial(geneticpoints) + maxgeneticpoints = initial(maxgeneticpoints) + + chem_charges = min(chem_charges, chem_storage) + + /datum/antagonist/changeling/proc/remove_changeling_powers() if(ishuman(owner.current) || ismonkey(owner.current)) reset_properties() @@ -287,7 +295,6 @@ prof.name_list[slot] = I.name prof.appearance_list[slot] = I.appearance prof.flags_cover_list[slot] = I.flags_cover - prof.item_color_list[slot] = I.item_color prof.item_state_list[slot] = I.item_state prof.exists_list[slot] = 1 else @@ -503,7 +510,6 @@ var/list/appearance_list = list() var/list/flags_cover_list = list() var/list/exists_list = list() - var/list/item_color_list = list() var/list/item_state_list = list() var/underwear @@ -526,7 +532,6 @@ newprofile.appearance_list = appearance_list.Copy() newprofile.flags_cover_list = flags_cover_list.Copy() newprofile.exists_list = exists_list.Copy() - newprofile.item_color_list = item_color_list.Copy() newprofile.item_state_list = item_state_list.Copy() newprofile.underwear = underwear newprofile.undershirt = undershirt diff --git a/code/modules/antagonists/changeling/changeling_power.dm b/code/modules/antagonists/changeling/changeling_power.dm index 574edf225a..aa45c56892 100644 --- a/code/modules/antagonists/changeling/changeling_power.dm +++ b/code/modules/antagonists/changeling/changeling_power.dm @@ -28,8 +28,7 @@ action.Remove(user) return -/obj/effect/proc_holder/changeling/Click() - var/mob/user = usr +/obj/effect/proc_holder/changeling/Trigger(mob/user) if(!user || !user.mind || !user.mind.has_antag_datum(/datum/antagonist/changeling)) return try_to_sting(user) diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm index 5cb4faa86e..c3c4ec78a3 100644 --- a/code/modules/antagonists/changeling/powers/absorb.dm +++ b/code/modules/antagonists/changeling/powers/absorb.dm @@ -96,6 +96,7 @@ to_chat(user, "[target] was one of us. We have absorbed their power.") target_ling.remove_changeling_powers() changeling.geneticpoints += round(target_ling.geneticpoints/2) + changeling.maxgeneticpoints += round(target_ling.geneticpoints/2) target_ling.geneticpoints = 0 target_ling.canrespec = 0 changeling.chem_storage += round(target_ling.chem_storage/2) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 49c34f4d1f..8514df4bd6 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -441,23 +441,23 @@ var/remaining_uses //Set by the changeling ability. -/obj/item/shield/changeling/Initialize() +/obj/item/shield/changeling/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) if(ismob(loc)) loc.visible_message("The end of [loc.name]\'s hand inflates rapidly, forming a huge shield-like mass!", "We inflate our hand into a strong shield.", "You hear organic matter ripping and tearing!") -/obj/item/shield/changeling/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(remaining_uses < 1) +/obj/item/shield/changeling/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + block_return[BLOCK_RETURN_BLOCK_CAPACITY] = (block_return[BLOCK_RETURN_BLOCK_CAPACITY] || 0) + remaining_uses + return ..() + +/obj/item/shield/changeling/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + . = ..() + if(--remaining_uses < 1) if(ishuman(loc)) var/mob/living/carbon/human/H = loc H.visible_message("With a sickening crunch, [H] reforms [H.p_their()] shield into an arm!", "We assimilate our shield into our body", "You press your hand onto [src], golden tendrils of light latching onto you. Was this the best of ideas?") + if(add_servant_of_ratvar(user, FALSE, FALSE, /datum/antagonist/clockcult/neutered/traitor)) + spent = TRUE + // Add some (5 KW) power so they don't suffer for 100 ticks + GLOB.clockwork_power += 5000 + // This intentionally does not use adjust_clockwork_power. + else + to_chat(user, "[src] falls dark. It appears you weren't worthy.") + return ..() + //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/item/clockwork/slab/debug/attack_hand(mob/living/user) if(!is_servant_of_ratvar(user)) @@ -103,8 +121,8 @@ . = ..() addtimer(CALLBACK(src, .proc/check_on_mob, user), 1) //dropped is called before the item is out of the slot, so we need to check slightly later -/obj/item/clockwork/slab/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() +/obj/item/clockwork/slab/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(isinhands && item_state && inhand_overlay) var/mutable_appearance/M = mutable_appearance(icon_file, "slab_[inhand_overlay]") . += M diff --git a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm index e4722dbcb0..faa5e025ca 100644 --- a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm +++ b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm @@ -232,7 +232,7 @@ background_icon_state = "bg_clock" buttontooltipstyle = "clockcult" -/datum/action/innate/eminence/IsAvailable() +/datum/action/innate/eminence/IsAvailable(silent = FALSE) if(!iseminence(owner)) qdel(src) return @@ -283,7 +283,7 @@ desc = "Initiates a mass recall, warping all servants to the Ark after a short delay. This can only be used once." button_icon_state = "Spatial Gateway" -/datum/action/innate/eminence/mass_recall/IsAvailable() +/datum/action/innate/eminence/mass_recall/IsAvailable(silent = FALSE) . = ..() if(.) var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar diff --git a/code/modules/antagonists/clockcult/clock_scripture.dm b/code/modules/antagonists/clockcult/clock_scripture.dm index 753de786dc..16d251fe92 100644 --- a/code/modules/antagonists/clockcult/clock_scripture.dm +++ b/code/modules/antagonists/clockcult/clock_scripture.dm @@ -30,6 +30,7 @@ Applications: 8 servants, 3 caches, and 100 CV var/primary_component var/important = FALSE //important scripture will be italicized in the slab's interface var/sort_priority = 1 //what position the scripture should have in a list of scripture. Should be based off of component costs/reqs, but you can't initial() lists. + var/requires_full_power = FALSE //requires the user to be a full, non neutered servant of ratvar //messages for offstation scripture recital, courtesy ratvar's generals(and neovgre) var/static/list/neovgre_penalty = list("Go to the station.", "Useless.", "Don't waste time.", "Pathetic.", "Wasteful.") @@ -77,6 +78,9 @@ Applications: 8 servants, 3 caches, and 100 CV /datum/clockwork_scripture/proc/can_recite() //If the words can be spoken if(!invoker || !slab || invoker.get_active_held_item() != slab) return FALSE + if(!is_servant_of_ratvar(invoker, requires_full_power)) + to_chat(invoker, "You aren't strongly connected enough to Ratvar to invoke this!") + return FALSE if(!invoker.can_speak_vocal()) to_chat(invoker, "You are unable to speak the words of the scripture!") return FALSE @@ -236,18 +240,21 @@ Applications: 8 servants, 3 caches, and 100 CV return FALSE return TRUE +/datum/clockwork_scripture/create_object/proc/get_spawn_path(mob/user) + return object_path + /datum/clockwork_scripture/create_object/scripture_effects() if(creator_message && observer_message) invoker.visible_message(observer_message, creator_message) else if(creator_message) to_chat(invoker, creator_message) - var/obj/O = new object_path (get_turf(invoker)) + var/to_spawn = get_spawn_path(invoker) + var/obj/O = new to_spawn(get_turf(invoker)) O.ratvar_act() //update the new object so it gets buffed if ratvar is alive if(isitem(O) && put_object_in_hands) invoker.put_in_hands(O) return TRUE - //Used specifically to create construct shells. /datum/clockwork_scripture/create_object/construct put_object_in_hands = FALSE diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm index 5d7a95222f..6349ecb581 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm @@ -88,7 +88,7 @@ sort_priority = 4 quickbind = TRUE quickbind_desc = "Creates a Sigil of Submission, which will convert non-Servants that remain on it." - + requires_full_power = TRUE //Kindle: Charges the slab with blazing energy. It can be released to stun and silence a target. /datum/clockwork_scripture/ranged_ability/kindle @@ -211,6 +211,7 @@ quickbind = TRUE quickbind_desc = "Returns you to Reebe." var/client_color + requires_full_power = TRUE /datum/clockwork_scripture/abscond/check_special_requirements() if(is_reebe(invoker.z)) diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm index 4e1a5b42cb..130fc24583 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm @@ -50,7 +50,6 @@ return FALSE return ..() - //Vitality Matrix: Creates a sigil which will drain health from nonservants and can use that health to heal or even revive servants. /datum/clockwork_scripture/create_object/vitality_matrix descname = "Trap, Damage to Healing" @@ -77,6 +76,10 @@ return FALSE return ..() +/datum/clockwork_scripture/create_object/vitality_matrix/get_spawn_path(mob/user) + if(!is_servant_of_ratvar(user, TRUE)) + return /obj/effect/clockwork/sigil/vitality/neutered + return ..() //Judicial Visor: Creates a judicial visor, which can smite an area. /datum/clockwork_scripture/create_object/judicial_visor @@ -150,7 +153,7 @@ /obj/item/clothing/head/helmet/space, /obj/item/clothing/shoes/magboots)) //replace this only if ratvar is up -/datum/action/innate/clockwork_armaments/IsAvailable() +/datum/action/innate/clockwork_armaments/IsAvailable(silent = FALSE) if(!is_servant_of_ratvar(owner)) qdel(src) return diff --git a/code/modules/antagonists/clockcult/clockcult.dm b/code/modules/antagonists/clockcult/clockcult.dm index cf3d88983c..cbfd443744 100644 --- a/code/modules/antagonists/clockcult/clockcult.dm +++ b/code/modules/antagonists/clockcult/clockcult.dm @@ -5,15 +5,27 @@ antagpanel_category = "Clockcult" job_rank = ROLE_SERVANT_OF_RATVAR antag_moodlet = /datum/mood_event/cult + var/datum/action/innate/hierophant/hierophant_network = new threat = 3 - var/datum/action/innate/hierophant/hierophant_network = new() var/datum/team/clockcult/clock_team var/make_team = TRUE //This should be only false for tutorial scarabs + var/neutered = FALSE //can not use round ending, gibbing, converting, or similar things with unmatched round impact + var/ignore_eligibility_check = FALSE + var/ignore_holy_water = FALSE /datum/antagonist/clockcult/silent silent = TRUE show_in_antagpanel = FALSE //internal +/datum/antagonist/clockcult/neutered + neutered = TRUE + +/datum/antagonist/clockcult/neutered/traitor + ignore_eligibility_check = TRUE + ignore_holy_water = TRUE + show_in_roundend = FALSE + make_team = FALSE + /datum/antagonist/clockcult/Destroy() qdel(hierophant_network) return ..() @@ -38,7 +50,7 @@ /datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner) . = ..() - if(.) + if(. && !ignore_eligibility_check) . = is_eligible_servant(new_owner.current) /datum/antagonist/clockcult/greet() diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 9a086b75a2..d64e99d206 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -17,7 +17,7 @@ qdel(X) ..() -/datum/action/innate/cult/blood_magic/IsAvailable() +/datum/action/innate/cult/blood_magic/IsAvailable(silent = FALSE) if(!iscultist(owner)) return FALSE return ..() @@ -118,7 +118,7 @@ hand_magic = null ..() -/datum/action/innate/cult/blood_spell/IsAvailable() +/datum/action/innate/cult/blood_spell/IsAvailable(silent = FALSE) if(!iscultist(owner) || owner.incapacitated() || !charges) return FALSE return ..() @@ -439,7 +439,7 @@ "A feeling of warmth washes over you, rays of holy light surround your body and protect you from the flash of light!") else // cult doesn't stun any longer when halos are out, instead it does burn damage + knockback! var/datum/antagonist/cult/user_antag = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(user_antag.cult_team.cult_ascendent) + if(user_antag.cult_team?.cult_ascendent) if(!iscultist(L)) L.adjustFireLoss(20) if(L.move_resist < MOVE_FORCE_STRONG) @@ -577,7 +577,9 @@ var/turf/T = get_turf(target) if(istype(target, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/candidate = target - if(candidate.use(50)) + if(!iscultist(user, TRUE)) + to_chat(user, "You are not strongly connected enough to Nar'sie to use make constructs...") + else if(candidate.use(50)) uses-- to_chat(user, "A dark cloud emanates from your hand and swirls around the metal, twisting it into a construct shell!") new /obj/structure/constructshell(T) @@ -600,7 +602,9 @@ SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) else if(istype(target,/mob/living/silicon/robot)) var/mob/living/silicon/robot/candidate = target - if(candidate.mmi) + if(!iscultist(user, TRUE)) + to_chat(user, "You are not strongly connected enough to Nar'sie to use make constructs...") + else if(candidate.mmi) user.visible_message("A dark cloud emanates from [user]'s hand and swirls around [candidate]!") playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, 1) var/prev_color = candidate.color @@ -656,6 +660,7 @@ C.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), SLOT_WEAR_SUIT) C.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), SLOT_SHOES) C.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), SLOT_BACK) + C.equip_to_slot_or_del(new /obj/item/clothing/gloves/fingerless/pugilist/hungryghost(user), SLOT_GLOVES) if(C == user) qdel(src) //Clears the hands C.put_in_hands(new /obj/item/melee/cultblade(user)) @@ -819,6 +824,8 @@ if("Blood Beam (500)") if(uses < 500) to_chat(user, "You need 500 charges to perform this rite.") + else if(!iscultist(user, TRUE)) + to_chat(user, "You are not strongly connected to Nar'sie enough to use something of this power.") else var/obj/rite = new /obj/item/blood_beam() uses -= 500 diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index 1746fd135c..023794182a 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -11,15 +11,27 @@ var/datum/action/innate/cult/blood_magic/magic = new job_rank = ROLE_CULTIST var/ignore_implant = FALSE + var/make_team = TRUE var/give_equipment = FALSE var/datum/team/cult/cult_team + var/neutered = FALSE //can not use round ending, gibbing, converting, or similar things with unmatched round impact + var/ignore_eligibility_checks = FALSE + var/ignore_holy_water = FALSE +/datum/antagonist/cult/neutered + neutered = TRUE + +/datum/antagonist/cult/neutered/traitor + ignore_eligibility_checks = TRUE + ignore_holy_water = TRUE + show_in_roundend = FALSE + make_team = FALSE /datum/antagonist/cult/get_team() return cult_team /datum/antagonist/cult/create_team(datum/team/cult/new_team) - if(!new_team) + if(!new_team && make_team) //todo remove this and allow admin buttons to create more than one cult for(var/datum/antagonist/cult/H in GLOB.antagonists) if(!H.owner) @@ -30,12 +42,12 @@ cult_team = new /datum/team/cult cult_team.setup_objectives() return - if(!istype(new_team)) + if(make_team && !istype(new_team)) stack_trace("Wrong team type passed to [type] initialization.") cult_team = new_team /datum/antagonist/cult/proc/add_objectives() - objectives |= cult_team.objectives + objectives |= cult_team?.objectives /datum/antagonist/cult/Destroy() QDEL_NULL(communion) @@ -44,7 +56,7 @@ /datum/antagonist/cult/can_be_owned(datum/mind/new_owner) . = ..() - if(. && !ignore_implant) + if(. && !ignore_implant && !ignore_eligibility_checks) . = is_convertable_to_cult(new_owner.current,cult_team) /datum/antagonist/cult/greet() @@ -62,7 +74,7 @@ SSticker.mode.update_cult_icons_added(owner) current.log_message("has been converted to the cult of Nar'Sie!", LOG_ATTACK, color="#960000") - if(cult_team.blood_target && cult_team.blood_target_image && current.client) + if(cult_team?.blood_target && cult_team.blood_target_image && current.client) current.client.images += cult_team.blood_target_image @@ -105,13 +117,13 @@ current = mob_override current.faction |= "cult" current.grant_language(/datum/language/narsie) - if(!cult_team.cult_master) + if(!cult_team?.cult_master) vote.Grant(current) communion.Grant(current) if(ishuman(current)) magic.Grant(current) current.throw_alert("bloodsense", /obj/screen/alert/bloodsense) - if(cult_team.cult_risen) + if(cult_team?.cult_risen) cult_team.rise(current) if(cult_team.cult_ascendent) cult_team.ascend(current) @@ -144,7 +156,7 @@ owner.current.visible_message("[owner.current] looks like [owner.current.p_theyve()] just reverted to [owner.current.p_their()] old faith!", null, null, null, owner.current) to_chat(owner.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.") owner.current.log_message("has renounced the cult of Nar'Sie!", LOG_ATTACK, color="#960000") - if(cult_team.blood_target && cult_team.blood_target_image && owner.current.client) + if(cult_team?.blood_target && cult_team.blood_target_image && owner.current.client) owner.current.client.images -= cult_team.blood_target_image . = ..() @@ -206,7 +218,7 @@ throwing.Grant(current) current.update_action_buttons_icon() current.apply_status_effect(/datum/status_effect/cult_master) - if(cult_team.cult_risen) + if(cult_team?.cult_risen) cult_team.rise(current) if(cult_team.cult_ascendent) cult_team.ascend(current) diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index 761412e9f8..77893225fa 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -6,7 +6,7 @@ buttontooltipstyle = "cult" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS -/datum/action/innate/cult/IsAvailable() +/datum/action/innate/cult/IsAvailable(silent = FALSE) if(!iscultist(owner)) return FALSE return ..() @@ -51,7 +51,7 @@ name = "Spiritual Communion" desc = "Conveys a message from the spirit realm that all cultists can hear." -/datum/action/innate/cult/comm/spirit/IsAvailable() +/datum/action/innate/cult/comm/spirit/IsAvailable(silent = FALSE) if(iscultist(owner.mind.current)) return TRUE @@ -72,9 +72,9 @@ name = "Assert Leadership" button_icon_state = "cultvote" -/datum/action/innate/cult/mastervote/IsAvailable() +/datum/action/innate/cult/mastervote/IsAvailable(silent = FALSE) var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(!C || C.cult_team.cult_vote_called || !ishuman(owner)) + if(!C?.cult_team || C.cult_team.cult_vote_called || !ishuman(owner)) return FALSE return ..() @@ -82,6 +82,9 @@ var/choice = alert(owner, "The mantle of leadership is heavy. Success in this role requires an expert level of communication and experience. Are you sure?",, "Yes", "No") if(choice == "Yes" && IsAvailable()) var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!C.cult_team) + to_chat(owner, "Do you not alreaady lead yourself?") + return pollCultists(owner,C.cult_team) /proc/pollCultists(var/mob/living/Nominee,datum/team/cult/team) //Cult Master Poll @@ -137,7 +140,7 @@ to_chat(B.current,"[Nominee] has won the cult's support and is now their master. Follow [Nominee.p_their()] orders to the best of your ability!") return TRUE -/datum/action/innate/cult/master/IsAvailable() +/datum/action/innate/cult/master/IsAvailable(silent = FALSE) if(!owner.mind || !owner.mind.has_antag_datum(/datum/antagonist/cult/master) || GLOB.cult_narsie) return 0 return ..() @@ -151,6 +154,9 @@ var/datum/antagonist/cult/antag = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) if(!antag) return + if(!antag.cult_team) + to_chat(owner, "You have no team. You are alone.") + return for(var/i in 1 to 4) chant(i) var/list/destinations = list() @@ -220,9 +226,9 @@ CM.attached_action = src ..() -/datum/action/innate/cult/master/cultmark/IsAvailable() +/datum/action/innate/cult/master/cultmark/IsAvailable(silent = FALSE) if(cooldown > world.time) - if(!CM.active) + if(!CM.active && !silent) to_chat(owner, "You need to wait [DisplayTimeText(cooldown - world.time)] before you can mark another target!") return FALSE return ..() @@ -261,7 +267,10 @@ return FALSE var/datum/antagonist/cult/C = caller.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - + if(!C.cult_team) + to_chat(ranged_ability_user, "What is the point of marking a target for yourself?") + remove_ranged_ability() + return if(target in view(7, get_turf(ranged_ability_user))) if(C.cult_team.blood_target) to_chat(ranged_ability_user, "The cult has already designated a target!") @@ -299,7 +308,7 @@ name = "Mark a Blood Target for the Cult" desc = "Marks a target for the entire cult to track." -/datum/action/innate/cult/master/cultmark/ghost/IsAvailable() +/datum/action/innate/cult/master/cultmark/ghost/IsAvailable(silent = FALSE) if(istype(owner, /mob/dead/observer) && iscultist(owner.mind.current)) return TRUE else @@ -313,7 +322,7 @@ var/cooldown = 0 var/base_cooldown = 600 -/datum/action/innate/cult/ghostmark/IsAvailable() +/datum/action/innate/cult/ghostmark/IsAvailable(silent = FALSE) if(istype(owner, /mob/dead/observer) && iscultist(owner.mind.current)) return TRUE else @@ -330,8 +339,11 @@ /datum/action/innate/cult/ghostmark/Activate() var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!C.cult_team) + to_chat(owner, "You are alone. You do not have a team.") + return if(C.cult_team.blood_target) - if(cooldown>world.time) + if(cooldown > world.time) reset_blood_target(C.cult_team) to_chat(owner, "You have cleared the cult's blood target!") deltimer(C.cult_team.blood_target_reset_timer) @@ -339,7 +351,7 @@ else to_chat(owner, "The cult has already designated a target!") return - if(cooldown>world.time) + if(cooldown > world.time) to_chat(owner, "You aren't ready to place another blood mark yet!") return target = owner.orbiting?.parent || get_turf(owner) @@ -389,11 +401,11 @@ PM.attached_action = src ..() -/datum/action/innate/cult/master/pulse/IsAvailable() +/datum/action/innate/cult/master/pulse/IsAvailable(silent = FALSE) if(!owner.mind || !owner.mind.has_antag_datum(/datum/antagonist/cult/master)) return FALSE if(cooldown > world.time) - if(!PM.active) + if(!PM.active && !silent) to_chat(owner, "You need to wait [DisplayTimeText(cooldown - world.time)] before you can pulse again!") return FALSE return ..() diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 148e5cfbd5..b05aa7f769 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -6,6 +6,21 @@ throw_range = 5 w_class = WEIGHT_CLASS_SMALL +/obj/item/tome/traitor + var/spent = FALSE + +/obj/item/tome/traitor/check_uplink_validity() + return !spent + +/obj/item/tome/traitor/attack_self(mob/living/user) + if(!iscultist(user) && !spent) + to_chat(user, "You press your hand onto [src], sinister tendrils of corrupted magic swirling around you. Was this the best of ideas?") + if(user.mind.add_antag_datum(/datum/antagonist/cult/neutered/traitor)) + spent = TRUE + else + to_chat(user, "[src] falls dark. It appears you weren't worthy.") + return ..() + /obj/item/melee/cultblade/dagger name = "ritual dagger" desc = "A strange dagger said to be used by sinister groups for \"preparing\" a corpse before sacrificing it to their dark gods." @@ -162,24 +177,20 @@ jaunt.Remove(user) user.update_icons() -/obj/item/twohanded/required/cult_bastard/IsReflect() - if(spinning) +/obj/item/twohanded/required/cult_bastard/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(spinning && is_energy_reflectable_projectile(object) && (attack_type & ATTACK_TYPE_PROJECTILE)) playsound(src, pick('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg', 'sound/weapons/effects/ric3.ogg', 'sound/weapons/effects/ric4.ogg', 'sound/weapons/effects/ric5.ogg'), 100, 1) - return TRUE - else - ..() - -/obj/item/twohanded/required/cult_bastard/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT if(prob(final_block_chance)) - if(attack_type == PROJECTILE_ATTACK) + if(attack_type & ATTACK_TYPE_PROJECTILE) owner.visible_message("[owner] deflects [attack_text] with [src]!") playsound(src, pick('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg', 'sound/weapons/effects/ric3.ogg', 'sound/weapons/effects/ric4.ogg', 'sound/weapons/effects/ric5.ogg'), 100, 1) - return TRUE + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT else playsound(src, 'sound/weapons/parry.ogg', 75, 1) owner.visible_message("[owner] parries [attack_text] with [src]!") - return TRUE - return FALSE + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return BLOCK_NONE /obj/item/twohanded/required/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters) . = ..() @@ -211,7 +222,7 @@ phasein = /obj/effect/temp_visual/dir_setting/cult/phase phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out -/datum/action/innate/dash/cult/IsAvailable() +/datum/action/innate/dash/cult/IsAvailable(silent = FALSE) if(iscultist(holder) && current_charges) return TRUE else @@ -231,7 +242,7 @@ sword = bastard holder = user -/datum/action/innate/cult/spin2win/IsAvailable() +/datum/action/innate/cult/spin2win/IsAvailable(silent = FALSE) if(iscultist(holder) && cooldown <= world.time) return TRUE else @@ -423,7 +434,13 @@ user.adjustBruteLoss(25) user.dropItemToGround(src, TRUE) -/obj/item/clothing/suit/hooded/cultrobes/cult_shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) +/obj/item/clothing/suit/hooded/cultrobes/cult_shield/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(current_charges) + block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE] = 100 + block_return[BLOCK_RETURN_BLOCK_CAPACITY] = (block_return[BLOCK_RETURN_BLOCK_CAPACITY] || 0) + current_charges + return ..() + +/obj/item/clothing/suit/hooded/cultrobes/cult_shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(current_charges) owner.visible_message("\The [attack_text] is deflected in a burst of blood-red sparks!") current_charges-- @@ -431,11 +448,11 @@ if(!current_charges) owner.visible_message("The runed shield around [owner] suddenly disappears!") owner.update_inv_wear_suit() - return 1 - return 0 + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return BLOCK_NONE -/obj/item/clothing/suit/hooded/cultrobes/cult_shield/worn_overlays(isinhands, icon_file, style_flags = NONE) - . = list() +/obj/item/clothing/suit/hooded/cultrobes/cult_shield/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) + . = ..() if(!isinhands && current_charges) . += mutable_appearance('icons/effects/cult_effects.dmi', "shield-cult", MOB_LAYER + 0.01) @@ -507,7 +524,7 @@ var/static/curselimit = 0 /obj/item/shuttle_curse/attack_self(mob/living/user) - if(!iscultist(user)) + if(!iscultist(user, TRUE)) user.dropItemToGround(src, TRUE) user.DefaultCombatKnockdown(100) to_chat(user, "A powerful force shoves you away from [src]!") @@ -734,19 +751,19 @@ playsound(T, 'sound/effects/glassbr3.ogg', 100) qdel(src) -/obj/item/twohanded/cult_spear/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) +/obj/item/twohanded/cult_spear/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(wielded) final_block_chance *= 2 if(prob(final_block_chance)) - if(attack_type == PROJECTILE_ATTACK) + if(attack_type & ATTACK_TYPE_PROJECTILE) owner.visible_message("[owner] deflects [attack_text] with [src]!") playsound(src, pick('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg', 'sound/weapons/effects/ric3.ogg', 'sound/weapons/effects/ric4.ogg', 'sound/weapons/effects/ric5.ogg'), 100, 1) - return TRUE + return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_REDIRECTED | BLOCK_PHYSICAL_EXTERNAL else playsound(src, 'sound/weapons/parry.ogg', 100, 1) owner.visible_message("[owner] parries [attack_text] with [src]!") - return TRUE - return FALSE + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return BLOCK_NONE /datum/action/innate/cult/spear name = "Bloody Bond" @@ -945,10 +962,18 @@ hitsound = 'sound/weapons/smash.ogg' var/illusions = 2 -/obj/item/shield/mirror/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) +/obj/item/shield/mirror/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] = max(block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] || null, final_block_chance) + return ..() + +/obj/item/shield/mirror/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(iscultist(owner)) - if(istype(hitby, /obj/item/projectile)) - var/obj/item/projectile/P = hitby + if(istype(object, /obj/item/projectile) && (attack_type == ATTACK_TYPE_PROJECTILE)) + if(is_energy_reflectable_projectile(object)) + if(prob(final_block_chance)) + return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED + return BLOCK_NONE //To avoid reflection chance double-dipping with block chance + var/obj/item/projectile/P = object if(P.damage >= 30) var/turf/T = get_turf(owner) T.visible_message("The sheer force from [P] shatters the mirror shield!") @@ -956,11 +981,9 @@ playsound(T, 'sound/effects/glassbr3.ogg', 100) owner.DefaultCombatKnockdown(25) qdel(src) - return FALSE - if(P.is_reflectable) - return FALSE //To avoid reflection chance double-dipping with block chance + return BLOCK_NONE . = ..() - if(.) + if(. & BLOCK_SUCCESS) playsound(src, 'sound/weapons/parry.ogg', 100, 1) if(illusions > 0) illusions-- @@ -975,7 +998,7 @@ E.Copy_Parent(owner, 70, 10) E.GiveTarget(owner) E.Goto(owner, owner.movement_delay(), E.minimum_distance) - return TRUE + return else if(prob(50)) var/mob/living/simple_animal/hostile/illusion/H = new(owner.loc) @@ -984,7 +1007,7 @@ H.GiveTarget(owner) H.move_to_delay = owner.movement_delay() to_chat(owner, "[src] betrays you!") - return FALSE + return BLOCK_NONE /obj/item/shield/mirror/proc/readd() illusions++ @@ -992,11 +1015,6 @@ var/mob/living/holder = loc to_chat(holder, "The shield's illusions are back at full strength!") -/obj/item/shield/mirror/IsReflect() - if(prob(block_chance)) - return TRUE - return FALSE - /obj/item/shield/mirror/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) var/turf/T = get_turf(hit_atom) var/datum/thrownthing/D = throwingdatum diff --git a/code/modules/antagonists/cult/ritual.dm b/code/modules/antagonists/cult/ritual.dm index e92f562db3..40804ccc24 100644 --- a/code/modules/antagonists/cult/ritual.dm +++ b/code/modules/antagonists/cult/ritual.dm @@ -59,6 +59,9 @@ This file contains the cult dagger and rune list code rune_to_scribe = GLOB.rune_types[entered_rune_name] if(!rune_to_scribe) return + if(!iscultist(user, initial(rune_to_scribe.requires_full_power))) + to_chat(user, "You aren't strongly connected enough to Nar'sie to do draw this.") + return if(initial(rune_to_scribe.req_keyword)) chosen_keyword = stripped_input(user, "Enter a keyword for the new rune.", "Words of Power") if(!chosen_keyword) @@ -84,8 +87,8 @@ This file contains the cult dagger and rune list code to_chat(user, "Only one ritual site remains - it must be reserved for the final summoning!") return if(ispath(rune_to_scribe, /obj/effect/rune/narsie)) - var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives - var/datum/objective/sacrifice/sac_objective = locate() in user_antag.cult_team.objectives + var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team?.objectives + var/datum/objective/sacrifice/sac_objective = locate() in user_antag.cult_team?.objectives if(!summon_objective) to_chat(user, "Nar'Sie does not wish to be summoned!") return diff --git a/code/modules/antagonists/cult/rune_spawn_action.dm b/code/modules/antagonists/cult/rune_spawn_action.dm index 60a8527860..b164246060 100644 --- a/code/modules/antagonists/cult/rune_spawn_action.dm +++ b/code/modules/antagonists/cult/rune_spawn_action.dm @@ -14,7 +14,7 @@ var/obj/effect/temp_visual/cult/rune_spawn/rune_center_type var/rune_color -/datum/action/innate/cult/create_rune/IsAvailable() +/datum/action/innate/cult/create_rune/IsAvailable(silent = FALSE) if(!rune_type || cooldown > world.time) return FALSE return ..() diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index ec763a66d7..b0538d6521 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -32,6 +32,7 @@ Runes can either be invoked by one's self or with many different cultists. Each var/scribe_delay = 40 //how long the rune takes to create var/scribe_damage = 0.1 //how much damage you take doing it + var/requires_full_power = FALSE //requires full power to draw or invoke var/invoke_damage = 0 //how much damage invokers take when invoking it var/construct_invoke = TRUE //if constructs can invoke it @@ -185,6 +186,7 @@ structure_check() searches for nearby cultist structures required for the invoca color = RUNE_COLOR_OFFER req_cultists = 1 rune_in_use = FALSE + requires_full_power = TRUE /obj/effect/rune/convert/do_invoke_glow() return @@ -458,6 +460,7 @@ structure_check() searches for nearby cultist structures required for the invoca pixel_y = -32 scribe_delay = 500 //how long the rune takes to create scribe_damage = 40.1 //how much damage you take doing it + requires_full_power = TRUE var/used = FALSE /obj/effect/rune/narsie/Initialize(mapload, set_keyword) @@ -482,6 +485,9 @@ structure_check() searches for nearby cultist structures required for the invoca fail_invoke() return var/datum/antagonist/cult/user_antag = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!user_antag.cult_team) + to_chat(user, "You can't seem to make the arcane links to your fellows that you'd need to use this.") + return var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives var/area/place = get_area(src) if(!(place in summon_objective.summon_spots)) @@ -812,6 +818,7 @@ structure_check() searches for nearby cultist structures required for the invoca invoke_damage = 10 construct_invoke = FALSE color = RUNE_COLOR_DARKRED + requires_full_power = TRUE var/mob/living/affecting = null var/ghost_limit = 3 var/ghosts = 0 @@ -942,6 +949,7 @@ structure_check() searches for nearby cultist structures required for the invoca color = RUNE_COLOR_DARKRED req_cultists = 3 scribe_delay = 100 + requires_full_power = TRUE /obj/effect/rune/apocalypse/invoke(var/list/invokers) if(rune_in_use) @@ -950,6 +958,9 @@ structure_check() searches for nearby cultist structures required for the invoca var/area/place = get_area(src) var/mob/living/user = invokers[1] var/datum/antagonist/cult/user_antag = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) + if(!user_antag.cult_team) + to_chat(user, "You can't seem to make the arcane links to your fellows that you'd need to use this.") + return var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives if(summon_objective.summon_spots.len <= 1) to_chat(user, "Only one ritual site remains - it must be reserved for the final summoning!") diff --git a/code/modules/antagonists/devil/true_devil/inventory.dm b/code/modules/antagonists/devil/true_devil/inventory.dm index 778c421616..579dfb4fb1 100644 --- a/code/modules/antagonists/devil/true_devil/inventory.dm +++ b/code/modules/antagonists/devil/true_devil/inventory.dm @@ -12,12 +12,7 @@ var/obj/item/r_hand = get_item_for_held_index(2) if(r_hand) - - var/r_state = r_hand.item_state - if(!r_state) - r_state = r_hand.icon_state - - var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(state = r_state, default_layer = DEVIL_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) + var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(default_layer = DEVIL_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) hands_overlays += r_hand_overlay @@ -28,12 +23,7 @@ client.screen |= r_hand if(l_hand) - - var/l_state = l_hand.item_state - if(!l_state) - l_state = l_hand.icon_state - - var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(state = l_state, default_layer = DEVIL_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) + var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(default_layer = DEVIL_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) hands_overlays += l_hand_overlay diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm index 724c4e6f76..c1f493ac52 100644 --- a/code/modules/antagonists/swarmer/swarmer.dm +++ b/code/modules/antagonists/swarmer/swarmer.dm @@ -179,8 +179,8 @@ /obj/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) if(resistance_flags & INDESTRUCTIBLE) return FALSE - for(var/mob/living/L in contents) - if(!issilicon(L) && !isbrain(L)) + for(var/mob/living/L in GetAllContents()) + if(!ispAI(L) && !isbrain(L)) to_chat(S, "An organism has been detected inside this object. Aborting.") return FALSE return ..() @@ -416,6 +416,57 @@ to_chat(S, "Destroying this object would cause a catastrophic chain reaction. Aborting.") return FALSE +/obj/machinery/ore_silo/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "Destroying this object, however tempting it's, will disrupt the research development that may serve for our masters in the future. Aborting.") + return FALSE + +/obj/machinery/rnd/server/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "Destroying this object, will disrupt the research development that may serve for our masters in the future. Aborting.") + return FALSE + +/obj/machinery/pool/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) //pool's closed, but not. + to_chat(S, "The pool must not be closed, it will provide healthy fun for our masters in the future. Aborting.") + return FALSE + +/obj/structure/pool/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "The pool must not be closed, it will provide healthy fun for our masters in the future. Aborting.") + return FALSE + +/obj/structure/holosign/barrier/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + var/static/list/lazy_typecache = typecacheof(list(/obj/structure/holosign/barrier/engineering, /obj/structure/holosign/barrier/firelock, /obj/structure/holosign/barrier/atmos, /obj/structure/holosign/barrier/combifan)) + if(lazy_typecache[type]) + to_chat(S, "Destroying this holographic barrier may not benefit us. Aborting.") + return FALSE + return ..() + +/obj/machinery/dominator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "This advanced piece of technology may be of use for our masters in the future. Aborting.") + return FALSE + +/obj/machinery/computer/bsa_control/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "This advanced piece of technology may be of use for our masters in the future. Aborting.") + return FALSE + +/obj/machinery/bsa/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "This advanced piece of technology may be of use for our masters in the future. Aborting.") + return FALSE + +/obj/machinery/dna_vault/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "This advanced piece of technology may be of use for our masters in the future. Aborting.") + return FALSE + +/obj/structure/filler/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "This advanced piece of technology may be of use for our masters in the future. Aborting.") + return FALSE + +/obj/machinery/computer/sat_control/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "Destroying this object will lower the station shielding against space debris. Aborting.") + return FALSE + +/obj/machinery/satellite/meteor_shield/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + to_chat(S, "Destroying this object will lower the station shielding against space debris. Aborting.") + return FALSE + ////END CTRL CLICK FOR SWARMERS//// /mob/living/simple_animal/hostile/swarmer/proc/Fabricate(atom/fabrication_object,fabrication_cost = 0) @@ -429,6 +480,14 @@ return new fabrication_object(loc) /mob/living/simple_animal/hostile/swarmer/proc/Integrate(atom/movable/target) + if(isobj(target)) + var/obj/O = target + if(O.resistance_flags & INDESTRUCTIBLE) + return FALSE + for(var/mob/living/L in GetAllContents()) + if(!ispAI(L) && !isbrain(L)) + to_chat(src, "An organism has been detected inside this object. Aborting.") + return FALSE var/resource_gain = target.IntegrateAmount() if(resources + resource_gain > max_resources) to_chat(src, "We cannot hold more materials!") diff --git a/code/modules/antagonists/swarmer/swarmer_event.dm b/code/modules/antagonists/swarmer/swarmer_event.dm index 6ef35fdbaa..c626799a53 100644 --- a/code/modules/antagonists/swarmer/swarmer_event.dm +++ b/code/modules/antagonists/swarmer/swarmer_event.dm @@ -1,10 +1,10 @@ /datum/round_event_control/spawn_swarmer name = "Spawn Swarmer Shell" typepath = /datum/round_event/spawn_swarmer - weight = 0 - max_occurrences = 0 + weight = 7 + max_occurrences = 1 //Only once okay fam earliest_start = 30 MINUTES - min_players = 15 + min_players = 35 gamemode_blacklist = list("dynamic") diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 338d135b4c..f7dc7ad6d1 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -38,8 +38,8 @@ weights[C] = weight var/choice = pickweightAllowZero(weights) if(!choice) - choice = GLOB.traitor_classes[TRAITOR_HUMAN] - set_traitor_kind(pickweightAllowZero(weights)) + choice = GLOB.traitor_classes[TRAITOR_HUMAN] // it's an "easter egg" + set_traitor_kind(choice) traitor_kind.weight *= 0.8 // less likely this round SSticker.mode.traitors += owner owner.special_role = special_role diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm index e6ca95472e..6616eea006 100644 --- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm +++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm @@ -43,7 +43,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( else owner_AI = owner -/datum/action/innate/ai/IsAvailable() +/datum/action/innate/ai/IsAvailable(silent = FALSE) . = ..() if(owner_AI && owner_AI.malf_cooldown > world.time) return FALSE diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index 0f43dfaf3a..d7f1046cd7 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -31,12 +31,12 @@ /obj/item/soulstone/pickup(mob/living/user) ..() - if(!iscultist(user) && !iswizard(user) && !usability) + if(!iscultist(user, TRUE) && !iswizard(user) && !usability) to_chat(user, "An overwhelming feeling of dread comes over you as you pick up the soulstone. It would be wise to be rid of this quickly.") /obj/item/soulstone/examine(mob/user) . = ..() - if(usability || iscultist(user) || iswizard(user) || isobserver(user)) + if(usability || iscultist(user, TRUE) || iswizard(user) || isobserver(user)) if (old_shard) . += "A soulstone, used to capture a soul, either from dead humans or from freed shades." else @@ -53,7 +53,7 @@ //////////////////////////////Capturing//////////////////////////////////////////////////////// /obj/item/soulstone/attack(mob/living/carbon/human/M, mob/living/user) - if(!iscultist(user) && !iswizard(user) && !usability) + if(!iscultist(user, TRUE) && !iswizard(user) && !usability) user.Unconscious(100) to_chat(user, "Your body is wracked with debilitating pain!") return @@ -74,7 +74,7 @@ /obj/item/soulstone/attack_self(mob/living/user) if(!in_range(src, user)) return - if(!iscultist(user) && !iswizard(user) && !usability) + if(!iscultist(user, TRUE) && !iswizard(user) && !usability) user.Unconscious(100) to_chat(user, "Your body is wracked with debilitating pain!") return @@ -103,7 +103,7 @@ /obj/structure/constructshell/examine(mob/user) . = ..() - if(iscultist(user) || iswizard(user) || user.stat == DEAD) + if(iscultist(user, TRUE) || iswizard(user) || user.stat == DEAD) . += "A construct shell, used to house bound souls from a soulstone." . += "Placing a soulstone with a soul into this shell allows you to produce your choice of the following:" . += "An Artificer, which can produce more shells and soulstones, as well as fortifications." @@ -113,7 +113,7 @@ /obj/structure/constructshell/attackby(obj/item/O, mob/user, params) if(istype(O, /obj/item/soulstone)) var/obj/item/soulstone/SS = O - if(!iscultist(user) && !iswizard(user) && !SS.usability) + if(!iscultist(user, TRUE) && !iswizard(user) && !SS.usability) to_chat(user, "An overwhelming feeling of dread comes over you as you attempt to place the soulstone into the shell. It would be wise to be rid of this quickly.") user.Dizzy(30) return @@ -145,7 +145,7 @@ if("VICTIM") var/mob/living/carbon/human/T = target var/datum/antagonist/cult/C = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(C && C.cult_team.is_sacrifice_target(T.mind)) + if(C && C.cult_team?.is_sacrifice_target(T.mind)) if(iscultist(user)) to_chat(user, "\"This soul is mine. SACRIFICE THEM!\"") else diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm index 13ea317b9b..0fbc5cf71c 100644 --- a/code/modules/assembly/flash.dm +++ b/code/modules/assembly/flash.dm @@ -312,7 +312,7 @@ if(holder) holder.update_icon() -/obj/item/assembly/flash/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) +/obj/item/assembly/flash/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) activate() return ..() diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index a79beca4ec..63a03b1d40 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -84,7 +84,6 @@ /obj/machinery/atmospherics/components/proc/nullifyPipenet(datum/pipeline/reference) if(!reference) CRASH("nullifyPipenet(null) called by [type] on [COORD(src)]") - return var/i = parents.Find(reference) reference.other_airs -= airs[i] reference.other_atmosmch -= src @@ -168,4 +167,4 @@ /obj/machinery/atmospherics/components/analyzer_act(mob/living/user, obj/item/I) - atmosanalyzer_scan(airs, user, src) \ No newline at end of file + atmosanalyzer_scan(airs, user, src) diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 899b621262..565bbb7b3c 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -131,7 +131,6 @@ var/datum/pipeline/P = returnPipenet(A) if(!P) CRASH("null.addMember() called by [type] on [COORD(src)]") - return P.addMember(A, src) @@ -208,7 +207,7 @@ /datum/pipeline/proc/return_air() . = other_airs + air if(null in .) - stack_trace("[src] has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().") + stack_trace("[src]([REF(src)]) has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().") return removeNullsFromList(.) /datum/pipeline/proc/reconcile_air() diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index c45461317d..3418f78dbd 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -488,7 +488,6 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if (isnull(A)) //If theres no supplypod bay mapped into centcom, throw an error to_chat(holder.mob, "No /area/centcom/supplypod/loading/one (or /two or /three or /four) in the world! You can make one yourself (then refresh) for now, but yell at a mapper to fix this, today!") CRASH("No /area/centcom/supplypod/loading/one (or /two or /three or /four) has been mapped into the centcom z-level!") - return orderedArea = list() if (!isemptylist(A.contents)) //Go through the area passed into the proc, and figure out the top left and bottom right corners by calculating max and min values var/startX = A.contents[1].x //Create the four values (we do it off a.contents[1] so they have some sort of arbitrary initial value. They should be overwritten in a few moments) diff --git a/code/modules/cargo/exports/gear.dm b/code/modules/cargo/exports/gear.dm index 10b3d4f707..4db7c68efd 100644 --- a/code/modules/cargo/exports/gear.dm +++ b/code/modules/cargo/exports/gear.dm @@ -309,7 +309,7 @@ /datum/export/gear/combatgloves cost = 80 unit_name = "combat gloves" - export_types = list(/obj/item/clothing/gloves/combat, /obj/item/clothing/gloves/rapid, /obj/item/clothing/gloves/krav_maga) + export_types = list(/obj/item/clothing/gloves/combat, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/clothing/gloves/krav_maga) include_subtypes = TRUE /datum/export/gear/bonegloves diff --git a/code/modules/cargo/exports/parts.dm b/code/modules/cargo/exports/parts.dm index e4efaf0810..660d79cae4 100644 --- a/code/modules/cargo/exports/parts.dm +++ b/code/modules/cargo/exports/parts.dm @@ -112,7 +112,7 @@ /datum/export/glasswork_lens cost = 1800 unit_name = "small glass lens" - export_types = list(/obj/item/lens) + export_types = list(/obj/item/glasswork/glass_base/lens) /datum/export/glasswork_spouty cost = 1200 @@ -131,3 +131,27 @@ unit_name = "large flask" export_types = list(/obj/item/reagent_containers/glass/beaker/flask/large) include_subtypes = FALSE + +/datum/export/glasswork_teaplate + cost = 1200 + unit_name = "tea gear" + export_types = list(/obj/item/tea_plate) + include_subtypes = FALSE + +/datum/export/glasswork_teacup + cost = 1800 + unit_name = "tea gear" + export_types = list(/obj/item/tea_cup) + include_subtypes = FALSE + +/datum/export/glasswork_laserpointer + cost = 2600 + unit_name = "hand made laserpointer" + export_types = list(/obj/item/laser_pointer/blue/handmade) + include_subtypes = FALSE + +/datum/export/glasswork_glasses + cost = 5000 + unit_name = "hand made glasses" + export_types = list(/obj/item/glasswork/glasses) + include_subtypes = FALSE diff --git a/code/modules/cargo/exports/weapons.dm b/code/modules/cargo/exports/weapons.dm index 836dc044b7..2342603bde 100644 --- a/code/modules/cargo/exports/weapons.dm +++ b/code/modules/cargo/exports/weapons.dm @@ -287,7 +287,7 @@ /datum/export/weapon/gloves cost = 90 unit_name = "star struck gloves" - export_types = list(/obj/item/clothing/gloves/rapid) + export_types = list(/obj/item/clothing/gloves/fingerless/pugilist/rapid) /datum/export/weapon/l6 cost = 500 diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm index 273acb10e2..14828729cd 100644 --- a/code/modules/cargo/packs/misc.dm +++ b/code/modules/cargo/packs/misc.dm @@ -152,7 +152,7 @@ /obj/item/instrument/trombone, /obj/item/instrument/recorder, /obj/item/instrument/harmonica, - /obj/structure/piano/unanchored) + /obj/structure/musician/piano/unanchored) crate_type = /obj/structure/closet/crate/wooden /datum/supply_pack/misc/casinocrate diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm index a3548a5eb6..6b4733aad8 100644 --- a/code/modules/cargo/packs/science.dm +++ b/code/modules/cargo/packs/science.dm @@ -74,10 +74,9 @@ /datum/supply_pack/science/circuitry name = "Circuitry Starter Pack Crate" - desc = "Journey into the mysterious world of Circuitry with this starter pack. Contains a circuit printer, analyzer, debugger and wirer. Power cells not included." + desc = "Journey into the mysterious world of Circuitry with this starter pack. Contains a circuit printer, debugger and wirer. Power cells not included." cost = 1000 - contains = list(/obj/item/integrated_electronics/analyzer, - /obj/item/integrated_circuit_printer, + contains = list(/obj/item/integrated_circuit_printer, /obj/item/integrated_electronics/debugger, /obj/item/integrated_electronics/wirer) crate_name = "circuitry starter pack crate" diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 7bafefcf53..6f62701590 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -529,7 +529,7 @@ GLOBAL_LIST_EMPTY(asset_datums) "pill21" = 'icons/UI_Icons/Pills/pill21.png', "pill22" = 'icons/UI_Icons/Pills/pill22.png', ) - + /datum/asset/simple/IRV assets = list( "jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js', @@ -704,9 +704,43 @@ GLOBAL_LIST_EMPTY(asset_datums) Insert(initial(D.id), I) return ..() +/datum/asset/spritesheet/vending + name = "vending" + +/datum/asset/spritesheet/vending/register() + for(var/k in GLOB.vending_products) + var/atom/item = k + if(!ispath(item, /atom)) + continue + + var/icon_file = initial(item.icon) + var/icon_state = initial(item.icon_state) + var/icon/I + + var/icon_states_list = icon_states(icon_file) + if(icon_state in icon_states_list) + I = icon(icon_file, icon_state, SOUTH) + var/c = initial(item.color) + if(!isnull(c) && c != "#FFFFFF") + I.Blend(c, ICON_MULTIPLY) + else + var/icon_states_string + for(var/an_icon_state in icon_states_list) + if(!icon_states_string) + icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])" + else + icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])" + stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]") + I = icon('icons/turf/floors.dmi', "", SOUTH) + + var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-") + + Insert(imgid, I) + return ..() + /datum/asset/simple/genetics assets = list( "dna_discovered.gif" = 'html/dna_discovered.gif', "dna_undiscovered.gif" = 'html/dna_undiscovered.gif', "dna_extra.gif" = 'html/dna_extra.gif' -) \ No newline at end of file +) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index adfcd547bc..f7d251f32d 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -150,7 +150,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) "ipc_antenna" = "None", "flavor_text" = "", "meat_type" = "Mammalian", - "body_model" = MALE + "body_model" = MALE, + "body_size" = RESIZE_DEFAULT_SIZE ) var/list/custom_names = list() @@ -294,7 +295,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "[real_name]
" dat += "Be nameless: [nameless ? "Yes" : "No"]
" - dat += "Gender: [gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" + dat += "Gender: [gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" dat += "Age: [age]
" dat += "Special Names:
" @@ -345,7 +346,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) else dat += "[TextPreview(features["flavor_text"])]...
" dat += "

Body

" - dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" + dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" if(gender != NEUTER && pref_species.sexes) dat += "Body Model:[features["body_model"] == MALE ? "Masculine" : "Feminine"]
" dat += "Species:[pref_species.name]
" @@ -379,6 +380,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "    Change
" mutant_colors = TRUE + if (CONFIG_GET(number/body_size_min) != CONFIG_GET(number/body_size_max)) + dat += "Sprite Size: [features["body_size"]]%
" + if((EYECOLOR in pref_species.species_traits) && !(NOEYES in pref_species.species_traits)) if(!use_skintones && !mutant_colors) @@ -2119,6 +2123,38 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_toggle_color) hud_toggle_color = new_toggle_color + if("gender") + var/chosengender = input(user, "Select your character's gender.", "Gender Selection", gender) as null|anything in list(MALE,FEMALE,"nonbinary","object") + if(!chosengender) + return + switch(chosengender) + if("nonbinary") + chosengender = PLURAL + features["body_model"] = pick(MALE, FEMALE) + if("object") + chosengender = NEUTER + features["body_model"] = MALE + else + features["body_model"] = chosengender + gender = chosengender + facial_hair_style = random_facial_hair_style(gender) + hair_style = random_hair_style(gender) + + if("body_size") + var/min = CONFIG_GET(number/body_size_min) + var/max = CONFIG_GET(number/body_size_max) + var/danger = CONFIG_GET(number/threshold_body_size_slowdown) + var/new_body_size = input(user, "Choose your desired sprite size:\n([min*100]%-[max*100]%), Warning: May make your character look distorted[danger > min ? ", and an exponential slowdown will occur for those smaller than [danger*100]%!" : "!"]", "Character Preference", features["body_size"]*100) as num|null + if (new_body_size) + new_body_size = CLAMP(new_body_size * 0.01, min, max) + var/dorfy + if(danger > new_body_size) + dorfy = alert(user, "The chosen size appears to be smaller than the threshold of [danger*100]%, which will lead to an added exponential slowdown. Are you sure about that?", "Dwarfism Alert", "Yes", "Move it to the threshold", "No") + if(!dorfy || dorfy == "Move it above the threshold") + new_body_size = danger + if(dorfy != "No") + features["body_size"] = new_body_size + else switch(href_list["preference"]) //CITADEL PREFERENCES EDIT - I can't figure out how to modularize these, so they have to go here. :c -Pooj @@ -2171,22 +2207,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("publicity") if(unlock_content) toggles ^= MEMBER_PUBLIC - if("gender") - var/chosengender = input(user, "Select your character's gender.", "Gender Selection", gender) as null|anything in list(MALE,FEMALE,"nonbinary","object") - if(!chosengender) - return - switch(chosengender) - if("nonbinary") - chosengender = PLURAL - features["body_model"] = pick(MALE, FEMALE) - if("object") - chosengender = NEUTER - features["body_model"] = MALE - else - features["body_model"] = chosengender - gender = chosengender - facial_hair_style = random_facial_hair_style(gender) - hair_style = random_hair_style(gender) if("body_model") features["body_model"] = features["body_model"] == MALE ? FEMALE : MALE @@ -2431,6 +2451,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) pref_species = new /datum/species/human save_character() + var/old_size = character.dna.features["body_size"] + character.dna.features = features.Copy() character.set_species(chosen_species, icon_update = FALSE, pref_load = TRUE) character.dna.real_name = character.real_name @@ -2452,6 +2474,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) character.give_genitals(TRUE) //character.update_genitals() is already called on genital.update_appearance() + character.dna.update_body_size(old_size) + SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks) //let's be sure the character updates diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index ca51a27dae..7da9d5a1dc 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -395,6 +395,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["body_is_always_random"] >> be_random_body S["gender"] >> gender S["body_model"] >> features["body_model"] + S["body_size"] >> features["body_size"] S["age"] >> age S["hair_color"] >> hair_color S["facial_hair_color"] >> facial_hair_color @@ -568,6 +569,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car features["insect_markings"] = sanitize_inlist(features["insect_markings"], GLOB.insect_markings_list, "None") features["insect_wings"] = sanitize_inlist(features["insect_wings"], GLOB.insect_wings_list) + var/static/size_min + if(!size_min) + size_min = CONFIG_GET(number/body_size_min) + var/static/size_max + if(!size_max) + size_max = CONFIG_GET(number/body_size_max) + features["body_size"] = sanitize_integer(features["body_size"], size_min, size_max, RESIZE_DEFAULT_SIZE) + var/static/list/B_sizes if(!B_sizes) var/list/L = CONFIG_GET(keyed_list/breasts_cups_prefs) @@ -643,6 +652,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["body_is_always_random"] , be_random_body) WRITE_FILE(S["gender"] , gender) WRITE_FILE(S["body_model"] , features["body_model"]) + WRITE_FILE(S["body_size"] , features["body_size"]) WRITE_FILE(S["age"] , age) WRITE_FILE(S["hair_color"] , hair_color) WRITE_FILE(S["facial_hair_color"] , facial_hair_color) diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index cbd1fcff87..9f1111e5d9 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -219,14 +219,13 @@ if(isitem(target)) var/obj/item/I = target I.item_state = initial(picked_item.item_state) - I.item_color = initial(picked_item.item_color) var/obj/item/clothing/CL = target var/obj/item/clothing/PCL = new picked_item if(istype(CL) && istype(PCL)) CL.flags_cover = PCL.flags_cover CL.flags_inv = PCL.flags_inv CL.mutantrace_variation = PCL.mutantrace_variation - CL.alternate_worn_icon = PCL.alternate_worn_icon + CL.mob_overlay_icon = PCL.mob_overlay_icon qdel(PCL) target.icon = initial(picked_item.icon) @@ -238,7 +237,6 @@ P.desc = initial(picked_item.desc) P.icon_state = initial(picked_item.icon_state) P.item_state = initial(picked_item.item_state) - P.item_color = initial(picked_item.item_color) P.overlays_offsets = initial(picked_item.overlays_offsets) P.set_new_overlays() P.update_icon() @@ -269,7 +267,6 @@ name = "black jumpsuit" icon_state = "black" item_state = "bl_suit" - item_color = "black" desc = "It's a plain jumpsuit. It has a small dial on the wrist." sensor_mode = SENSOR_OFF //Hey who's this guy on the Syndicate Shuttle?? random_sensor = FALSE @@ -284,7 +281,6 @@ desc = "A tough jumpsuit woven from alloy threads. It can take on the appearance of other jumpsuits." icon_state = "engine" item_state = "engi_suit" - item_color = "engine" /obj/item/clothing/under/chameleon/Initialize() . = ..() @@ -394,7 +390,6 @@ name = "grey cap" desc = "It's a baseball hat in a tasteful grey colour." icon_state = "greysoft" - item_color = "grey" resistance_flags = NONE armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) @@ -494,7 +489,6 @@ /obj/item/clothing/shoes/chameleon name = "black shoes" icon_state = "black" - item_color = "black" desc = "A pair of black shoes." permeability_coefficient = 0.05 resistance_flags = NONE @@ -520,7 +514,6 @@ /obj/item/clothing/shoes/chameleon/noslip name = "black shoes" icon_state = "black" - item_color = "black" desc = "A pair of black shoes." clothing_flags = NOSLIP @@ -639,7 +632,6 @@ desc = "A neosilk clip-on tie." icon = 'icons/obj/clothing/neck.dmi' icon_state = "blacktie" - item_color = "blacktie" resistance_flags = NONE armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 7e2d73190a..d484027ad5 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -3,6 +3,7 @@ resistance_flags = FLAMMABLE max_integrity = 200 integrity_failure = 0.4 + block_priority = BLOCK_PRIORITY_CLOTHING var/damaged_clothes = 0 //similar to machine's BROKEN stat and structure's broken var var/flash_protect = 0 //What level of bright light protection item has. 1 = Flashers, Flashes, & Flashbangs | 2 = Welding | -1 = OH GOD WELDING BURNT OUT MY RETINAS var/tint = 0 //Sets the item's level of visual impairment tint, normally set to the same as flash_protect @@ -46,25 +47,12 @@ //Add a "exclude" string to do the opposite, making it only only species listed that can't wear it. //You append this to clothing objects. - //Polychrome stuff: - var/hasprimary = FALSE //These vars allow you to choose which overlays a clothing has - var/hassecondary = FALSE - var/hastertiary = FALSE - var/primary_color = "#FFFFFF" //RGB in hexcode - var/secondary_color = "#FFFFFF" - var/tertiary_color = "#808080" - - //No idea what this is but eh -tori - var/force_alternate_icon = FALSE - /obj/item/clothing/Initialize() . = ..() if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE)) actions_types += /datum/action/item_action/toggle_voice_box if(ispath(pocket_storage_component_path)) LoadComponent(pocket_storage_component_path) - if(hasprimary | hassecondary | hastertiary) //Checks if polychrome is enabled - update_icon() //Applies the overlays and default colors onto the clothes on spawn. /obj/item/clothing/MouseDrop(atom/over_object) . = ..() @@ -149,8 +137,6 @@ how_cool_are_your_threads += "Adding or removing items from [src] makes no noise.\n" how_cool_are_your_threads += "
" . += how_cool_are_your_threads.Join() - if(hasprimary | hassecondary | hastertiary) //Checks if polychrome is enabled - . += "Alt-click to recolor it." /obj/item/clothing/obj_break(damage_flag) if(!damaged_clothes) @@ -189,178 +175,11 @@ BLIND // can't see anything /proc/generate_female_clothing(index,t_color,icon,type) var/icon/female_clothing_icon = icon("icon"=icon, "icon_state"=t_color) - var/icon/female_s = icon("icon"='icons/mob/uniform.dmi', "icon_state"="[(type == FEMALE_UNIFORM_FULL) ? "female_full" : "female_top"]") + var/icon/female_s = icon("icon"='icons/mob/clothing/uniform.dmi', "icon_state"="[(type == FEMALE_UNIFORM_FULL) ? "female_full" : "female_top"]") female_clothing_icon.Blend(female_s, ICON_MULTIPLY) female_clothing_icon = fcopy_rsc(female_clothing_icon) GLOB.female_clothing_icons[index] = female_clothing_icon -/obj/item/clothing/under/verb/toggle() - set name = "Adjust Suit Sensors" - set category = "Object" - set src in usr - var/mob/M = usr - if (istype(M, /mob/dead/)) - return - if (!can_use(M)) - return - if(src.has_sensor == LOCKED_SENSORS) - to_chat(usr, "The controls are locked.") - return 0 - if(src.has_sensor == BROKEN_SENSORS) - to_chat(usr, "The sensors have shorted out!") - return 0 - if(src.has_sensor <= NO_SENSORS) - to_chat(usr, "This suit does not have any sensors.") - return 0 - - var/list/modes = list("Off", "Binary vitals", "Exact vitals", "Tracking beacon") - var/switchMode = input("Select a sensor mode:", "Suit Sensor Mode", modes[sensor_mode + 1]) in modes - if(get_dist(usr, src) > 1) - to_chat(usr, "You have moved too far away!") - return - sensor_mode = modes.Find(switchMode) - 1 - - if (src.loc == usr) - switch(sensor_mode) - if(0) - to_chat(usr, "You disable your suit's remote sensing equipment.") - if(1) - to_chat(usr, "Your suit will now only report whether you are alive or dead.") - if(2) - to_chat(usr, "Your suit will now only report your exact vital lifesigns.") - if(3) - to_chat(usr, "Your suit will now report your exact vital lifesigns as well as your coordinate position.") - - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - if(H.w_uniform == src) - H.update_suit_sensors() - - -/obj/item/clothing/under/CtrlClick(mob/user) - . = ..() - - if (!(item_flags & IN_INVENTORY)) - return - - if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) - return - - if(has_sensor == LOCKED_SENSORS) - to_chat(user, "The controls are locked.") - return - if(has_sensor == BROKEN_SENSORS) - to_chat(user, "The sensors have shorted out!") - return - if(has_sensor <= NO_SENSORS) - to_chat(user, "This suit does not have any sensors.") - return - - sensor_mode = SENSOR_COORDS - - to_chat(user, "Your suit will now report your exact vital lifesigns as well as your coordinate position.") - - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.w_uniform == src) - H.update_suit_sensors() - -/obj/item/clothing/under/AltClick(mob/user) - . = ..() - if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) - return - if(attached_accessory) - remove_accessory(user) - else - rolldown() - // Polychrome stuff: - if(hasprimary | hassecondary | hastertiary) - var/choice = input(user,"polychromic thread options", "Clothing Recolor") as null|anything in list("[hasprimary ? "Primary Color" : ""]", "[hassecondary ? "Secondary Color" : ""]", "[hastertiary ? "Tertiary Color" : ""]") //generates a list depending on the enabled overlays - switch(choice) //Lets the list's options actually lead to something - if("Primary Color") - var/primary_color_input = input(usr,"","Choose Primary Color",primary_color) as color|null //color input menu, the "|null" adds a cancel button to it. - if(primary_color_input) //Checks if the color selected is NULL, rejects it if it is NULL. - primary_color = sanitize_hexcolor(primary_color_input, desired_format=6, include_crunch=1) //formats the selected color properly - update_icon() //updates the item icon - user.regenerate_icons() //updates the worn icon. Probably a bad idea, but it works. - if("Secondary Color") - var/secondary_color_input = input(usr,"","Choose Secondary Color",secondary_color) as color|null - if(secondary_color_input) - secondary_color = sanitize_hexcolor(secondary_color_input, desired_format=6, include_crunch=1) - update_icon() - user.regenerate_icons() - if("Tertiary Color") - var/tertiary_color_input = input(usr,"","Choose Tertiary Color",tertiary_color) as color|null - if(tertiary_color_input) - tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1) - update_icon() - user.regenerate_icons() - return TRUE - -/obj/item/clothing/neck/AltClick(mob/user) - . = ..() - if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) - return - // Polychrome stuff: - if(hasprimary | hassecondary | hastertiary) - var/choice = input(user,"polychromic thread options", "Clothing Recolor") as null|anything in list("[hasprimary ? "Primary Color" : ""]", "[hassecondary ? "Secondary Color" : ""]", "[hastertiary ? "Tertiary Color" : ""]") //generates a list depending on the enabled overlays - switch(choice) //Lets the list's options actually lead to something - if("Primary Color") - var/primary_color_input = input(usr,"","Choose Primary Color",primary_color) as color|null //color input menu, the "|null" adds a cancel button to it. - if(primary_color_input) //Checks if the color selected is NULL, rejects it if it is NULL. - primary_color = sanitize_hexcolor(primary_color_input, desired_format=6, include_crunch=1) //formats the selected color properly - update_icon() //updates the item icon - user.regenerate_icons() //updates the worn icon. Probably a bad idea, but it works. - if("Secondary Color") - var/secondary_color_input = input(usr,"","Choose Secondary Color",secondary_color) as color|null - if(secondary_color_input) - secondary_color = sanitize_hexcolor(secondary_color_input, desired_format=6, include_crunch=1) - update_icon() - user.regenerate_icons() - if("Tertiary Color") - var/tertiary_color_input = input(usr,"","Choose Tertiary Color",tertiary_color) as color|null - if(tertiary_color_input) - tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1) - update_icon() - user.regenerate_icons() - return TRUE - -/obj/item/clothing/under/verb/jumpsuit_adjust() - set name = "Adjust Jumpsuit Style" - set category = null - set src in usr - rolldown() - -/obj/item/clothing/under/proc/rolldown() - if(!can_use(usr)) - return - if(!can_adjust) - to_chat(usr, "You cannot wear this suit any differently!") - return - if(toggle_jumpsuit_adjust()) - to_chat(usr, "You adjust the suit to wear it more casually.") - else - to_chat(usr, "You adjust the suit back to normal.") - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - H.update_inv_w_uniform() - H.update_body() - -/obj/item/clothing/under/proc/toggle_jumpsuit_adjust() - adjusted = !adjusted - - if(adjusted) - if(fitted != FEMALE_UNIFORM_TOP) - fitted = NO_FEMALE_UNIFORM - if(!alt_covers_chest) // for the special snowflake suits that expose the chest when adjusted - body_parts_covered &= ~CHEST - else - fitted = initial(fitted) - if(!alt_covers_chest) - body_parts_covered |= CHEST - - return adjusted - /obj/item/clothing/proc/weldingvisortoggle(mob/user) //proc to toggle welding visors on helmets, masks, goggles, etc. if(!can_use(user)) return FALSE @@ -440,15 +259,3 @@ BLIND // can't see anything return FALSE return TRUE - -/obj/item/clothing/update_overlays() // Polychrome stuff - . = ..() - if(hasprimary) //Checks if the overlay is enabled - var/mutable_appearance/primary_overlay = mutable_appearance(icon, "[item_color]-primary", color = primary_color) //Automagically picks overlays - . += primary_overlay //Applies the coloured overlay onto the item sprite. but NOT the mob sprite. - if(hassecondary) - var/mutable_appearance/secondary_overlay = mutable_appearance(icon, "[item_color]-secondary", color = secondary_color) - . += secondary_overlay - if(hastertiary) - var/mutable_appearance/tertiary_overlay = mutable_appearance(icon, "[item_color]-tertiary", color = tertiary_color) - . += tertiary_overlay \ No newline at end of file diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 66dcf89a7a..8cbc416b2e 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -132,7 +132,7 @@ name = "prescription night vision goggles" desc = "NVGs but for those with nearsightedness." vision_correction = 1 - + /obj/item/clothing/glasses/night/syndicate name = "combat night vision goggles" desc = "See everything, without fear." @@ -346,11 +346,11 @@ add_atom_colour("#[user.eye_color]", FIXED_COLOUR_PRIORITY) colored_before = TRUE -/obj/item/clothing/glasses/sunglasses/blindfold/white/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() +/obj/item/clothing/glasses/sunglasses/blindfold/white/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(!isinhands && ishuman(loc) && !colored_before) var/mob/living/carbon/human/H = loc - var/mutable_appearance/M = mutable_appearance('icons/mob/eyes.dmi', "blindfoldwhite") + var/mutable_appearance/M = mutable_appearance('icons/mob/clothing/eyes.dmi', "blindfoldwhite") M.appearance_flags |= RESET_COLOR M.color = "#[H.eye_color]" . += M diff --git a/code/modules/clothing/glasses/phantomthief.dm b/code/modules/clothing/glasses/phantomthief.dm index 1c9afcfd6f..fecf660450 100644 --- a/code/modules/clothing/glasses/phantomthief.dm +++ b/code/modules/clothing/glasses/phantomthief.dm @@ -1,7 +1,7 @@ /obj/item/clothing/glasses/phantomthief name = "suspicious paper mask" desc = "A cheap, Syndicate-branded paper face mask. They'll never see it coming." - alternate_worn_icon = 'icons/mob/mask.dmi' + mob_overlay_icon = 'icons/mob/clothing/mask.dmi' icon = 'icons/obj/clothing/masks.dmi' icon_state = "s-ninja" item_state = "s-ninja" @@ -23,8 +23,8 @@ else . += "[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again." -/obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/user, combatmodestate) - if(istype(user) && combatmodestate && world.time >= nextadrenalinepop) +/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) 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/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index 0729317eac..ddf5e4b584 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -26,8 +26,8 @@ user.visible_message("\the [src] are forcing [user]'s hands around [user.p_their()] neck! It looks like the gloves are possessed!") return OXYLOSS -/obj/item/clothing/gloves/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() +/obj/item/clothing/gloves/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(!isinhands) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves") diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index cf3541fd89..77f06a8a74 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -1,3 +1,6 @@ +/obj/item/clothing/gloves/color + dying_key = DYE_REGISTRY_GLOVES + /obj/item/clothing/gloves/color/yellow desc = "These gloves will protect the wearer from electric shock." name = "insulated gloves" @@ -5,7 +8,6 @@ item_state = "ygloves" siemens_coefficient = 0 permeability_coefficient = 0.05 - item_color="yellow" resistance_flags = NONE var/can_be_cut = 1 @@ -16,7 +18,6 @@ item_state = "ygloves" siemens_coefficient = 1 //Set to a default of 1, gets overridden in New() permeability_coefficient = 0.05 - item_color="yellow" resistance_flags = NONE var/can_be_cut = 1 @@ -70,21 +71,14 @@ name = "black gloves" icon_state = "black" item_state = "blackgloves" - item_color="black" cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE - var/can_be_cut = 1 + var/can_be_cut = TRUE strip_mod = 1.2 -/obj/item/clothing/gloves/color/black/hos - item_color = "hosred" //Exists for washing machines. Is not different from black gloves in any way. - -/obj/item/clothing/gloves/color/black/ce - item_color = "chief" //Exists for washing machines. Is not different from black gloves in any way. - /obj/item/clothing/gloves/color/black/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/wirecutters)) if(can_be_cut && icon_state == initial(icon_state))//only if not dyed @@ -99,15 +93,12 @@ desc = "A pair of gloves, they don't look special in any way." icon_state = "orange" item_state = "orangegloves" - item_color="orange" /obj/item/clothing/gloves/color/red name = "red gloves" desc = "A pair of gloves, they don't look special in any way." icon_state = "red" item_state = "redgloves" - item_color = "red" - /obj/item/clothing/gloves/color/red/insulated name = "insulated gloves" @@ -121,68 +112,48 @@ desc = "A pair of gloves, they don't look special in any way." icon_state = "rainbow" item_state = "rainbowgloves" - item_color = "rainbow" - -/obj/item/clothing/gloves/color/rainbow/clown - item_color = "clown" /obj/item/clothing/gloves/color/blue name = "blue gloves" desc = "A pair of gloves, they don't look special in any way." icon_state = "blue" item_state = "bluegloves" - item_color="blue" /obj/item/clothing/gloves/color/purple name = "purple gloves" desc = "A pair of gloves, they don't look special in any way." icon_state = "purple" item_state = "purplegloves" - item_color="purple" /obj/item/clothing/gloves/color/green name = "green gloves" desc = "A pair of gloves, they don't look special in any way." icon_state = "green" item_state = "greengloves" - item_color="green" /obj/item/clothing/gloves/color/grey name = "grey gloves" desc = "A pair of gloves, they don't look special in any way." icon_state = "gray" item_state = "graygloves" - item_color="grey" - -/obj/item/clothing/gloves/color/grey/rd - item_color = "director" //Exists for washing machines. Is not different from gray gloves in any way. - -/obj/item/clothing/gloves/color/grey/hop - item_color = "hop" //Exists for washing machines. Is not different from gray gloves in any way. /obj/item/clothing/gloves/color/light_brown name = "light brown gloves" desc = "A pair of gloves, they don't look special in any way." icon_state = "lightbrown" item_state = "lightbrowngloves" - item_color="light brown" /obj/item/clothing/gloves/color/brown name = "brown gloves" desc = "A pair of gloves, they don't look special in any way." icon_state = "brown" item_state = "browngloves" - item_color="brown" - -/obj/item/clothing/gloves/color/brown/cargo - item_color = "cargo" //Exists for washing machines. Is not different from brown gloves in any way. /obj/item/clothing/gloves/color/captain desc = "Regal blue gloves, with a nice gold trim, a diamond anti-shock coating, and an integrated thermal barrier. Swanky." name = "captain's gloves" icon_state = "captain" item_state = "egloves" - item_color = "captain" siemens_coefficient = 0 permeability_coefficient = 0.05 cold_protection = HANDS @@ -199,7 +170,6 @@ item_state = "lgloves" siemens_coefficient = 0.3 permeability_coefficient = 0.01 - item_color="mime" transfer_prints = TRUE resistance_flags = NONE var/carrytrait = TRAIT_QUICK_CARRY @@ -207,18 +177,17 @@ /obj/item/clothing/gloves/color/latex/equipped(mob/user, slot) ..() if(slot == SLOT_GLOVES) - ADD_TRAIT(user, carrytrait, CLOTHING_TRAIT) + ADD_TRAIT(user, carrytrait, GLOVE_TRAIT) /obj/item/clothing/gloves/color/latex/dropped(mob/user) ..() - REMOVE_TRAIT(user, carrytrait, CLOTHING_TRAIT) + REMOVE_TRAIT(user, carrytrait, GLOVE_TRAIT) /obj/item/clothing/gloves/color/latex/nitrile name = "nitrile gloves" desc = "Pricy sterile gloves that are stronger than latex. Transfers advanced paramedical knowledge to the wearer via the use of nanochips." icon_state = "nitrile" item_state = "nitrilegloves" - item_color = "cmo" transfer_prints = FALSE carrytrait = TRAIT_QUICKER_CARRY @@ -236,7 +205,3 @@ desc = "These look pretty fancy." icon_state = "white" item_state = "wgloves" - item_color="white" - -/obj/item/clothing/gloves/color/white/redcoat - item_color = "redcoat" //Exists for washing machines. Is not different from white gloves in any way. diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index 9f4b89f607..a37dc8b638 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -4,7 +4,6 @@ desc = "Plain black gloves without fingertips for the hard working." icon_state = "fingerless" item_state = "fingerless" - item_color = null //So they don't wash. transfer_prints = TRUE strip_delay = 40 equip_delay_other = 20 @@ -12,6 +11,135 @@ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT strip_mod = 0.9 +/obj/item/clothing/gloves/fingerless/pugilist + name = "armwraps" + desc = "A series of armwraps. Makes you pretty keen to start punching people." + icon_state = "armwraps" + item_state = "armwraps" + body_parts_covered = ARMS + cold_protection = ARMS + strip_delay = 300 //you can't just yank them off + ///Extra damage through the punch. + var/enhancement = 0 //it's a +0 to your punches because it isn't magical + ///Main trait added by the gloves to the user on wear. + var/inherited_trait = TRAIT_NOGUNS //what are you, dishonoroable? + ///Secondary trait added by the gloves to the user on wear. + var/secondary_trait = TRAIT_FEARLESS //what are you, a coward? + +/obj/item/clothing/gloves/fingerless/pugilist/equipped(mob/user, slot) + . = ..() + if(slot == SLOT_GLOVES) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + ADD_TRAIT(H, TRAIT_PUGILIST, GLOVE_TRAIT) + ADD_TRAIT(H, inherited_trait, GLOVE_TRAIT) + ADD_TRAIT(H, secondary_trait, GLOVE_TRAIT) + H.dna.species.punchdamagehigh += enhancement + H.dna.species.punchdamagelow += enhancement + +/obj/item/clothing/gloves/fingerless/pugilist/dropped(mob/user) + + REMOVE_TRAIT(user, TRAIT_PUGILIST, GLOVE_TRAIT) + REMOVE_TRAIT(user, inherited_trait, GLOVE_TRAIT) + REMOVE_TRAIT(user, secondary_trait, GLOVE_TRAIT) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.dna.species.punchdamagehigh = initial(H.dna.species.punchdamagehigh) + H.dna.species.punchdamagelow = initial(H.dna.species.punchdamagelow) + return ..() + +/obj/item/clothing/gloves/fingerless/pugilist/chaplain + name = "armwraps of unyielding resolve" + desc = "A series of armwraps, soaked in holy water. Makes you pretty keen to smite evil magic users." + resistance_flags = FIRE_PROOF | ACID_PROOF + enhancement = 1 //It is not magic that makes you punch harder, but force of will. Trust me. + secondary_trait = TRAIT_ANTIMAGIC + var/chaplain_spawnable = TRUE + +/obj/item/clothing/gloves/fingerless/pugilist/chaplain/Initialize() + . = ..() + AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE) + +/obj/item/clothing/gloves/fingerless/pugilist/magic + name = "armwraps of mighty fists" + desc = "A series of armwraps. Makes you pretty keen to go adventuring and punch dragons." + resistance_flags = FIRE_PROOF | ACID_PROOF //magic items are harder to damage with energy this is a dnd joke okay? + enhancement = 1 //They're +1! + +/obj/item/clothing/gloves/fingerless/pugilist/hungryghost + name = "armwraps of the hungry ghost" + desc = "A series of blackened, bloodstained armwraps stitched with strange geometric symbols. Makes you pretty keen to commit horrible acts against the living through bloody carnage." + icon_state = "narsiearmwraps" + item_state = "narsiearmwraps" + resistance_flags = FIRE_PROOF | ACID_PROOF + armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 35, "rad" = 0, "fire" = 50, "acid" = 50) + enhancement = 3 + secondary_trait = TRAIT_KI_VAMPIRE + +/obj/item/clothing/gloves/fingerless/pugilist/brassmountain + name = "armbands of the brass mountain" + desc = "A series of scolding hot brass armbands. Makes you pretty keen to bring the light to the unenlightened through unmitigated violence." + icon_state = "ratvararmwraps" + item_state = "ratvararmwraps" + resistance_flags = FIRE_PROOF | ACID_PROOF + armor = list("melee" = 10, "bullet" = 0, "laser" = -10, "energy" = 0, "bomb" = 0, "bio" = 35, "rad" = 0, "fire" = 50, "acid" = 50) + enhancement = 4 //The artifice of Ratvar is unmatched except when it is. + secondary_trait = TRAIT_STRONG_GRABBER + +/obj/item/clothing/gloves/fingerless/pugilist/rapid + name = "Bands of the North Star" + desc = "The armbands of a deadly martial artist. Makes you pretty keen to put an end to evil in an extremely violent manner." + icon_state = "rapid" + item_state = "rapid" + enhancement = 10 //omae wa mou shindeiru + var/warcry = "AT" + secondary_trait = TRAIT_NOSOFTCRIT //basically extra health + +/obj/item/clothing/gloves/fingerless/pugilist/rapid/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, GLOVE_TRAIT) + +/obj/item/clothing/gloves/fingerless/pugilist/rapid/Touch(atom/target, proximity = TRUE) + if(!isliving(target)) + return + + var/mob/living/M = loc + M.changeNext_move(CLICK_CD_RAPID) + if(warcry) + M.say("[warcry]", ignore_spam = TRUE, forced = TRUE) + + return FALSE + +/obj/item/clothing/gloves/fingerless/pugilist/rapid/AltClick(mob/user) + var/input = stripped_input(user,"What do you want your battlecry to be? Max length of 6 characters.", ,"", 7) + if(input) + warcry = input + +/obj/item/clothing/gloves/fingerless/pugilist/rapid/hug + name = "Hugs of the North Star" + desc = "The armbands of a humble friend. Makes you pretty keen to go let everyone know how much you appreciate them!" + warcry = "owo" //Shouldn't ever come into play + enhancement = 0 + secondary_trait = TRAIT_PACIFISM //You are only here to hug and be friends! + +/obj/item/clothing/gloves/fingerless/pugilist/rapid/hug/Touch(mob/target, proximity = TRUE) + if(!isliving(target)) + return + + var/mob/living/M = loc + + if(M.a_intent != INTENT_HELP) + return FALSE + if(target.stat != CONSCIOUS) //Can't hug people who are dying/dead + return FALSE + else + M.changeNext_move(CLICK_CD_RAPID) + + return FALSE + +/obj/item/clothing/gloves/fingerless/pugilist/rapid/hug/AltClick(mob/user) + return FALSE + /obj/item/clothing/gloves/botanic_leather name = "botanist's leather gloves" desc = "These leather gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin. They're also quite warm." @@ -48,7 +176,6 @@ desc = "For when you're expecting to get slapped on the wrist. Offers modest protection to your arms." icon_state = "bracers" item_state = "bracers" - item_color = null //So they don't wash. transfer_prints = TRUE strip_delay = 40 equip_delay_other = 20 @@ -59,54 +186,6 @@ resistance_flags = NONE armor = list("melee" = 15, "bullet" = 35, "laser" = 35, "energy" = 20, "bomb" = 35, "bio" = 35, "rad" = 35, "fire" = 0, "acid" = 0) -/obj/item/clothing/gloves/rapid - name = "Gloves of the North Star" - desc = "Just looking at these fills you with an urge to beat the shit out of people. Violently." - icon_state = "rapid" - item_state = "rapid" - transfer_prints = TRUE - var/warcry = "AT" - -/obj/item/clothing/gloves/rapid/Touch(mob/living/target,proximity = TRUE) - if(!istype(target)) - return - - var/mob/living/M = loc - M.changeNext_move(CLICK_CD_RAPID) - M.adjustStaminaLoss(-3.5) // used to be -2 with some comment about stamina buffer management but *shrug -hatterhat - if(warcry) - M.say("[warcry]", ignore_spam = TRUE, forced = "north star warcry") - - .= FALSE - - -/obj/item/clothing/gloves/rapid/attack_self(mob/user) - var/input = stripped_input(user,"What do you want your battlecry to be? Max length of 6 characters.", ,"", 7) - if(input) - warcry = input - -/obj/item/clothing/gloves/rapid/hug - name = "Hugs of the North Star" - desc = "Just looking at these fills you with an urge to hug the shit out of people. In a very friendly manner." - warcry = "owo" //Shouldn't ever come into play - -/obj/item/clothing/gloves/rapid/hug/Touch(mob/living/target,proximity = TRUE) - if(!istype(target)) - return - - var/mob/living/M = loc - - if(M.a_intent == INTENT_HELP) - if(target.health >= 0 && !HAS_TRAIT(target, TRAIT_FAKEDEATH)) //Can't hug people who are dying/dead - if(target.on_fire || target.lying) //No spamming extinguishing, helping them up, or other non-hugging/patting help interactions - return - else - M.changeNext_move(CLICK_CD_RAPID) - . = FALSE - -/obj/item/clothing/gloves/rapid/hug/attack_self(mob/user) - return FALSE - /obj/item/clothing/gloves/thief name = "black gloves" desc = "Gloves made with completely frictionless, insulated cloth, easier to steal from people with." @@ -117,4 +196,4 @@ strip_delay = 80 transfer_prints = FALSE strip_mod = 5 - strip_silence = TRUE \ No newline at end of file + strip_silence = TRUE diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index d599fbf6f7..475e7a4e51 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -48,8 +48,8 @@ -/obj/item/clothing/head/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() +/obj/item/clothing/head/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(!isinhands) if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedhelmet") diff --git a/code/modules/clothing/head/beanie.dm b/code/modules/clothing/head/beanie.dm index a5fb04d393..4117e88811 100644 --- a/code/modules/clothing/head/beanie.dm +++ b/code/modules/clothing/head/beanie.dm @@ -5,7 +5,6 @@ name = "white beanie" desc = "A stylish beanie. The perfect winter accessory for those with a keen fashion sense, and those who just can't handle a cold breeze on their heads." icon_state = "beanie" //Default white - item_color = "beanie" /obj/item/clothing/head/beanie/black name = "black beanie" @@ -52,33 +51,27 @@ /obj/item/clothing/head/beanie/christmas name = "christmas beanie" icon_state = "beaniechristmas" - item_color = "beaniechristmas" /obj/item/clothing/head/beanie/striped name = "striped beanie" icon_state = "beaniestriped" - item_color = "beaniestriped" /obj/item/clothing/head/beanie/stripedred name = "red striped beanie" icon_state = "beaniestripedred" - item_color = "beaniestripedred" /obj/item/clothing/head/beanie/stripedblue name = "blue striped beanie" icon_state = "beaniestripedblue" - item_color = "beaniestripedblue" /obj/item/clothing/head/beanie/stripedgreen name = "green striped beanie" icon_state = "beaniestripedgreen" - item_color = "beaniestripedgreen" /obj/item/clothing/head/beanie/durathread name = "durathread beanie" desc = "A beanie made from durathread, its resilient fibres provide some protection to the wearer." icon_state = "beaniedurathread" - item_color = null armor = list("melee" = 25, "bullet" = 10, "laser" = 20,"energy" = 10, "bomb" = 30, "bio" = 15, "rad" = 20, "fire" = 100, "acid" = 50) diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 29b0aa9552..ffd50cbfbe 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -7,7 +7,7 @@ light_color = "#FFCC66" var/power_on = 0.8 var/on = FALSE - item_color = "yellow" //Determines used sprites: hardhat[on]_[item_color] and hardhat[on]_[item_color]2 (lying down sprite) + var/hat_type = "yellow" //Determines used sprites: hardhat[on]_[hat_type] and hardhat[on]_[hat_type]2 (lying down sprite) armor = list("melee" = 15, "bullet" = 5, "laser" = 20,"energy" = 10, "bomb" = 20, "bio" = 10, "rad" = 20, "fire" = 100, "acid" = 50) flags_inv = 0 actions_types = list(/datum/action/item_action/toggle_helmet_light) @@ -33,8 +33,8 @@ update_icon() /obj/item/clothing/head/hardhat/update_icon_state() - icon_state = "hardhat[on]_[item_color]" - item_state = "hardhat[on]_[item_color]" + icon_state = "hardhat[on]_[hat_type]" + item_state = "hardhat[on]_[hat_type]" /obj/item/clothing/head/hardhat/proc/turn_on(mob/user) set_light(brightness_on, power_on) @@ -45,13 +45,13 @@ /obj/item/clothing/head/hardhat/orange icon_state = "hardhat0_orange" item_state = "hardhat0_orange" - item_color = "orange" + hat_type = "orange" dog_fashion = null /obj/item/clothing/head/hardhat/red icon_state = "hardhat0_red" item_state = "hardhat0_red" - item_color = "red" + hat_type = "red" dog_fashion = null name = "firefighter helmet" clothing_flags = STOPSPRESSUREDAMAGE @@ -63,7 +63,7 @@ /obj/item/clothing/head/hardhat/white icon_state = "hardhat0_white" item_state = "hardhat0_white" - item_color = "white" + hat_type = "white" clothing_flags = STOPSPRESSUREDAMAGE heat_protection = HEAD max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT @@ -74,13 +74,13 @@ /obj/item/clothing/head/hardhat/dblue icon_state = "hardhat0_dblue" item_state = "hardhat0_dblue" - item_color = "dblue" + hat_type = "dblue" dog_fashion = null /obj/item/clothing/head/hardhat/atmos icon_state = "hardhat0_atmos" item_state = "hardhat0_atmos" - item_color = "atmos" + hat_type = "atmos" dog_fashion = null name = "atmospheric technician's firefighting helmet" desc = "A firefighter's helmet, able to keep the user cool in any situation." @@ -124,12 +124,12 @@ playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing update_icon() -/obj/item/clothing/head/hardhat/weldhat/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/clothing/head/hardhat/weldhat/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) - . += mutable_appearance('icons/mob/head.dmi', "weldhelmet") + . += mutable_appearance('icons/mob/clothing/head.dmi', "weldhelmet") if(!up) - . += mutable_appearance('icons/mob/head.dmi', "weldvisor") + . += mutable_appearance('icons/mob/clothing/head.dmi', "weldvisor") /obj/item/clothing/head/hardhat/weldhat/update_overlays() . = ..() @@ -139,14 +139,14 @@ /obj/item/clothing/head/hardhat/weldhat/orange icon_state = "hardhat0_orange" item_state = "hardhat0_orange" - item_color = "orange" + hat_type = "orange" /obj/item/clothing/head/hardhat/weldhat/white desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight AND welding shield!" //This bulb is not smaller icon_state = "hardhat0_white" item_state = "hardhat0_white" brightness_on = 4 //Boss always takes the best stuff - item_color = "white" + hat_type = "white" clothing_flags = STOPSPRESSUREDAMAGE heat_protection = HEAD max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT @@ -156,4 +156,4 @@ /obj/item/clothing/head/hardhat/weldhat/dblue icon_state = "hardhat0_dblue" item_state = "hardhat0_dblue" - item_color = "dblue" \ No newline at end of file + hat_type = "dblue" \ No newline at end of file diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 9253c4e9aa..638a0c2f23 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -364,7 +364,6 @@ name = "durathread beret" desc = "A beret made from durathread, its resilient fibres provide some protection to the wearer." icon_state = "beretdurathread" - item_color = null armor = list("melee" = 25, "bullet" = 10, "laser" = 20,"energy" = 10, "bomb" = 30, "bio" = 15, "rad" = 20, "fire" = 100, "acid" = 50) #undef DRILL_DEFAULT diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 189fb46e46..2cb043ba88 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -372,14 +372,12 @@ name = "Telegram cap" desc = "A bright red cap warn by hotel staff. Or people who want to be a singing telegram" icon_state = "telegram" - item_color = "telegram" dog_fashion = /datum/dog_fashion/head/telegram /obj/item/clothing/head/colour name = "Singer cap" desc = "A light white hat that has bands of color. Just makes you want to sing and dance!" icon_state = "colour" - item_color = "colour" dog_fashion = /datum/dog_fashion/head/colour /obj/item/clothing/head/christmashat diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 0b58ea234c..9c96223a6f 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -42,7 +42,6 @@ desc = "You put the cake on your head. Brilliant." icon_state = "hardhat0_cakehat" item_state = "hardhat0_cakehat" - item_color = "cakehat" hitsound = 'sound/weapons/tap.ogg' flags_inv = HIDEEARS|HIDEHAIR armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) @@ -114,7 +113,6 @@ desc = "A jack o' lantern! Believed to ward off evil spirits." icon_state = "hardhat0_pumpkin" item_state = "hardhat0_pumpkin" - item_color = "pumpkin" flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) brightness_on = 2 //luminosity when on @@ -151,7 +149,6 @@ desc = "Some fake antlers and a very fake red nose." icon_state = "hardhat0_reindeer" item_state = "hardhat0_reindeer" - item_color = "reindeer" flags_inv = 0 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) brightness_on = 1 //luminosity when on @@ -187,14 +184,15 @@ /obj/item/clothing/head/wig name = "wig" desc = "A bunch of hair without a head attached." - icon_state = "" - item_state = "pwig" + icon = 'icons/mob/human_face.dmi' // default icon for all hairs + icon_state = "hair_vlong" flags_inv = HIDEHAIR + color = "#000" var/hair_style = "Very Long Hair" - var/hair_color = "#000" /obj/item/clothing/head/wig/Initialize(mapload) . = ..() + icon_state = "" //Shitty hack that i dont know if it is even neccesary to deal with the vendor stack exception update_icon() /obj/item/clothing/head/wig/update_icon_state() @@ -202,29 +200,24 @@ if(!S) icon = 'icons/obj/clothing/hats.dmi' icon_state = "pwig" + else + icon = S.icon + icon_state = S.icon_state -/obj/item/clothing/head/wig/update_overlays() +/obj/item/clothing/head/wig/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) . = ..() - var/datum/sprite_accessory/S = GLOB.hair_styles_list[hair_style] - if(S) - var/mutable_appearance/M = mutable_appearance(S.icon, S.icon_state, color = hair_color) - M.appearance_flags |= RESET_COLOR - . += M - -/obj/item/clothing/head/wig/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() if(!isinhands) var/datum/sprite_accessory/S = GLOB.hair_styles_list[hair_style] if(!S) return var/mutable_appearance/M = mutable_appearance(S.icon, S.icon_state,layer = -HAIR_LAYER) M.appearance_flags |= RESET_COLOR - M.color = hair_color + M.color = color . += M /obj/item/clothing/head/wig/random/Initialize(mapload) hair_style = pick(GLOB.hair_styles_list - "Bald") //Don't want invisible wig - hair_color = "#[random_short_color()]" + color = "#[random_short_color()]" . = ..() /obj/item/clothing/head/bronze diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index 19ff6bc8b2..2f4bd44e4f 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -3,14 +3,14 @@ desc = "It's a baseball hat in a tasteless yellow colour." icon_state = "cargosoft" item_state = "helmet" - item_color = "cargo" + var/soft_type = "cargo" dog_fashion = /datum/dog_fashion/head/cargo_tech var/flipped = 0 /obj/item/clothing/head/soft/dropped(mob/user) - icon_state = "[item_color]soft" + icon_state = "[soft_type]soft" flipped = FALSE return ..() @@ -33,10 +33,10 @@ if(!user.incapacitated()) src.flipped = !src.flipped if(src.flipped) - icon_state = "[item_color]soft_flipped" + icon_state = "[soft_type]soft_flipped" to_chat(user, "You flip the hat backwards.") else - icon_state = "[item_color]soft" + icon_state = "[soft_type]soft" to_chat(user, "You flip the hat back in normal position.") usr.update_inv_head() //so our mob-overlays update @@ -48,77 +48,77 @@ name = "red cap" desc = "It's a baseball hat in a tasteless red colour." icon_state = "redsoft" - item_color = "red" + soft_type = "red" dog_fashion = null /obj/item/clothing/head/soft/blue name = "blue cap" desc = "It's a baseball hat in a tasteless blue colour." icon_state = "bluesoft" - item_color = "blue" + soft_type = "blue" dog_fashion = null /obj/item/clothing/head/soft/green name = "green cap" desc = "It's a baseball hat in a tasteless green colour." icon_state = "greensoft" - item_color = "green" + soft_type = "green" dog_fashion = null /obj/item/clothing/head/soft/yellow name = "yellow cap" desc = "It's a baseball hat in a tasteless yellow colour." icon_state = "yellowsoft" - item_color = "yellow" + soft_type = "yellow" dog_fashion = null /obj/item/clothing/head/soft/grey name = "grey cap" desc = "It's a baseball hat in a tasteful grey colour." icon_state = "greysoft" - item_color = "grey" + soft_type = "grey" dog_fashion = null /obj/item/clothing/head/soft/orange name = "orange cap" desc = "It's a baseball hat in a tasteless orange colour." icon_state = "orangesoft" - item_color = "orange" + soft_type = "orange" dog_fashion = null /obj/item/clothing/head/soft/mime name = "white cap" desc = "It's a baseball hat in a tasteless white colour." icon_state = "mimesoft" - item_color = "mime" + soft_type = "mime" dog_fashion = null /obj/item/clothing/head/soft/purple name = "purple cap" desc = "It's a baseball hat in a tasteless purple colour." icon_state = "purplesoft" - item_color = "purple" + soft_type = "purple" dog_fashion = null /obj/item/clothing/head/soft/black name = "black cap" desc = "It's a baseball hat in a tasteless black colour." icon_state = "blacksoft" - item_color = "black" + soft_type = "black" dog_fashion = null /obj/item/clothing/head/soft/rainbow name = "rainbow cap" desc = "It's a baseball hat in a bright rainbow of colors." icon_state = "rainbowsoft" - item_color = "rainbow" + soft_type = "rainbow" dog_fashion = null /obj/item/clothing/head/soft/sec name = "security cap" desc = "It's a robust baseball hat in tasteful red colour." icon_state = "secsoft" - item_color = "sec" + soft_type = "sec" armor = list("melee" = 30, "bullet" = 25, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50) strip_delay = 60 dog_fashion = null @@ -127,14 +127,14 @@ name = "EMT cap" desc = "It's a baseball hat with a dark turquoise color and a reflective cross on the top." icon_state = "emtsoft" - item_color = "emt" + soft_type = "emt" dog_fashion = null /obj/item/clothing/head/soft/baseball name = "baseball cap" desc = "It's a robust baseball hat, this one belongs to syndicate major league team." icon_state = "baseballsoft" - item_color = "baseballsoft" + soft_type = "baseballsoft" item_state = "baseballsoft" flags_inv = HIDEEYES|HIDEFACE armor = list("melee" = 35, "bullet" = 35, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 90) diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index 5019633cf0..7df38661e5 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -28,8 +28,8 @@ /obj/item/clothing/mask/proc/handle_speech() -/obj/item/clothing/mask/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() +/obj/item/clothing/mask/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(!isinhands) if(body_parts_covered & HEAD) if(damaged_clothes) diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 38f0a7c20a..144b17e510 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -68,6 +68,7 @@ clothing_flags = ALLOWINTERNALS icon_state = "clown" item_state = "clown_hat" + dye_color = "clown" flags_cover = MASKCOVERSEYES resistance_flags = FLAMMABLE actions_types = list(/datum/action/item_action/adjust) diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index b6579a3cd8..3813ced2c4 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -132,7 +132,6 @@ /obj/item/clothing/mask/cowmask name = "Cow mask with a builtin voice modulator." desc = "A rubber cow mask," - icon = 'icons/mob/mask.dmi' icon_state = "cowmask" item_state = "cowmask" clothing_flags = VOICEBOX_TOGGLABLE diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 530af7777d..402ea37f21 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -6,8 +6,8 @@ strip_delay = 40 equip_delay_other = 40 -/obj/item/clothing/neck/worn_overlays(isinhands = FALSE, icon_flag, style_flags = NONE) - . = list() +/obj/item/clothing/neck/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(!isinhands) if(body_parts_covered & HEAD) if(damaged_clothes) @@ -21,35 +21,29 @@ icon = 'icons/obj/clothing/neck.dmi' icon_state = "bluetie" item_state = "" //no inhands - item_color = "bluetie" w_class = WEIGHT_CLASS_SMALL /obj/item/clothing/neck/tie/blue name = "blue tie" icon_state = "bluetie" - item_color = "bluetie" /obj/item/clothing/neck/tie/red name = "red tie" icon_state = "redtie" - item_color = "redtie" /obj/item/clothing/neck/tie/black name = "black tie" icon_state = "blacktie" - item_color = "blacktie" /obj/item/clothing/neck/tie/horrible name = "horrible tie" desc = "A neosilk clip-on tie. This one is disgusting." icon_state = "horribletie" - item_color = "horribletie" /obj/item/clothing/neck/stethoscope name = "stethoscope" desc = "An outdated medical apparatus for listening to the sounds of the human body. It also makes you look like you know what you're doing." icon_state = "stethoscope" - item_color = "stethoscope" /obj/item/clothing/neck/stethoscope/suicide_act(mob/living/carbon/user) user.visible_message("[user] puts \the [src] to [user.p_their()] chest! It looks like [user.p_they()] wont hear much!") @@ -94,7 +88,6 @@ name = "white scarf" icon_state = "scarf" desc = "A stylish scarf. The perfect winter accessory for those with a keen fashion sense, and those who just can't handle a cold breeze on their necks." - item_color = "scarf" dog_fashion = /datum/dog_fashion/head /obj/item/clothing/neck/scarf/black @@ -148,12 +141,10 @@ /obj/item/clothing/neck/scarf/zebra name = "zebra scarf" icon_state = "zebrascarf" - item_color = "zebrascarf" /obj/item/clothing/neck/scarf/christmas name = "christmas scarf" icon_state = "christmasscarf" - item_color = "christmasscarf" //The three following scarves don't have the scarf subtype //This is because Ian can equip anything from that subtype @@ -161,17 +152,14 @@ /obj/item/clothing/neck/stripedredscarf name = "striped red scarf" icon_state = "stripedredscarf" - item_color = "stripedredscarf" /obj/item/clothing/neck/stripedgreenscarf name = "striped green scarf" icon_state = "stripedgreenscarf" - item_color = "stripedgreenscarf" /obj/item/clothing/neck/stripedbluescarf name = "striped blue scarf" icon_state = "stripedbluescarf" - item_color = "stripedbluescarf" /////////// //COLLARS// @@ -181,57 +169,44 @@ name = "pet collar" desc = "It's for pets. Though you probably could wear it yourself, you'd doubtless be the subject of ridicule. It seems to be made out of a polychromic material." icon_state = "petcollar" - item_color = "petcollar" - alternate_worn_icon = 'icons/mob/neck.dmi' //Because, as it appears, the item itself is normally not directly aware of its worn overlays, so this is about the easiest way, without adding a new var. - hasprimary = TRUE - primary_color = "#00BBBB" pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/collar + var/poly_states = 1 + var/poly_colors = list("#00BBBB") var/tagname = null + var/treat_path = /obj/item/reagent_containers/food/snacks/cookie + +/obj/item/clothing/neck/petcollar/Initialize() + . = ..() + if(treat_path) + new treat_path(src) + +/obj/item/clothing/neck/petcollar/ComponentInitialize() + . = ..() + if(!poly_states) + return + AddElement(/datum/element/polychromic, poly_colors, poly_states) /obj/item/clothing/neck/petcollar/attack_self(mob/user) tagname = stripped_input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot", MAX_NAME_LEN) name = "[initial(name)] - [tagname]" -/obj/item/clothing/neck/petcollar/worn_overlays(isinhands, icon_file, style_flags = NONE) - . = ..() - if(hasprimary | hassecondary | hastertiary) - if(!isinhands) //prevents the worn sprites from showing up if you're just holding them - if(hasprimary) //checks if overlays are enabled - var/mutable_appearance/primary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-primary") //automagical sprite selection - primary_worn.color = primary_color //colors the overlay - . += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite - if(hassecondary) - var/mutable_appearance/secondary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-secondary") - secondary_worn.color = secondary_color - . += secondary_worn - if(hastertiary) - var/mutable_appearance/tertiary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-tertiary") - tertiary_worn.color = tertiary_color - . += tertiary_worn - /obj/item/clothing/neck/petcollar/leather name = "leather pet collar" icon_state = "leathercollar" - item_color = "leathercollar" - - hasprimary = TRUE - hassecondary = TRUE - primary_color = "#222222" - secondary_color = "#888888" + poly_states = 2 + poly_colors = list("#222222", "#888888") /obj/item/clothing/neck/petcollar/choker desc = "Quite fashionable... if you're somebody who's just read their first BDSM-themed erotica novel." name = "choker" icon_state = "choker" - item_color = "choker" - - hasprimary = TRUE - primary_color = "#222222" + poly_colors = list("#222222") /obj/item/clothing/neck/petcollar/locked name = "locked collar" desc = "A collar that has a small lock on it to keep it from being removed." pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/collar/locked + treat_path = /obj/item/key/collar var/lock = FALSE /obj/item/clothing/neck/petcollar/locked/attackby(obj/item/K, mob/user, params) @@ -253,34 +228,19 @@ /obj/item/clothing/neck/petcollar/locked/leather name = "leather pet collar" icon_state = "leathercollar" - item_color = "leathercollar" - - hasprimary = TRUE - hassecondary = TRUE - primary_color = "#222222" - secondary_color = "#888888" + poly_states = 2 + poly_colors = list("#222222", "#888888") /obj/item/clothing/neck/petcollar/locked/choker name = "choker" desc = "Quite fashionable... if you're somebody who's just read their first BDSM-themed erotica novel." icon_state = "choker" - item_color = "choker" - - hasprimary = TRUE - primary_color = "#222222" + poly_colors = list("#222222") /obj/item/key/collar name = "Collar Key" desc = "A key for a tiny lock on a collar or bag." -/obj/item/clothing/neck/petcollar/Initialize() - . = ..() - new /obj/item/reagent_containers/food/snacks/cookie(src) - -/obj/item/clothing/neck/petcollar/locked/Initialize() - . = ..() - new /obj/item/key/collar(src) - ////////////// //DOPE BLING// ////////////// @@ -290,7 +250,6 @@ desc = "Damn, it feels good to be a gangster." icon = 'icons/obj/clothing/neck.dmi' icon_state = "bling" - item_color = "bling" ////////////////////////////////// //VERY SUPER BADASS NECKERCHIEFS// @@ -304,7 +263,7 @@ obj/item/clothing/neck/neckerchief /obj/item/clothing/neck/neckerchief/worn_overlays(isinhands) . = ..() if(!isinhands) - var/mutable_appearance/realOverlay = mutable_appearance('icons/mob/mask.dmi', icon_state) + var/mutable_appearance/realOverlay = mutable_appearance('icons/mob/clothing/mask.dmi', icon_state) realOverlay.pixel_y = -3 . += realOverlay diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index 4c6d3a8f88..802dd7265e 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -49,8 +49,8 @@ last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works last_blood_DNA = blood_dna[blood_dna.len] -/obj/item/clothing/shoes/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() +/obj/item/clothing/shoes/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(!isinhands) var/bloody = FALSE if(blood_DNA) @@ -61,7 +61,7 @@ if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedshoe") if(bloody) - var/file2use = style_flags & STYLE_DIGITIGRADE ? 'icons/mob/feet_digi.dmi' : 'icons/effects/blood.dmi' + var/file2use = style_flags & STYLE_DIGITIGRADE ? 'icons/mob/clothing/feet_digi.dmi' : 'icons/effects/blood.dmi' . += mutable_appearance(file2use, "shoeblood", color = blood_DNA_to_color()) /obj/item/clothing/shoes/equipped(mob/user, slot) diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index c45b9b443a..df0f03f614 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -1,9 +1,9 @@ /obj/item/clothing/shoes/sneakers + dying_key = DYE_REGISTRY_SNEAKERS /obj/item/clothing/shoes/sneakers/black name = "black shoes" icon_state = "black" - item_color = "black" desc = "A pair of black shoes." cold_protection = FEET @@ -11,80 +11,49 @@ heat_protection = FEET max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT -/obj/item/clothing/shoes/sneakers/black/redcoat - item_color = "redcoat" //Exists for washing machines. Is not different from black shoes in any way. - /obj/item/clothing/shoes/sneakers/brown name = "brown shoes" desc = "A pair of brown shoes." icon_state = "brown" - item_color = "brown" - -/obj/item/clothing/shoes/sneakers/brown/captain - item_color = "captain" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/sneakers/brown/hop - item_color = "hop" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/sneakers/brown/ce - item_color = "chief" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/sneakers/brown/rd - item_color = "director" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/sneakers/brown/cmo - item_color = "medical" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/sneakers/brown/qm - item_color = "cargo" //Exists for washing machines. Is not different from brown shoes in any way. /obj/item/clothing/shoes/sneakers/blue name = "blue shoes" icon_state = "blue" - item_color = "blue" /obj/item/clothing/shoes/sneakers/green name = "green shoes" icon_state = "green" - item_color = "green" /obj/item/clothing/shoes/sneakers/yellow name = "yellow shoes" icon_state = "yellow" - item_color = "yellow" /obj/item/clothing/shoes/sneakers/purple name = "purple shoes" icon_state = "purple" - item_color = "purple" /obj/item/clothing/shoes/sneakers/brown name = "brown shoes" icon_state = "brown" - item_color = "brown" /obj/item/clothing/shoes/sneakers/red name = "red shoes" desc = "Stylish red shoes." icon_state = "red" - item_color = "red" /obj/item/clothing/shoes/sneakers/white name = "white shoes" icon_state = "white" permeability_coefficient = 0.01 - item_color = "white" /obj/item/clothing/shoes/sneakers/rainbow name = "rainbow shoes" desc = "Very gay shoes." icon_state = "rain_bow" - item_color = "rainbow" /obj/item/clothing/shoes/sneakers/orange name = "orange shoes" icon_state = "orange" - item_color = "orange" /obj/item/clothing/shoes/sneakers/orange/attack_self(mob/user) if (src.chained) @@ -120,5 +89,4 @@ to_chat(c, "You need help taking these off!") return return ..() - - \ No newline at end of file + diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 32d9dd4483..7a3ed902ea 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -4,7 +4,6 @@ /obj/item/clothing/shoes/sneakers/mime name = "mime shoes" icon_state = "mime" - item_color = "mime" /obj/item/clothing/shoes/combat //basic syndicate combat boots for nuke ops and mob corpses name = "combat boots" @@ -124,7 +123,6 @@ icon_state = "jackboots" lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - item_color = "hosred" strip_delay = 50 equip_delay_other = 50 resistance_flags = NONE @@ -181,7 +179,6 @@ name = "\improper Nar'Sien invoker boots" desc = "A pair of boots worn by the followers of Nar'Sie." icon_state = "cult" - item_color = "cult" cold_protection = FEET min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT heat_protection = FEET @@ -227,7 +224,6 @@ name = "jump boots" desc = "A specialized pair of combat boots with a built-in propulsion system for rapid foward movement." icon_state = "jetboots" - item_color = "hosred" resistance_flags = FIRE_PROOF pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes actions_types = list(/datum/action/item_action/bhop) @@ -381,3 +377,99 @@ name = "black cowboy boots" desc = "A pair of black cowboy boots, pretty easy to scuff up." icon_state = "cowboyboots_black" + +/obj/item/clothing/shoes/wallwalkers + name = "wall walking boots" + desc = "Contrary to popular belief, these do not allow you to walk on walls. Through bluespace magic stolen from an organisation that hoards technology, they simply allow you to slip through the atoms that make up anything, but only while walking, for safety reasons. As well as this, they unfortunately cause minor breath loss as the majority of atoms in your lungs are sucked out into any solid object you walk through. Make sure not to overuse them." + icon_state = "walkboots" + var/walkcool = 0 + var/wallcharges = 4 + var/newlocobject = null + +/obj/item/clothing/shoes/wallwalkers/equipped(mob/user,slot) + . = ..() + if(slot == SLOT_SHOES) + RegisterSignal(user, COMSIG_MOB_CLIENT_MOVE,.proc/intercept_user_move) + +/obj/item/clothing/shoes/wallwalkers/dropped(mob/user) + . = ..() + UnregisterSignal(user, COMSIG_MOB_CLIENT_MOVE) + +/obj/item/clothing/shoes/wallwalkers/attackby(obj/item/W, mob/user, params) + . = ..() + if(!istype(W, /obj/item/bluespacerecharge)) + return + var/obj/item/bluespacerecharge/ER = W + if(ER.uses) + wallcharges += ER.uses + to_chat(user, "You charged the bluespace crystal in the [src]. It now has [wallcharges] charges left.") + ER.uses = 0 + ER.icon_state = "[initial(ER.icon_state)]0" + else + to_chat(user, "[ER] has no crystal on it.") + +/obj/item/clothing/shoes/wallwalkers/examine(mob/user) + . = ..() + . += "It has [wallcharges] charges left." + +/obj/item/clothing/shoes/wallwalkers/proc/intercept_user_move(mob/living/m, client/client, dir, newloc, oldloc) + if (walkcool >= world.time || m.m_intent != MOVE_INTENT_WALK || wallcharges <= 0) + return + walkcool = world.time + m.movement_delay() + var/issolid = FALSE + var/turf/K = newloc + if (istype(K)) + if (K.density) + issolid = TRUE + if (!issolid) + for (var/atom/T in newloc) //stuff on the new turf + if (!T.CanPass(m,newloc) && T != m) + issolid = TRUE + newlocobject = T + break + if (!issolid) + for (var/atom/T in oldloc) //directional shit on the old turf + if (!T.CanPass(m,newloc) && T != m && T != newlocobject) + issolid = TRUE + break + newlocobject = null //stopping structures from using two charges because of how shitty the canpass code is + m.forceMove(newloc) + if (!issolid) + return + m.adjustOxyLoss(rand(5,13)) + if (prob(15)) + m.adjustBruteLoss(rand(4,7)) + to_chat(m,"You feel as if travelling through the solid object left something behind and it hurts!") + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(5, 1, oldloc) + s.start() + flash_lighting_fx(3, 3, LIGHT_COLOR_ORANGE) + wallcharges-- + +/obj/item/bluespacerecharge + name = "bluespace crystal recharging device" + desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for replacing the crystals in bluespace devices." + icon = 'icons/obj/module.dmi' + icon_state = "bluespace_charge" + item_flags = NOBLUDGEON + w_class = WEIGHT_CLASS_TINY + var/uses = 6 + +/obj/item/bluespacerecharge/examine(mob/user) + . = ..() + if(uses) + . += "It can add up to [uses] charges to compatible devices." + else + . += "The crystal is gone." + +/obj/item/bluespacerecharge/attackby(obj/item/I, mob/user, params) + ..() + if(!istype(I, /obj/item/stack/ore/bluespace_crystal) || uses) + return + var/obj/item/stack/ore/bluespace_crystal/B = I + if (B.amount < 10) + return + uses += 3 + to_chat(user, "You insert [I] into [src].") + B.use(10) + icon_state = initial(icon_state) diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 4311aa5166..94ccdf94c6 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -321,7 +321,7 @@ check_flags = AB_CHECK_CONSCIOUS //|AB_CHECK_INSIDE var/obj/item/clothing/suit/space/chronos/chronosuit = null -/datum/action/innate/chrono_teleport/IsAvailable() +/datum/action/innate/chrono_teleport/IsAvailable(silent = FALSE) return (chronosuit && chronosuit.activated && chronosuit.camera && !chronosuit.teleporting) /datum/action/innate/chrono_teleport/Activate() diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 1f23569a9c..93b34f4522 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -10,7 +10,7 @@ var/brightness_on = 4 //luminosity when on var/on = FALSE var/obj/item/clothing/suit/space/hardsuit/suit - item_color = "engineering" //Determines used sprites: hardsuit[on]-[color] and hardsuit[on]-[color]2 (lying down sprite) + var/hardsuit_type = "engineering" //Determines used sprites: hardsuit[on]-[type] actions_types = list(/datum/action/item_action/toggle_helmet_light) var/rad_count = 0 @@ -30,16 +30,14 @@ /obj/item/clothing/head/helmet/space/hardsuit/attack_self(mob/user) on = !on - icon_state = "[basestate][on]-[item_color]" user.update_inv_head() //so our mob-overlays update - if(on) set_light(brightness_on) else set_light(0) - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon() + +/obj/item/clothing/head/helmet/space/hardsuit/update_icon_state() + icon_state = "[basestate][on]-[hardsuit_type]" /obj/item/clothing/head/helmet/space/hardsuit/dropped(mob/user) ..() @@ -103,6 +101,7 @@ actions_types = list(/datum/action/item_action/toggle_helmet) var/helmettype = /obj/item/clothing/head/helmet/space/hardsuit var/obj/item/tank/jetpack/suit/jetpack = null + var/hardsuit_type /obj/item/clothing/suit/space/hardsuit/Initialize() @@ -169,7 +168,7 @@ icon_state = "hardsuit0-engineering" item_state = "eng_helm" armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 100, "acid" = 75) - item_color = "engineering" + hardsuit_type = "engineering" resistance_flags = FIRE_PROOF /obj/item/clothing/suit/space/hardsuit/engine @@ -188,7 +187,7 @@ desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has thermal shielding." icon_state = "hardsuit0-atmospherics" item_state = "atmo_helm" - item_color = "atmospherics" + hardsuit_type = "atmospherics" armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 25, "fire" = 100, "acid" = 75) heat_protection = HEAD //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -209,7 +208,7 @@ desc = "An advanced helmet designed for work in a hazardous, low pressure environment. Shines with a high polish." icon_state = "hardsuit0-white" item_state = "ce_helm" - item_color = "white" + hardsuit_type = "white" armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 90) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -231,7 +230,7 @@ desc = "A special helmet designed for work in a hazardous, low pressure environment. Has reinforced plating for wildlife encounters and dual floodlights." icon_state = "hardsuit0-mining" item_state = "mining_helm" - item_color = "mining" + hardsuit_type = "mining" max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF heat_protection = HEAD @@ -267,7 +266,7 @@ alt_desc = "A dual-mode advanced helmet designed for work in special operations. It is in combat mode. Property of Gorlex Marauders." icon_state = "hardsuit1-syndi" item_state = "syndie_helm" - item_color = "syndi" + hardsuit_type = "syndi" armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90) on = FALSE var/obj/item/clothing/suit/space/hardsuit/syndi/linkedsuit = null @@ -276,7 +275,7 @@ visor_flags = STOPSPRESSUREDAMAGE /obj/item/clothing/head/helmet/space/hardsuit/syndi/update_icon_state() - icon_state = "hardsuit[on]-[item_color]" + icon_state = "hardsuit[on]-[hardsuit_type]" /obj/item/clothing/head/helmet/space/hardsuit/syndi/Initialize() . = ..() @@ -332,7 +331,7 @@ linkedsuit.clothing_flags &= ~STOPSPRESSUREDAMAGE linkedsuit.cold_protection &= ~(CHEST | GROIN | LEGS | FEET | ARMS | HANDS) - linkedsuit.icon_state = "hardsuit[on]-[item_color]" + linkedsuit.icon_state = "hardsuit[on]-[hardsuit_type]" linkedsuit.update_icon() user.update_inv_wear_suit() user.update_inv_w_uniform() @@ -344,7 +343,7 @@ alt_desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in combat mode. Property of Gorlex Marauders." icon_state = "hardsuit1-syndi" item_state = "syndie_hardsuit" - item_color = "syndi" + hardsuit_type = "syndi" w_class = WEIGHT_CLASS_NORMAL armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90) allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) @@ -358,7 +357,7 @@ desc = "An elite version of the syndicate helmet, with improved armour and fireproofing. It is in EVA mode. Property of Gorlex Marauders." alt_desc = "An elite version of the syndicate helmet, with improved armour and fireproofing. It is in combat mode. Property of Gorlex Marauders." icon_state = "hardsuit0-syndielite" - item_color = "syndielite" + hardsuit_type = "syndielite" armor = list("melee" = 60, "bullet" = 60, "laser" = 50, "energy" = 25, "bomb" = 55, "bio" = 100, "rad" = 70, "fire" = 100, "acid" = 100) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -375,7 +374,7 @@ desc = "An elite version of the syndicate hardsuit, with improved armour and fireproofing. It is in travel mode." alt_desc = "An elite version of the syndicate hardsuit, with improved armour and fireproofing. It is in combat mode." icon_state = "hardsuit0-syndielite" - item_color = "syndielite" + hardsuit_type = "syndielite" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite armor = list("melee" = 60, "bullet" = 60, "laser" = 50, "energy" = 25, "bomb" = 55, "bio" = 100, "rad" = 70, "fire" = 100, "acid" = 100) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -394,7 +393,7 @@ alt_desc = "A dual-mode advanced helmet designed for any crime-fighting situation. It is in combat mode." icon_state = "hardsuit1-owl" item_state = "s_helmet" - item_color = "owl" + hardsuit_type = "owl" visor_flags_inv = 0 visor_flags = 0 on = FALSE @@ -405,7 +404,7 @@ alt_desc = "A dual-mode advanced hardsuit designed for any crime-fighting situation. It is in combat mode." icon_state = "hardsuit1-owl" item_state = "s_suit" - item_color = "owl" + hardsuit_type = "owl" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi/owl mutantrace_variation = STYLE_DIGITIGRADE @@ -416,7 +415,7 @@ desc = "A bizarre gem-encrusted helmet that radiates magical energies." icon_state = "hardsuit0-wiz" item_state = "wiz_helm" - item_color = "wiz" + hardsuit_type = "wiz" resistance_flags = FIRE_PROOF | ACID_PROOF //No longer shall our kind be foiled by lone chemists with spray bottles! armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) heat_protection = HEAD //Uncomment to enable firesuit protection @@ -451,7 +450,7 @@ desc = "A special helmet designed for work in a hazardous, low pressure environment. Built with lightweight materials for extra comfort, but does not protect the eyes from intense light." icon_state = "hardsuit0-medical" item_state = "medical_helm" - item_color = "medical" + hardsuit_type = "medical" flash_protect = 0 armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR @@ -484,7 +483,7 @@ name = "prototype hardsuit helmet" desc = "A prototype helmet designed for research in a hazardous, low pressure environment. Scientific data flashes across the visor." icon_state = "hardsuit0-rd" - item_color = "rd" + hardsuit_type = "rd" resistance_flags = ACID_PROOF | FIRE_PROOF max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80) @@ -526,7 +525,7 @@ desc = "A special helmet designed for work in a hazardous, low pressure environment. Has an additional layer of armor." icon_state = "hardsuit0-sec" item_state = "sec_helm" - item_color = "sec" + hardsuit_type = "sec" armor = list("melee" = 35, "bullet" = 15, "laser" = 30,"energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 75, "acid" = 75) /obj/item/clothing/suit/space/hardsuit/security @@ -547,7 +546,7 @@ name = "head of security's hardsuit helmet" desc = "A special bulky helmet designed for work in a hazardous, low pressure environment. Has an additional layer of armor." icon_state = "hardsuit0-hos" - item_color = "hos" + hardsuit_type = "hos" armor = list("melee" = 45, "bullet" = 25, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 50, "fire" = 95, "acid" = 95) /obj/item/clothing/suit/space/hardsuit/security/hos @@ -596,7 +595,7 @@ icon_state = "hardsuit0-clown" item_state = "hardsuit0-clown" armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 30) - item_color = "clown" + hardsuit_type = "clown" /obj/item/clothing/suit/space/hardsuit/clown name = "cosmohonk hardsuit" @@ -622,7 +621,7 @@ icon_state = "hardsuit0-ancient" item_state = "anc_helm" armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75) - item_color = "ancient" + hardsuit_type = "ancient" resistance_flags = FIRE_PROOF /obj/item/clothing/suit/space/hardsuit/ancient @@ -658,7 +657,7 @@ icon_state = "hardsuit0-ancient" item_state = "anc_helm" armor = list("melee" = 20, "bullet" = 15, "laser" = 15, "energy" = 45, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) - item_color = "ancient" + hardsuit_type = "ancient" brightness_on = 16 flash_protect = 5 //We will not be flash by bombs tint = 1 @@ -720,7 +719,7 @@ name = "soviet hardhelmet" desc = "Crafted with the pride of the proletariat. The vengeful gaze of the visor roots out all fascists and capitalists." item_state = "rig0-soviet" - item_color = "soviet" + hardsuit_type = "soviet" icon_state = "rig0-soviet" armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75) mutantrace_variation = NONE @@ -762,7 +761,13 @@ if(!allowed) allowed = GLOB.advanced_hardsuit_allowed -/obj/item/clothing/suit/space/hardsuit/shielded/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) +/obj/item/clothing/suit/space/hardsuit/shielded/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(current_charges > 0) + block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE] = 100 + block_return[BLOCK_RETURN_BLOCK_CAPACITY] = (block_return[BLOCK_RETURN_BLOCK_CAPACITY] || 0) + current_charges + return ..() + +/obj/item/clothing/suit/space/hardsuit/shielded/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) recharge_cooldown = world.time + recharge_delay if(current_charges > 0) var/datum/effect_system/spark_spread/s = new @@ -776,8 +781,8 @@ owner.visible_message("[owner]'s shield overloads!") shield_state = "broken" owner.update_inv_wear_suit() - return 1 - return 0 + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return BLOCK_NONE /obj/item/clothing/suit/space/hardsuit/shielded/Destroy() STOP_PROCESSING(SSobj, src) @@ -795,7 +800,7 @@ var/mob/living/carbon/human/C = loc C.update_inv_wear_suit() -/obj/item/clothing/suit/space/hardsuit/shielded/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/clothing/suit/space/hardsuit/shielded/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) var/file2use = style_flags & STYLE_ALL_TAURIC ? 'modular_citadel/icons/mob/64x32_effects.dmi' : 'icons/effects/effects.dmi' @@ -811,7 +816,7 @@ desc = "Standard issue hardsuit for playing capture the flag." icon_state = "ert_medical" item_state = "ert_medical" - item_color = "ert_medical" + hardsuit_type = "ert_medical" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95) slowdown = 0 @@ -825,7 +830,7 @@ name = "red shielded hardsuit" icon_state = "ert_security" item_state = "ert_security" - item_color = "ert_security" + hardsuit_type = "ert_security" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red shield_state = "shield-red" shield_on = "shield-red" @@ -842,20 +847,20 @@ desc = "Standard issue hardsuit helmet for playing capture the flag." icon_state = "hardsuit0-ert_medical" item_state = "hardsuit0-ert_medical" - item_color = "ert_medical" + hardsuit_type = "ert_medical" armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95) /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red icon_state = "hardsuit0-ert_security" item_state = "hardsuit0-ert_security" - item_color = "ert_security" + hardsuit_type = "ert_security" /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/blue name = "shielded hardsuit helmet" desc = "Standard issue hardsuit helmet for playing capture the flag." icon_state = "hardsuit0-ert_commander" item_state = "hardsuit0-ert_commander" - item_color = "ert_commander" + hardsuit_type = "ert_commander" //////Syndicate Version @@ -864,7 +869,7 @@ desc = "An advanced hardsuit with built in energy shielding." icon_state = "hardsuit1-syndi" item_state = "syndie_hardsuit" - item_color = "syndi" + hardsuit_type = "syndi" armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi @@ -880,7 +885,7 @@ desc = "An advanced hardsuit helmet with built in energy shielding." icon_state = "hardsuit1-syndi" item_state = "syndie_helm" - item_color = "syndi" + hardsuit_type = "syndi" armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) ///SWAT version @@ -889,7 +894,7 @@ desc = "An advanced hardsuit favored by commandos for use in special operations." icon_state = "deathsquad" item_state = "swat_suit" - item_color = "syndi" + hardsuit_type = "syndi" max_charges = 4 current_charges = 4 recharge_delay = 15 @@ -904,7 +909,7 @@ desc = "A tactical helmet with built in energy shielding." icon_state = "deathsquad" item_state = "deathsquad" - item_color = "syndi" + hardsuit_type = "syndi" armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -919,7 +924,7 @@ desc = "A helmet designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips." icon_state = "knight_cydonia" item_state = "knight_yellow" - item_color = null + hardsuit_type = null max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | LAVA_PROOF heat_protection = HEAD @@ -952,7 +957,7 @@ . = ..() . += mutable_appearance(icon, "knight_cydonia_overlay", color = energy_color) -/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) +/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER) @@ -983,7 +988,7 @@ . = ..() . += mutable_appearance(icon, "knight_cydonia_overlay", color = energy_color) -/obj/item/clothing/suit/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) +/obj/item/clothing/suit/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER) diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index 8c39427c49..e1deb5d28c 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -174,7 +174,7 @@ Contains: desc = "Standard issue command helmet for the ERT." icon_state = "hardsuit0-ert_commander" item_state = "hardsuit0-ert_commander" - item_color = "ert_commander" + hardsuit_type = "ert_commander" armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) strip_delay = 130 brightness_on = 7 @@ -201,7 +201,7 @@ Contains: desc = "Standard issue security helmet for the ERT." icon_state = "hardsuit0-ert_security" item_state = "hardsuit0-ert_security" - item_color = "ert_security" + hardsuit_type = "ert_security" /obj/item/clothing/suit/space/hardsuit/ert/sec desc = "Standard issue security suit for the ERT." @@ -214,7 +214,7 @@ Contains: desc = "Standard issue engineer helmet for the ERT." icon_state = "hardsuit0-ert_engineer" item_state = "hardsuit0-ert_engineer" - item_color = "ert_engineer" + hardsuit_type = "ert_engineer" /obj/item/clothing/suit/space/hardsuit/ert/engi desc = "Standard issue engineer suit for the ERT." @@ -227,7 +227,7 @@ Contains: desc = "Standard issue medical helmet for the ERT." icon_state = "hardsuit0-ert_medical" item_state = "hardsuit0-ert_medical" - item_color = "ert_medical" + hardsuit_type = "ert_medical" /obj/item/clothing/suit/space/hardsuit/ert/med desc = "Standard issue medical suit for the ERT." @@ -243,7 +243,7 @@ Contains: desc = "Red alert command helmet for the ERT. This one is more armored than its standard version." icon_state = "hardsuit0-ert_commander-alert" item_state = "hardsuit0-ert_commander-alert" - item_color = "ert_commander-alert" + hardsuit_type = "ert_commander-alert" armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) brightness_on = 8 resistance_flags = FIRE_PROOF | ACID_PROOF @@ -263,7 +263,7 @@ Contains: desc = "Red alert security helmet for the ERT. This one is more armored than its standard version." icon_state = "hardsuit0-ert_security-alert" item_state = "hardsuit0-ert_security-alert" - item_color = "ert_security-alert" + hardsuit_type = "ert_security-alert" /obj/item/clothing/suit/space/hardsuit/ert/alert/sec desc = "Red alert security suit for the ERT. This one is more armored than its standard version." @@ -276,7 +276,7 @@ Contains: desc = "Red alert engineer helmet for the ERT. This one is more armored than its standard version." icon_state = "hardsuit0-ert_engineer-alert" item_state = "hardsuit0-ert_engineer-alert" - item_color = "ert_engineer-alert" + hardsuit_type = "ert_engineer-alert" /obj/item/clothing/suit/space/hardsuit/ert/alert/engi desc = "Red alert engineer suit for the ERT. This one is more armored than its standard version." @@ -289,7 +289,7 @@ Contains: desc = "Red alert medical helmet for the ERT. This one is more armored than its standard version." icon_state = "hardsuit0-ert_medical-alert" item_state = "hardsuit0-ert_medical-alert" - item_color = "ert_medical-alert" + hardsuit_type = "ert_medical-alert" /obj/item/clothing/suit/space/hardsuit/ert/alert/med desc = "Red alert medical suit for the ERT. This one is more armored than its standard version." @@ -320,7 +320,6 @@ Contains: icon_state = "cespace_helmet" item_state = "nothing" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) - item_color = "engineering" resistance_flags = FIRE_PROOF rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE actions_types = list() @@ -391,7 +390,7 @@ Contains: desc = "A helmet worn by those who deal with paranormal threats for a living." icon_state = "hardsuit0-prt" item_state = "hardsuit0-prt" - item_color = "knight_grey" + hardsuit_type = "knight_grey" max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT actions_types = list() resistance_flags = FIRE_PROOF @@ -456,7 +455,8 @@ Contains: armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0) strip_delay = 65 -/obj/item/clothing/suit/space/fragile/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) +/obj/item/clothing/suit/space/fragile/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + . = ..() if(!torn && prob(50) && damage >= 5) to_chat(owner, "[src] tears from the damage, breaking the air-tight seal!") clothing_flags &= ~STOPSPRESSUREDAMAGE diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index fee8dbce33..f17eb91b74 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -67,7 +67,7 @@ var/datum/action/A=X A.UpdateButtonIcon() -/obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands && on) . += mutable_appearance(icon_file, light_overlay) diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index 1b2080feb1..8de49c63de 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -1,6 +1,7 @@ /obj/item/clothing/suit icon = 'icons/obj/clothing/suits.dmi' name = "suit" + block_priority = BLOCK_PRIORITY_WEAR_SUIT var/fire_resist = T0C+100 allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) @@ -11,7 +12,7 @@ var/suittoggled = FALSE mutantrace_variation = STYLE_DIGITIGRADE -/obj/item/clothing/suit/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) +/obj/item/clothing/suit/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) if(damaged_clothes) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 7384fbde21..a19dfaa889 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -173,12 +173,13 @@ armor = list("melee" = 10, "bullet" = 10, "laser" = 60, "energy" = 50, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF var/hit_reflect_chance = 40 + var/list/protected_zones = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) -/obj/item/clothing/suit/armor/laserproof/IsReflect(def_zone) - if(!(def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN))) //If not shot where ablative is covering you, you don't get the reflection bonus! - return 0 - if (prob(hit_reflect_chance)) - return 1 +/obj/item/clothing/suit/armor/laserproof/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(def_zone in protected_zones) + if(prob(hit_reflect_chance)) + return BLOCK_SHOULD_REDIRECT | BLOCK_REDIRECTED | BLOCK_SUCCESS | BLOCK_PHYSICAL_INTERNAL + return ..() /obj/item/clothing/suit/armor/vest/det_suit name = "detective's armor vest" diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm index 7d56fbe6dd..ce3d2576f9 100644 --- a/code/modules/clothing/suits/cloaks.dm +++ b/code/modules/clothing/suits/cloaks.dm @@ -91,3 +91,14 @@ heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE + +/obj/item/clothing/neck/cloak/polychromic + name = "polychromic cloak" + desc = "For when you want to show off your horrible colour coordination skills." + icon_state = "polyce" + item_state = "qmcloak" + var/list/poly_colors = list("#FFFFFF", "#FFFFFF", "#808080") + +/obj/item/clothing/neck/cloak/polychromic/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, poly_colors, 3) diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 6f61bf56cb..c133ea7c88 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -973,73 +973,12 @@ name = "polychromic winter coat" icon_state = "coatpoly" item_state = "coatpoly" - item_color = "coatpoly" hoodtype = /obj/item/clothing/head/hooded/winterhood/polychromic - hasprimary = TRUE - hassecondary = TRUE - hastertiary = TRUE - primary_color = "#6A6964" - secondary_color = "#C4B8A6" - tertiary_color = "#0000FF" + +/obj/item/clothing/suit/hooded/wintercoat/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, list("#6A6964", "#C4B8A6", "#0000FF"), 3) /obj/item/clothing/head/hooded/winterhood/polychromic icon_state = "winterhood_poly" - item_color = "winterhood_poly" item_state = "winterhood_poly" - -/obj/item/clothing/head/hooded/winterhood/polychromic/worn_overlays(isinhands, icon_file, style_flags = NONE) //this is where the main magic happens. - . = ..() - if(suit.hasprimary | suit.hassecondary) - if(!isinhands) //prevents the worn sprites from showing up if you're just holding them - if(suit.hasprimary) //checks if overlays are enabled - var/mutable_appearance/primary_worn = mutable_appearance(icon_file, "[item_color]-primary") //automagical sprite selection - primary_worn.color = suit.primary_color //colors the overlay - . += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite. - if(suit.hassecondary) - var/mutable_appearance/secondary_worn = mutable_appearance(icon_file, "[item_color]-secondary") - secondary_worn.color = suit.secondary_color - . += secondary_worn - -/obj/item/clothing/suit/hooded/wintercoat/polychromic/worn_overlays(isinhands, icon_file, style_flags = NONE) //this is where the main magic happens. - . = ..() - if(hasprimary | hassecondary | hastertiary) - if(!isinhands) //prevents the worn sprites from showing up if you're just holding them - if(hasprimary) //checks if overlays are enabled - var/mutable_appearance/primary_worn = mutable_appearance(icon_file, "[item_color]-primary[suittoggled ? "_t" : ""]") //automagical sprite selection - primary_worn.color = primary_color //colors the overlay - . += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite. - if(hassecondary) - var/mutable_appearance/secondary_worn = mutable_appearance(icon_file, "[item_color]-secondary[suittoggled ? "_t" : ""]") - secondary_worn.color = secondary_color - . += secondary_worn - if(hastertiary) - var/mutable_appearance/tertiary_worn = mutable_appearance(icon_file, "[item_color]-tertiary[suittoggled ? "_t" : ""]") - tertiary_worn.color = tertiary_color - . += tertiary_worn - -/obj/item/clothing/suit/hooded/wintercoat/AltClick(mob/user) - . = ..() - if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) - return - if(hasprimary | hassecondary | hastertiary) - var/choice = input(user,"polychromic thread options", "Clothing Recolor") as null|anything in list("[hasprimary ? "Primary Color" : ""]", "[hassecondary ? "Secondary Color" : ""]", "[hastertiary ? "Tertiary Color" : ""]") //generates a list depending on the enabled overlays - switch(choice) //Lets the list's options actually lead to something - if("Primary Color") - var/primary_color_input = input(usr,"","Choose Primary Color",primary_color) as color|null //color input menu, the "|null" adds a cancel button to it. - if(primary_color_input) //Checks if the color selected is NULL, rejects it if it is NULL. - primary_color = sanitize_hexcolor(primary_color_input, desired_format=6, include_crunch=1) //formats the selected color properly - update_icon() //updates the item icon - user.regenerate_icons() //updates the worn icon. Probably a bad idea, but it works. - if("Secondary Color") - var/secondary_color_input = input(usr,"","Choose Secondary Color",secondary_color) as color|null - if(secondary_color_input) - secondary_color = sanitize_hexcolor(secondary_color_input, desired_format=6, include_crunch=1) - update_icon() - user.regenerate_icons() - if("Tertiary Color") - var/tertiary_color_input = input(usr,"","Choose Tertiary Color",tertiary_color) as color|null - if(tertiary_color_input) - tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1) - update_icon() - user.regenerate_icons() - return TRUE diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index 87e7098ebd..c8f54f8bda 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -36,8 +36,8 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) actions_types = list(/datum/action/item_action/toggle) resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - hit_reaction_chance = 50 // Only on the chest yet blocks all attacks? rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE + var/hit_reaction_chance = 50 /obj/item/clothing/suit/armor/reactive/attack_self(mob/user) active = !(active) @@ -62,6 +62,14 @@ item_state = "reactiveoff" reactivearmor_cooldown = world.time + 200 +/obj/item/clothing/suit/armor/reactive/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!active) + return BLOCK_NONE + return block_action(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return) + +/obj/item/clothing/suit/armor/reactive/proc/block_action(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + return BLOCK_NONE + //When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!) /obj/item/clothing/suit/armor/reactive/teleport name = "reactive teleport armor" @@ -71,18 +79,15 @@ var/rad_amount_before = 120 reactivearmor_cooldown_duration = 100 -/obj/item/clothing/suit/armor/reactive/teleport/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - . = FALSE - if(!active) - return +/obj/item/clothing/suit/armor/reactive/teleport/block_action(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(prob(hit_reaction_chance)) var/mob/living/carbon/human/H = owner if(world.time < reactivearmor_cooldown) owner.visible_message("The reactive teleport system is still recharging! It fails to teleport [H]!") return owner.visible_message("The reactive teleport system flings [H] clear of [attack_text], shutting itself off in the process!") - playsound(get_turf(owner),'sound/magic/blink.ogg', 100, 1) - var/list/turfs = new/list() + playsound(get_turf(owner), 'sound/magic/blink.ogg', 100, 1) + var/list/turfs = new var/turf/old = get_turf(src) for(var/turf/T in orange(tele_range, H)) if(T.density) @@ -101,7 +106,9 @@ radiation_pulse(old, rad_amount_before) radiation_pulse(src, rad_amount) reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration - return TRUE + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_PASSTHROUGH + return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT | BLOCK_TARGET_DODGED + return BLOCK_NONE //Fire @@ -109,9 +116,7 @@ name = "reactive incendiary armor" desc = "An experimental suit of armor with a reactive sensor array rigged to a flame emitter. For the stylish pyromaniac." -/obj/item/clothing/suit/armor/reactive/fire/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(!active) - return 0 +/obj/item/clothing/suit/armor/reactive/fire/block_action(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(prob(hit_reaction_chance)) if(world.time < reactivearmor_cooldown) owner.visible_message("The reactive incendiary armor on [owner] activates, but fails to send out flames as it is still recharging its flame jets!") @@ -124,8 +129,8 @@ C.IgniteMob() owner.fire_stacks = -20 reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration - return 1 - return 0 + return BLOCK_SUCCESS | BLOCK_PHYSICAL_INTERNAL + return BLOCK_NONE //Stealth @@ -134,9 +139,7 @@ reactivearmor_cooldown_duration = 65 desc = "An experimental suit of armor that renders the wearer invisible on detection of imminent harm, and creates a decoy that runs away from the owner. You can't fight what you can't see." -/obj/item/clothing/suit/armor/reactive/stealth/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(!active) - return 0 +/obj/item/clothing/suit/armor/reactive/stealth/block_action(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(prob(hit_reaction_chance)) if(world.time < reactivearmor_cooldown) owner.visible_message("The reactive stealth system on [owner] activates, but is still recharging its holographic emitters!") @@ -150,7 +153,8 @@ spawn(40) owner.alpha = initial(owner.alpha) reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration - return 1 + return BLOCK_SUCCESS | BLOCK_PHYSICAL_INTERNAL + return BLOCK_NONE //Tesla @@ -175,9 +179,7 @@ if(slot_flags & slotdefine2slotbit(slot)) //Was equipped to a valid slot for this item? user.flags_1 |= TESLA_IGNORE_1 -/obj/item/clothing/suit/armor/reactive/tesla/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(!active) - return FALSE +/obj/item/clothing/suit/armor/reactive/tesla/block_action(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(prob(hit_reaction_chance)) if(world.time < reactivearmor_cooldown) var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread @@ -196,7 +198,8 @@ M.adjustFireLoss(legacy_dmg) playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1) reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration - return TRUE + return BLOCK_SUCCESS | BLOCK_PHYSICAL_INTERNAL + return NONE //Repulse @@ -205,9 +208,7 @@ reactivearmor_cooldown_duration = 20 desc = "An experimental suit of armor that violently throws back attackers." -/obj/item/clothing/suit/armor/reactive/repulse/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(!active) - return 0 +/obj/item/clothing/suit/armor/reactive/repulse/block_action(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(prob(hit_reaction_chance)) if(world.time < reactivearmor_cooldown) owner.visible_message("The repulse generator is still recharging!") @@ -234,7 +235,8 @@ AM.throw_at(throwtarget,10,1) safety-- reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration - return 1 + return BLOCK_SUCCESS | BLOCK_PHYSICAL_INTERNAL + return BLOCK_NONE /obj/item/clothing/suit/armor/reactive/table name = "reactive table armor" @@ -242,9 +244,7 @@ desc = "If you can't beat the memes, embrace them." var/tele_range = 10 -/obj/item/clothing/suit/armor/reactive/table/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(!active) - return 0 +/obj/item/clothing/suit/armor/reactive/table/block_action(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(prob(hit_reaction_chance)) var/mob/living/carbon/human/H = owner if(world.time < reactivearmor_cooldown) @@ -270,8 +270,8 @@ H.forceMove(picked) new /obj/structure/table(get_turf(owner)) reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration - return 1 - return 0 + return BLOCK_SUCCESS | BLOCK_PHYSICAL_INTERNAL + return BLOCK_NONE /obj/item/clothing/suit/armor/reactive/table/emp_act() return diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index cbbd64ebcc..4f29eab6ab 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -6,7 +6,7 @@ var/hoodtype = /obj/item/clothing/head/hooded/winterhood //so the chaplain hoodie or other hoodies can override this /obj/item/clothing/suit/hooded/New() - MakeHood() + hood = MakeHelmet() ..() /obj/item/clothing/suit/hooded/Destroy() @@ -14,11 +14,15 @@ qdel(hood) hood = null -/obj/item/clothing/suit/hooded/proc/MakeHood() +/obj/item/clothing/suit/proc/MakeHelmet(obj/item/clothing/head/H) + SEND_SIGNAL(src, COMSIG_SUIT_MADE_HELMET, H) + return H + +/obj/item/clothing/suit/hooded/MakeHelmet(obj/item/clothing/head/hooded/H) if(!hood) - var/obj/item/clothing/head/hooded/W = new hoodtype(src) - W.suit = src - hood = W + H = new hoodtype(src) + H.suit = src + return ..() /obj/item/clothing/suit/hooded/ui_action_click() ToggleHood() @@ -125,7 +129,7 @@ //Hardsuit toggle code /obj/item/clothing/suit/space/hardsuit/Initialize() - MakeHelmet() + helmet = MakeHelmet() . = ..() /obj/item/clothing/suit/space/hardsuit/Destroy() @@ -140,13 +144,13 @@ suit.helmet = null return ..() -/obj/item/clothing/suit/space/hardsuit/proc/MakeHelmet() +/obj/item/clothing/suit/space/hardsuit/MakeHelmet(obj/item/clothing/head/helmet/space/hardsuit/H) if(!helmettype) return if(!helmet) - var/obj/item/clothing/head/helmet/space/hardsuit/W = new helmettype(src) - W.suit = src - helmet = W + H = new helmettype(src) + H.suit = src + return ..() /obj/item/clothing/suit/space/hardsuit/ui_action_click() ..() diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index cc91391393..fe3aaf4bda 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -3,8 +3,10 @@ name = "under" body_parts_covered = CHEST|GROIN|LEGS|ARMS permeability_coefficient = 0.9 + block_priority = BLOCK_PRIORITY_UNIFORM slot_flags = ITEM_SLOT_ICLOTHING armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + mutantrace_variation = STYLE_DIGITIGRADE var/fitted = FEMALE_UNIFORM_FULL // For use in alternate clothing styles for women var/has_sensor = HAS_SENSORS // For the crew computer var/random_sensor = TRUE @@ -15,30 +17,15 @@ var/dummy_thick = FALSE // is able to hold accessories on its item var/obj/item/clothing/accessory/attached_accessory var/mutable_appearance/accessory_overlay - mutantrace_variation = STYLE_DIGITIGRADE -/obj/item/clothing/under/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() +/obj/item/clothing/under/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) + . = ..() if(isinhands) return if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damageduniform") if(blood_DNA) . += mutable_appearance('icons/effects/blood.dmi', "uniformblood", color = blood_DNA_to_color()) - if(accessory_overlay) - . += accessory_overlay - if(hasprimary) //checks if overlays are enabled - var/mutable_appearance/primary_worn = mutable_appearance(icon_file, "[item_color]-primary") //automagical sprite selection - primary_worn.color = primary_color //colors the overlay - . += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite. - if(hassecondary) - var/mutable_appearance/secondary_worn = mutable_appearance(icon_file, "[item_color]-secondary") - secondary_worn.color = secondary_color - . += secondary_worn - if(hastertiary) - var/mutable_appearance/tertiary_worn = mutable_appearance(icon_file, "[item_color]-tertiary") - tertiary_worn.color = tertiary_color - . += tertiary_worn /obj/item/clothing/under/attackby(obj/item/I, mob/user, params) if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil)) @@ -112,10 +99,8 @@ if((flags_inv & HIDEACCESSORY) || (A.flags_inv & HIDEACCESSORY)) return TRUE - var/accessory_color = attached_accessory.item_color - if(!accessory_color) - accessory_color = attached_accessory.icon_state - accessory_overlay = mutable_appearance('icons/mob/accessories.dmi', "[accessory_color]") + var/accessory_color = attached_accessory.icon_state + accessory_overlay = mutable_appearance('icons/mob/clothing/accessories.dmi', "[accessory_color]") accessory_overlay.alpha = attached_accessory.alpha accessory_overlay.color = attached_accessory.color @@ -166,4 +151,123 @@ if(SENSOR_COORDS) . += "Its vital tracker and tracking beacon appear to be enabled." if(attached_accessory) - . += "\A [attached_accessory] is attached to it." \ No newline at end of file + . += "\A [attached_accessory] is attached to it." + +/obj/item/clothing/under/verb/toggle() + set name = "Adjust Suit Sensors" + set category = "Object" + set src in usr + var/mob/M = usr + if (istype(M, /mob/dead/)) + return + if (!can_use(M)) + return + if(src.has_sensor == LOCKED_SENSORS) + to_chat(usr, "The controls are locked.") + return 0 + if(src.has_sensor == BROKEN_SENSORS) + to_chat(usr, "The sensors have shorted out!") + return 0 + if(src.has_sensor <= NO_SENSORS) + to_chat(usr, "This suit does not have any sensors.") + return 0 + + var/list/modes = list("Off", "Binary vitals", "Exact vitals", "Tracking beacon") + var/switchMode = input("Select a sensor mode:", "Suit Sensor Mode", modes[sensor_mode + 1]) in modes + if(get_dist(usr, src) > 1) + to_chat(usr, "You have moved too far away!") + return + sensor_mode = modes.Find(switchMode) - 1 + + if (src.loc == usr) + switch(sensor_mode) + if(0) + to_chat(usr, "You disable your suit's remote sensing equipment.") + if(1) + to_chat(usr, "Your suit will now only report whether you are alive or dead.") + if(2) + to_chat(usr, "Your suit will now only report your exact vital lifesigns.") + if(3) + to_chat(usr, "Your suit will now report your exact vital lifesigns as well as your coordinate position.") + + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + if(H.w_uniform == src) + H.update_suit_sensors() + + +/obj/item/clothing/under/CtrlClick(mob/user) + . = ..() + + if (!(item_flags & IN_INVENTORY)) + return + + if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + return + + if(has_sensor == LOCKED_SENSORS) + to_chat(user, "The controls are locked.") + return + if(has_sensor == BROKEN_SENSORS) + to_chat(user, "The sensors have shorted out!") + return + if(has_sensor <= NO_SENSORS) + to_chat(user, "This suit does not have any sensors.") + return + + sensor_mode = SENSOR_COORDS + + to_chat(user, "Your suit will now report your exact vital lifesigns as well as your coordinate position.") + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.w_uniform == src) + H.update_suit_sensors() + +/obj/item/clothing/under/AltClick(mob/user) + . = ..() + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + return + if(attached_accessory) + remove_accessory(user) + else + rolldown() + +/obj/item/clothing/under/verb/jumpsuit_adjust() + set name = "Adjust Jumpsuit Style" + set category = null + set src in usr + rolldown() + +/obj/item/clothing/under/proc/rolldown() + if(!can_use(usr)) + return + if(!can_adjust) + to_chat(usr, "You cannot wear this suit any differently!") + return + if(toggle_jumpsuit_adjust()) + to_chat(usr, "You adjust the suit to wear it more casually.") + else + to_chat(usr, "You adjust the suit back to normal.") + if(ishuman(usr)) + var/mob/living/carbon/human/H = usr + H.update_inv_w_uniform() + H.update_body() + +/obj/item/clothing/under/proc/toggle_jumpsuit_adjust() + adjusted = !adjusted + + if(adjusted) + if(fitted != FEMALE_UNIFORM_TOP) + fitted = NO_FEMALE_UNIFORM + if(!alt_covers_chest) // for the special snowflake suits that expose the chest when adjusted + body_parts_covered &= ~CHEST + else + fitted = initial(fitted) + if(!alt_covers_chest) + body_parts_covered |= CHEST + + return adjusted + +/obj/item/clothing/under/rank + dying_key = DYE_REGISTRY_UNDER diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index 628f7187ca..88821e1afe 100644 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -4,7 +4,6 @@ icon = 'icons/obj/clothing/accessories.dmi' icon_state = "plasma" item_state = "" //no inhands - item_color = "plasma" //On accessories, this controls the worn sprite. That's a bit weird. slot_flags = 0 w_class = WEIGHT_CLASS_SMALL var/above_suit = FALSE @@ -85,7 +84,6 @@ desc = "For some classy, murderous fun." icon_state = "waistcoat" item_state = "waistcoat" - item_color = "waistcoat" minimize_when_attached = FALSE /obj/item/clothing/accessory/maidapron @@ -93,7 +91,6 @@ desc = "The best part of a maid costume." icon_state = "maidapron" item_state = "maidapron" - item_color = "maidapron" minimize_when_attached = FALSE ////////// @@ -104,7 +101,6 @@ name = "bronze medal" desc = "A bronze medal." icon_state = "bronze" - item_color = "bronze" custom_materials = list(/datum/material/iron=1000) resistance_flags = FIRE_PROOF var/medaltype = "medal" //Sprite used for medalbox @@ -173,7 +169,6 @@ name = "ribbon" desc = "A ribbon" icon_state = "cargo" - item_color = "cargo" /obj/item/clothing/accessory/medal/ribbon/cargo name = "\"cargo tech of the shift\" award" @@ -188,7 +183,6 @@ name = "silver medal" desc = "A silver medal." icon_state = "silver" - item_color = "silver" medaltype = "medal-silver" custom_materials = list(/datum/material/silver=1000) @@ -204,7 +198,6 @@ name = "gold medal" desc = "A prestigious golden medal." icon_state = "gold" - item_color = "gold" medaltype = "medal-gold" custom_materials = list(/datum/material/gold=1000) @@ -227,7 +220,6 @@ name = "plasma medal" desc = "An eccentric medal made of plasma." icon_state = "plasma" - item_color = "plasma" medaltype = "medal-plasma" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = -10, "acid" = 0) //It's made of plasma. Of course it's flammable. custom_materials = list(/datum/material/plasma=1000) @@ -250,7 +242,6 @@ name = "red armband" desc = "An fancy red armband!" icon_state = "redband" - item_color = "redband" /obj/item/clothing/accessory/armband/deputy name = "security deputy armband" @@ -260,37 +251,31 @@ name = "cargo bay guard armband" desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is brown." icon_state = "cargoband" - item_color = "cargoband" /obj/item/clothing/accessory/armband/engine name = "engineering guard armband" desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is orange with a reflective strip!" icon_state = "engieband" - item_color = "engieband" /obj/item/clothing/accessory/armband/science name = "science guard armband" desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is purple." icon_state = "rndband" - item_color = "rndband" /obj/item/clothing/accessory/armband/hydro name = "hydroponics guard armband" desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is green and blue." icon_state = "hydroband" - item_color = "hydroband" /obj/item/clothing/accessory/armband/med name = "medical guard armband" desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is white." icon_state = "medband" - item_color = "medband" /obj/item/clothing/accessory/armband/medblue name = "medical guard armband" desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is white and blue." icon_state = "medblueband" - item_color = "medblueband" ////////////// //OBJECTION!// @@ -300,7 +285,6 @@ name = "attorney's badge" desc = "Fills you with the conviction of JUSTICE. Lawyers tend to want to show it to everyone they meet." icon_state = "lawyerbadge" - item_color = "lawyerbadge" /obj/item/clothing/accessory/lawyers_badge/attack_self(mob/user) if(prob(1)) @@ -324,7 +308,6 @@ name = "pocket protector" desc = "Can protect your clothing from ink stains, but you'll look like a nerd if you're using one." icon_state = "pocketprotector" - item_color = "pocketprotector" pocket_storage_component_path = /datum/component/storage/concrete/pockets/pocketprotector /obj/item/clothing/accessory/pocketprotector/full/Initialize() @@ -346,14 +329,12 @@ name = "bone talisman" desc = "A hunter's talisman, some say the old gods smile on those who wear it." icon_state = "talisman" - item_color = "talisman" armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 20, "bio" = 20, "rad" = 5, "fire" = 0, "acid" = 25) /obj/item/clothing/accessory/skullcodpiece name = "skull codpiece" desc = "A skull shaped ornament, intended to protect the important things in life." icon_state = "skull" - item_color = "skull" above_suit = TRUE armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 20, "bio" = 20, "rad" = 5, "fire" = 0, "acid" = 25) @@ -361,7 +342,6 @@ name = "false codpiece" desc = "A plastic ornament, intended to protect the important things in life. It's not very good at it." icon_state = "skull" - item_color = "skull" above_suit = TRUE armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) @@ -373,7 +353,6 @@ name = "protective padding" desc = "A soft padding meant to cushion the wearer from melee harm." icon_state = "padding" - item_color = "nothing" armor = list("melee" = 20, "bullet" = 10, "laser" = 0, "energy" = 0, "bomb" = 5, "bio" = 0, "rad" = 0, "fire" = -20, "acid" = 45) flags_inv = HIDEACCESSORY //hidden from indiscrete mob examines. @@ -381,7 +360,6 @@ name = "kevlar padding" desc = "A layered kevlar padding meant to cushion the wearer from ballistic harm." icon_state = "padding" - item_color = "nothing" armor = list("melee" = 10, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 25) flags_inv = HIDEACCESSORY @@ -389,6 +367,5 @@ name = "ablative padding" desc = "A thin ultra-refractory composite padding meant to cushion the wearer from energy lasers harm." icon_state = "plastics" - item_color = "nothing" armor = list("melee" = 0, "bullet" = 0, "laser" = 20, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = -40) flags_inv = HIDEACCESSORY diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index 6b40e08af9..4b04a16b79 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -1,5 +1,6 @@ /obj/item/clothing/under/color desc = "A standard issue colored jumpsuit. Variety is the spice of life!" + dying_key = DYE_REGISTRY_UNDER /obj/item/clothing/under/color/jumpskirt body_parts_covered = CHEST|GROIN|ARMS @@ -38,7 +39,6 @@ name = "black jumpsuit" icon_state = "black" item_state = "bl_suit" - item_color = "black" resistance_flags = NONE /obj/item/clothing/under/color/black/trackless @@ -49,7 +49,6 @@ name = "black jumpskirt" icon_state = "black_skirt" item_state = "bl_suit" - item_color = "black_skirt" /obj/item/clothing/under/color/black/ghost item_flags = DROPDEL @@ -66,138 +65,119 @@ desc = "A tasteful grey jumpsuit that reminds you of the good old days." icon_state = "grey" item_state = "gy_suit" - item_color = "grey" /obj/item/clothing/under/color/jumpskirt/grey name = "grey jumpskirt" desc = "A tasteful grey jumpskirt that reminds you of the good old days." icon_state = "grey_skirt" item_state = "gy_suit" - item_color = "grey_skirt" /obj/item/clothing/under/color/grey/glorf name = "ancient jumpsuit" desc = "A terribly ragged and frayed grey jumpsuit. It looks like it hasn't been washed in over a decade." -/obj/item/clothing/under/color/grey/glorf/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - owner.forcesay(GLOB.hit_appends) - return 0 +/obj/item/clothing/under/color/grey/glorf/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + H.forcesay(GLOB.hit_appends) /obj/item/clothing/under/color/blue name = "blue jumpsuit" icon_state = "blue" item_state = "b_suit" - item_color = "blue" /obj/item/clothing/under/color/jumpskirt/blue name = "blue jumpskirt" icon_state = "blue_skirt" item_state = "b_suit" - item_color = "blue_skirt" /obj/item/clothing/under/color/green name = "green jumpsuit" icon_state = "green" item_state = "g_suit" - item_color = "green" /obj/item/clothing/under/color/jumpskirt/green name = "green jumpskirt" icon_state = "green_skirt" item_state = "g_suit" - item_color = "green_skirt" /obj/item/clothing/under/color/orange name = "orange jumpsuit" desc = "Don't wear this near paranoid security officers." icon_state = "orange" item_state = "o_suit" - item_color = "orange" /obj/item/clothing/under/color/jumpskirt/orange name = "orange jumpskirt" icon_state = "orange_skirt" item_state = "o_suit" - item_color = "orange_skirt" /obj/item/clothing/under/color/pink name = "pink jumpsuit" icon_state = "pink" desc = "Just looking at this makes you feel fabulous." item_state = "p_suit" - item_color = "pink" /obj/item/clothing/under/color/jumpskirt/pink name = "pink jumpskirt" icon_state = "pink_skirt" item_state = "p_suit" - item_color = "pink_skirt" /obj/item/clothing/under/color/red name = "red jumpsuit" icon_state = "red" item_state = "r_suit" - item_color = "red" /obj/item/clothing/under/color/jumpskirt/red name = "red jumpskirt" icon_state = "red_skirt" item_state = "r_suit" - item_color = "red_skirt" /obj/item/clothing/under/color/white name = "white jumpsuit" icon_state = "white" item_state = "w_suit" - item_color = "white" /obj/item/clothing/under/color/jumpskirt/white name = "white jumpskirt" icon_state = "white_skirt" item_state = "w_suit" - item_color = "white_skirt" /obj/item/clothing/under/color/yellow name = "yellow jumpsuit" icon_state = "yellow" item_state = "y_suit" - item_color = "yellow" /obj/item/clothing/under/color/jumpskirt/yellow name = "yellow jumpskirt" icon_state = "yellow_skirt" item_state = "y_suit" - item_color = "yellow_skirt" /obj/item/clothing/under/color/darkblue name = "darkblue jumpsuit" icon_state = "darkblue" item_state = "b_suit" - item_color = "darkblue" /obj/item/clothing/under/color/jumpskirt/darkblue name = "darkblue jumpskirt" icon_state = "darkblue_skirt" item_state = "b_suit" - item_color = "darkblue_skirt" /obj/item/clothing/under/color/teal name = "teal jumpsuit" icon_state = "teal" item_state = "b_suit" - item_color = "teal" /obj/item/clothing/under/color/jumpskirt/teal name = "teal jumpskirt" icon_state = "teal_skirt" item_state = "b_suit" - item_color = "teal_skirt" /obj/item/clothing/under/color/lightpurple name = "purple jumpsuit" icon_state = "lightpurple" item_state = "p_suit" - item_color = "lightpurple" /obj/item/clothing/under/color/lightpurple/trackless desc = "A magically colored jumpsuit. No sensors are attached!" @@ -207,62 +187,52 @@ name = "lightpurple jumpskirt" icon_state = "lightpurple_skirt" item_state = "p_suit" - item_color = "lightpurple_skirt" /obj/item/clothing/under/color/darkgreen name = "darkgreen jumpsuit" icon_state = "darkgreen" item_state = "g_suit" - item_color = "darkgreen" /obj/item/clothing/under/color/jumpskirt/darkgreen name = "darkgreen jumpskirt" icon_state = "darkgreen_skirt" item_state = "g_suit" - item_color = "darkgreen_skirt" /obj/item/clothing/under/color/lightbrown name = "lightbrown jumpsuit" icon_state = "lightbrown" item_state = "lb_suit" - item_color = "lightbrown" /obj/item/clothing/under/color/jumpskirt/lightbrown name = "lightbrown jumpskirt" icon_state = "lightbrown_skirt" item_state = "lb_suit" - item_color = "lightbrown_skirt" /obj/item/clothing/under/color/brown name = "brown jumpsuit" icon_state = "brown" item_state = "lb_suit" - item_color = "brown" /obj/item/clothing/under/color/jumpskirt/brown name = "brown jumpskirt" icon_state = "brown_skirt" item_state = "lb_suit" - item_color = "brown_skirt" /obj/item/clothing/under/color/maroon name = "maroon jumpsuit" icon_state = "maroon" item_state = "r_suit" - item_color = "maroon" /obj/item/clothing/under/color/jumpskirt/maroon name = "maroon jumpskirt" icon_state = "maroon_skirt" item_state = "r_suit" - item_color = "maroon_skirt" /obj/item/clothing/under/color/rainbow name = "rainbow jumpsuit" desc = "A multi-colored jumpsuit!" icon_state = "rainbow" item_state = "rainbow" - item_color = "rainbow" can_adjust = FALSE /obj/item/clothing/under/color/jumpskirt/rainbow @@ -270,5 +240,4 @@ desc = "A multi-colored jumpskirt!" icon_state = "rainbow_skirt" item_state = "rainbow" - item_color = "rainbow_skirt" can_adjust = FALSE diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm index be142a04ff..69a1dc67b3 100644 --- a/code/modules/clothing/under/costume.dm +++ b/code/modules/clothing/under/costume.dm @@ -2,7 +2,6 @@ name = "\improper Roman armor" desc = "Ancient Roman armor. Made of metallic and leather straps." icon_state = "roman" - item_color = "roman" item_state = "armor" can_adjust = FALSE strip_delay = 100 @@ -13,21 +12,18 @@ desc = "The leather club is two sectors down." icon_state = "darkholme" item_state = "darkholme" - item_color = "darkholme" can_adjust = FALSE /obj/item/clothing/under/costume/owl name = "owl uniform" desc = "A soft brown jumpsuit made of synthetic feathers and strong conviction." icon_state = "owl" - item_color = "owl" can_adjust = FALSE /obj/item/clothing/under/costume/griffin name = "griffon uniform" desc = "A soft brown jumpsuit with a white feather collar made of synthetic feathers and a lust for mayhem." icon_state = "griffin" - item_color = "griffin" can_adjust = FALSE /obj/item/clothing/under/costume/schoolgirl @@ -35,7 +31,6 @@ desc = "It's just like one of my Japanese animes!" icon_state = "schoolgirl" item_state = "schoolgirl" - item_color = "schoolgirl" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -44,26 +39,22 @@ name = "red schoolgirl uniform" icon_state = "schoolgirlred" item_state = "schoolgirlred" - item_color = "schoolgirlred" /obj/item/clothing/under/costume/schoolgirl/green name = "green schoolgirl uniform" icon_state = "schoolgirlgreen" item_state = "schoolgirlgreen" - item_color = "schoolgirlgreen" /obj/item/clothing/under/costume/schoolgirl/orange name = "orange schoolgirl uniform" icon_state = "schoolgirlorange" item_state = "schoolgirlorange" - item_color = "schoolgirlorange" /obj/item/clothing/under/costume/pirate name = "pirate outfit" desc = "Yarr." icon_state = "pirate" item_state = "pirate" - item_color = "pirate" can_adjust = FALSE /obj/item/clothing/under/costume/soviet @@ -71,7 +62,6 @@ desc = "For the Motherland!" icon_state = "soviet" item_state = "soviet" - item_color = "soviet" can_adjust = FALSE /obj/item/clothing/under/costume/redcoat @@ -79,7 +69,6 @@ desc = "Looks old." icon_state = "redcoat" item_state = "redcoat" - item_color = "redcoat" can_adjust = FALSE /obj/item/clothing/under/costume/kilt @@ -87,7 +76,6 @@ desc = "Includes shoes and plaid." icon_state = "kilt" item_state = "kilt" - item_color = "kilt" body_parts_covered = CHEST|GROIN|LEGS|FEET fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -103,20 +91,18 @@ name = "polychromic kilt" desc = "It's not a skirt!" icon_state = "polykilt" - item_color = "polykilt" - hasprimary = TRUE - hassecondary = TRUE - primary_color = "#FFFFFF" - secondary_color = "#F08080" body_parts_covered = CHEST|GROIN|ARMS|LEGS mutantrace_variation = NONE +/obj/item/clothing/under/costume/kilt/polychromic/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, list("#FFFFFF", "#F08080"), 2) + /obj/item/clothing/under/costume/gladiator name = "gladiator uniform" desc = "Are you not entertained? Is that not why you are here?" icon_state = "gladiator" item_state = "gladiator" - item_color = "gladiator" body_parts_covered = CHEST|GROIN|ARMS fitted = NO_FEMALE_UNIFORM can_adjust = FALSE @@ -131,7 +117,6 @@ desc = "Maid in China." icon_state = "maid" item_state = "maid" - item_color = "maid" body_parts_covered = CHEST|GROIN fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -146,7 +131,6 @@ desc = "Just looking at this makes you want to sing." icon_state = "ysing" item_state = "ysing" - item_color = "ysing" body_parts_covered = CHEST|GROIN|ARMS fitted = NO_FEMALE_UNIFORM alternate_worn_layer = ABOVE_SHOES_LAYER @@ -157,7 +141,6 @@ desc = "Just looking at this makes you want to sing." icon_state = "bsing" item_state = "bsing" - item_color = "bsing" body_parts_covered = CHEST|GROIN|ARMS alternate_worn_layer = ABOVE_SHOES_LAYER fitted = FEMALE_UNIFORM_TOP @@ -167,7 +150,6 @@ name = "geisha suit" desc = "Cute space ninja senpai not included." icon_state = "geisha" - item_color = "geisha" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE @@ -175,7 +157,6 @@ name = "villain suit" desc = "A change of wardrobe is necessary if you ever want to catch a real superhero." icon_state = "villain" - item_color = "villain" can_adjust = FALSE /obj/item/clothing/under/costume/sailor @@ -183,7 +164,6 @@ desc = "Skipper's in the wardroom drinkin gin'." icon_state = "sailor" item_state = "b_suit" - item_color = "sailor" can_adjust = FALSE /obj/item/clothing/under/costume/russian_officer @@ -191,14 +171,12 @@ desc = "The latest in fashionable russian outfits." icon_state = "hostanclothes" item_state = "hostanclothes" - item_color = "hostanclothes" /obj/item/clothing/under/costume/mummy name = "mummy wrapping" desc = "Return the slab or suffer my stale references." icon_state = "mummy" item_state = "mummy" - item_color = "mummy" body_parts_covered = CHEST|GROIN|ARMS|LEGS fitted = NO_FEMALE_UNIFORM can_adjust = FALSE @@ -209,7 +187,6 @@ desc = "Perfect camouflage for hiding in botany." icon_state = "scarecrow" item_state = "scarecrow" - item_color = "scarecrow" body_parts_covered = CHEST|GROIN|ARMS|LEGS fitted = NO_FEMALE_UNIFORM can_adjust = FALSE @@ -220,7 +197,6 @@ desc = "A dress inspired by the ancient \"Victorian\" era." icon_state = "draculass" item_state = "draculass" - item_color = "draculass" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -230,7 +206,6 @@ desc = "A modified scientist jumpsuit to look extra cool." icon_state = "drfreeze" item_state = "drfreeze" - item_color = "drfreeze" can_adjust = FALSE /obj/item/clothing/under/costume/lobster @@ -238,7 +213,6 @@ desc = "Who beheaded the college mascot?" icon_state = "lobster" item_state = "lobster" - item_color = "lobster" fitted = NO_FEMALE_UNIFORM can_adjust = FALSE @@ -247,7 +221,6 @@ desc = "Now you're cooking." icon_state = "gondola" item_state = "lb_suit" - item_color = "gondola" can_adjust = FALSE /obj/item/clothing/under/costume/skeleton @@ -255,7 +228,6 @@ desc = "A black jumpsuit with a white bone pattern printed on it. Spooky!" icon_state = "skeleton" item_state = "skeleton" - item_color = "skeleton" body_parts_covered = CHEST|GROIN|ARMS|LEGS fitted = NO_FEMALE_UNIFORM can_adjust = FALSE @@ -347,5 +319,4 @@ name = "cloud" desc = "cloud" icon_state = "cloud" - item_color = "cloud" can_adjust = FALSE diff --git a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm index 42902bf7a7..5928819b16 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm @@ -3,70 +3,60 @@ desc = "A joint envirosuit used by plasmamen quartermasters and cargo techs alike, due to the logistical problems of differenciating the two with the length of their pant legs." icon_state = "cargo_envirosuit" item_state = "cargo_envirosuit" - item_color = "cargo_envirosuit" /obj/item/clothing/under/plasmaman/mining name = "mining plasma envirosuit" desc = "An air-tight khaki suit designed for operations on lavaland by plasmamen." icon_state = "explorer_envirosuit" item_state = "explorer_envirosuit" - item_color = "explorer_envirosuit" /obj/item/clothing/under/plasmaman/chef name = "chef's plasma envirosuit" desc = "A white plasmaman envirosuit designed for cullinary practices. One might question why a member of a species that doesn't need to eat would become a chef." icon_state = "chef_envirosuit" item_state = "chef_envirosuit" - item_color = "chef_envirosuit" /obj/item/clothing/under/plasmaman/enviroslacks name = "enviroslacks" desc = "The pet project of a particularly posh plasmaman, this custom suit was quickly appropriated by Nano-Trasen for it's detectives, lawyers, and bar-tenders alike." icon_state = "enviroslacks" item_state = "enviroslacks" - item_color = "enviroslacks" /obj/item/clothing/under/plasmaman/chaplain name = "chaplain's plasma envirosuit" desc = "An envirosuit specially designed for only the most pious of plasmamen." icon_state = "chap_envirosuit" item_state = "chap_envirosuit" - item_color = "chap_envirosuit" /obj/item/clothing/under/plasmaman/curator name = "curator's plasma envirosuit" desc = "Made out of a modified voidsuit, this suit was Nano-Trasen's first solution to the *logistical problems* that come with employing plasmamen. Due to the modifications, the suit is no longer space-worthy. Despite their limitations, these suits are still in used by historian and old-styled plasmamen alike." icon_state = "prototype_envirosuit" item_state = "prototype_envirosuit" - item_color = "prototype_envirosuit" /obj/item/clothing/under/plasmaman/janitor name = "janitor's plasma envirosuit" desc = "A grey and purple envirosuit designated for plasmamen janitors." icon_state = "janitor_envirosuit" item_state = "janitor_envirosuit" - item_color = "janitor_envirosuit" /obj/item/clothing/under/plasmaman/botany name = "botany envirosuit" desc = "A green and blue envirosuit designed to protect plasmamen from minor plant-related injuries." icon_state = "botany_envirosuit" item_state = "botany_envirosuit" - item_color = "botany_envirosuit" /obj/item/clothing/under/plasmaman/hop name = "head of personell's envirosuit" desc = "A prestigious azure envirosuit designed for head of personell." icon_state = "hop_envirosuit" item_state = "hop_envirosuit" - item_color = "hop_envirosuit" /obj/item/clothing/under/plasmaman/captain name = "captain's envirosuit" desc = "An expensive piece of plasmaman envirosuit fashion. guaranteed to keep you cool while the station goes down in fierceful fires." icon_state = "captain_envirosuit" item_state = "captain_envirosuit" - item_color = "captain_envirosuit" armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) sensor_mode = SENSOR_COORDS random_sensor = FALSE @@ -76,14 +66,12 @@ desc = "It's not very colourful." icon_state = "mime_envirosuit" item_state = "mime_envirosuit" - item_color = "mime_envirosuit" /obj/item/clothing/under/plasmaman/clown name = "clown envirosuit" desc = "'HONK!'" icon_state = "clown_envirosuit" item_state = "clown_envirosuit" - item_color = "clown_envirosuit" /obj/item/clothing/under/plasmaman/clown/Extinguish(mob/living/carbon/human/H) if(!istype(H)) diff --git a/code/modules/clothing/under/jobs/Plasmaman/engineering.dm b/code/modules/clothing/under/jobs/Plasmaman/engineering.dm index 1f381df4cf..15eb189fa8 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/engineering.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/engineering.dm @@ -3,7 +3,6 @@ desc = "An air-tight suit designed to be used by plasmamen exployed as engineers, the usual purple stripes being replaced by engineer's orange. It protects the user from fire and acid damage." icon_state = "engineer_envirosuit" item_state = "engineer_envirosuit" - item_color = "engineer_envirosuit" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 95, "acid" = 95) /obj/item/clothing/under/plasmaman/engineering/ce @@ -11,11 +10,9 @@ desc = "An advanced air-tight suit designed to be used by plasmamen chief engineers, complete with ornamental widgets and gizmo. It protects the user from fire and acid damage." icon_state = "ce_envirosuit" item_state = "ce_envirosuit" - item_color = "ce_envirosuit" /obj/item/clothing/under/plasmaman/atmospherics name = "atmospherics plasma envirosuit" desc = "An air-tight suit designed to be used by plasmamen exployed as atmos technicians, the usual purple stripes being replaced by atmos's blue." icon_state = "atmos_envirosuit" item_state = "atmos_envirosuit" - item_color = "atmos_envirosuit" diff --git a/code/modules/clothing/under/jobs/Plasmaman/medsci.dm b/code/modules/clothing/under/jobs/Plasmaman/medsci.dm index 6106d785a9..03d089c10d 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/medsci.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/medsci.dm @@ -3,28 +3,24 @@ desc = "A suit designed for the station's more plasma-based doctors." icon_state = "doctor_envirosuit" item_state = "doctor_envirosuit" - item_color = "doctor_envirosuit" /obj/item/clothing/under/plasmaman/cmo name = "chief medical officer's plasma envirosuit" desc = "A suit designed for the station's most plasma-based chief medical officer, but not for their cat." icon_state = "cmo_envirosuit" item_state = "cmo_envirosuit" - item_color = "cmo_envirosuit" /obj/item/clothing/under/plasmaman/science name = "science plasma envirosuit" desc = "A plasmaman envirosuit designed for scientists." icon_state = "scientist_envirosuit" item_state = "scientist_envirosuit" - item_color = "scientist_envirosuit" /obj/item/clothing/under/plasmaman/rd name = "research direactor's plasma envirosuit" desc = "A plasmaman envirosuit designed for the research director to aid them in their job of directing research into the right direction." icon_state = "rd_envirosuit" item_state = "rd_envirosuit" - item_color = "rd_envirosuit" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) /obj/item/clothing/under/plasmaman/robotics @@ -32,25 +28,21 @@ desc = "A plasmaman envirosuit designed for roboticists." icon_state = "roboticist_envirosuit" item_state = "roboticist_envirosuit" - item_color = "roboticist_envirosuit" /obj/item/clothing/under/plasmaman/viro name = "virology plasma envirosuit" desc = "The suit worn by the safest people on the station, those who are completely immune to the monstrosities they create." icon_state = "virologist_envirosuit" item_state = "virologist_envirosuit" - item_color = "virologist_envirosuit" /obj/item/clothing/under/plasmaman/genetics name = "genetics plasma envirosuit" desc = "A plasmaman envirosuit designed for geneticists." icon_state = "geneticist_envirosuit" item_state = "geneticist_envirosuit" - item_color = "geneticist_envirosuit" /obj/item/clothing/under/plasmaman/chemist name = "chemistry plasma envirosuit" desc = "A plasmaman envirosuit designed for chemists." icon_state = "chemist_envirosuit" item_state = "chemist_envirosuit" - item_color = "chemist_envirosuit" diff --git a/code/modules/clothing/under/jobs/Plasmaman/security.dm b/code/modules/clothing/under/jobs/Plasmaman/security.dm index 6ef9eb9e53..ddbda041f3 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/security.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/security.dm @@ -3,7 +3,6 @@ desc = "A plasmaman containment suit designed for security officers, offering a limited amount of extra protection." icon_state = "security_envirosuit" item_state = "security_envirosuit" - item_color = "security_envirosuit" armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) sensor_mode = SENSOR_COORDS random_sensor = FALSE @@ -13,11 +12,9 @@ desc = "A plasmaman containment suit designed for the warden, white stripes being added to differeciate them from other members of security." icon_state = "warden_envirosuit" item_state = "warden_envirosuit" - item_color = "warden_envirosuit" /obj/item/clothing/under/plasmaman/security/hos name = "security plasma envirosuit" desc = "A slick black and red plasmaman containment suit designed for the head of security, also called the LAW." icon_state = "hos_envirosuit" item_state = "hos_envirosuit" - item_color = "hos_envirosuit" diff --git a/code/modules/clothing/under/jobs/cargo.dm b/code/modules/clothing/under/jobs/cargo.dm index 5727ebc0e9..3ee00996a4 100644 --- a/code/modules/clothing/under/jobs/cargo.dm +++ b/code/modules/clothing/under/jobs/cargo.dm @@ -4,14 +4,12 @@ desc = "It's a jumpsuit worn by the quartermaster. It's specially designed to prevent back injuries caused by pushing paper." icon_state = "qm" item_state = "lb_suit" - item_color = "qm" /obj/item/clothing/under/rank/cargo/qm/skirt name = "quartermaster's jumpskirt" desc = "It's a jumpskirt worn by the quartermaster. It's specially designed to prevent back injuries caused by pushing paper." icon_state = "qm_skirt" item_state = "lb_suit" - item_color = "qm_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -21,7 +19,6 @@ desc = "Shooooorts! They're comfy and easy to wear!" icon_state = "cargotech" item_state = "lb_suit" - item_color = "cargo" body_parts_covered = CHEST|GROIN|ARMS alt_covers_chest = TRUE @@ -30,7 +27,6 @@ desc = "Skiiiiirts! They're comfy and easy to wear" icon_state = "cargo_skirt" item_state = "lb_suit" - item_color = "cargo_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -40,12 +36,10 @@ name = "shaft miner's jumpsuit" icon_state = "miner" item_state = "miner" - item_color = "miner" /obj/item/clothing/under/rank/cargo/miner/lavaland desc = "A green uniform for operating in hazardous environments." name = "shaft miner's jumpsuit" icon_state = "explorer" item_state = "explorer" - item_color = "explorer" can_adjust = FALSE diff --git a/code/modules/clothing/under/jobs/centcom.dm b/code/modules/clothing/under/jobs/centcom.dm index 3ee210612e..33a4659b5f 100644 --- a/code/modules/clothing/under/jobs/centcom.dm +++ b/code/modules/clothing/under/jobs/centcom.dm @@ -3,7 +3,6 @@ name = "\improper CentCom officer's jumpsuit" icon_state = "officer" item_state = "g_suit" - item_color = "officer" alt_covers_chest = TRUE /obj/item/clothing/under/rank/centcom/officer/syndicate @@ -14,4 +13,3 @@ name = "\improper CentCom officer's jumpsuit" icon_state = "centcom" item_state = "dg_suit" - item_color = "centcom" diff --git a/code/modules/clothing/under/jobs/civilian/civilian.dm b/code/modules/clothing/under/jobs/civilian/civilian.dm index ac5f4f12fd..6f1066de5d 100644 --- a/code/modules/clothing/under/jobs/civilian/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian/civilian.dm @@ -3,7 +3,6 @@ name = "bartender's uniform" icon_state = "barman" item_state = "bar_suit" - item_color = "barman" alt_covers_chest = TRUE /obj/item/clothing/under/rank/civilian/bartender/purple @@ -11,7 +10,6 @@ name = "purple bartender's uniform" icon_state = "purplebartender" item_state = "purplebartender" - item_color = "purplebartender" can_adjust = FALSE /obj/item/clothing/under/rank/civilian/bartender/skirt @@ -19,7 +17,6 @@ desc = "It looks like it could use some more flair." icon_state = "barman_skirt" item_state = "bar_suit" - item_color = "barman_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -29,15 +26,13 @@ name = "chaplain's jumpsuit" icon_state = "chaplain" item_state = "bl_suit" - item_color = "chapblack" can_adjust = FALSE /obj/item/clothing/under/rank/civilian/chaplain/skirt name = "chaplain's jumpskirt" desc = "It's a black jumpskirt, often worn by religious folk." - icon_state = "chapblack_skirt" + icon_state = "chaplain_skirt" item_state = "bl_suit" - item_color = "chapblack_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -46,14 +41,12 @@ name = "cook's suit" desc = "A suit which is given only to the most hardcore cooks in space." icon_state = "chef" - item_color = "chef" alt_covers_chest = TRUE /obj/item/clothing/under/rank/civilian/chef/skirt name = "cook's skirt" desc = "A skirt which is given only to the most hardcore cooks in space." icon_state = "chef_skirt" - item_color = "chef_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -63,7 +56,6 @@ name = "head of personnel's jumpsuit" icon_state = "hop" item_state = "b_suit" - item_color = "hop" can_adjust = FALSE /obj/item/clothing/under/rank/civilian/head_of_personnel/skirt @@ -71,7 +63,6 @@ desc = "It's a jumpskirt worn by someone who works in the position of \"Head of Personnel\"." icon_state = "hop_skirt" item_state = "b_suit" - item_color = "hop_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -81,7 +72,6 @@ desc = "A teal suit and yellow necktie. An authoritative yet tacky ensemble." icon_state = "teal_suit" item_state = "g_suit" - item_color = "teal_suit" can_adjust = FALSE /obj/item/clothing/under/rank/civilian/head_of_personnel/suit/skirt @@ -89,7 +79,6 @@ desc = "A teal suitskirt and yellow necktie. An authoritative yet tacky ensemble." icon_state = "teal_suit_skirt" item_state = "g_suit" - item_color = "teal_suit_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -99,7 +88,6 @@ name = "botanist's jumpsuit" icon_state = "hydroponics" item_state = "g_suit" - item_color = "hydroponics" permeability_coefficient = 0.5 /obj/item/clothing/under/rank/civilian/hydroponics/skirt @@ -107,7 +95,6 @@ desc = "It's a jumpskirt designed to protect against minor plant-related hazards." icon_state = "hydroponics_skirt" item_state = "g_suit" - item_color = "hydroponics_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -116,14 +103,12 @@ desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." name = "janitor's jumpsuit" icon_state = "janitor" - item_color = "janitor" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) /obj/item/clothing/under/rank/civilian/janitor/skirt name = "janitor's jumpskirt" desc = "It's the official skirt of the station's janitor. It has minor protection from biohazards." icon_state = "janitor_skirt" - item_color = "janitor_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -133,7 +118,6 @@ desc = "A simple maid uniform for housekeeping." icon_state = "janimaid" item_state = "janimaid" - item_color = "janimaid" body_parts_covered = CHEST|GROIN fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -147,21 +131,18 @@ name = "lawyer black suit" icon_state = "lawyer_black" item_state = "lawyer_black" - item_color = "lawyer_black" /obj/item/clothing/under/rank/civilian/lawyer/black/alt name = "lawyer black suit" desc = "A professional black suit. Nanotrasen Investigation Bureau approved!" icon_state = "blacksuit" item_state = "bar_suit" - item_color = "blacksuit" can_adjust = TRUE alt_covers_chest = TRUE /obj/item/clothing/under/rank/civilian/lawyer/black/alt/skirt name = "lawyer black suitskirt" icon_state = "blacksuit_skirt" - item_color = "blacksuit_skirt" can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -170,14 +151,12 @@ desc = "A formal black suit and red tie, intended for the station's finest." icon_state = "really_black_suit" item_state = "bl_suit" - item_color = "really_black_suit" /obj/item/clothing/under/rank/civilian/lawyer/really_black/skirt name = "executive suitskirt" desc = "A formal black suitskirt and red tie, intended for the station's finest." icon_state = "really_black_suit_skirt" item_state = "bl_suit" - item_color = "really_black_suit_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -186,46 +165,39 @@ name = "lawyer black suitskirt" icon_state = "lawyer_black_skirt" item_state = "lawyer_black" - item_color = "lawyer_black_skirt" fitted = FEMALE_UNIFORM_TOP /obj/item/clothing/under/rank/civilian/lawyer/female name = "female black suit" icon_state = "black_suit_fem" item_state = "bl_suit" - item_color = "black_suit_fem" /obj/item/clothing/under/rank/civilian/lawyer/red name = "lawyer red suit" icon_state = "lawyer_red" item_state = "lawyer_red" - item_color = "lawyer_red" /obj/item/clothing/under/rank/civilian/lawyer/female/skirt name = "female black suitskirt" icon_state = "black_suit_fem_skirt" item_state = "bl_suit" - item_color = "black_suit_fem_skirt" fitted = FEMALE_UNIFORM_TOP /obj/item/clothing/under/rank/civilian/lawyer/red/skirt name = "lawyer red suitskirt" icon_state = "lawyer_red_skirt" item_state = "lawyer_red" - item_color = "lawyer_red_skirt" fitted = FEMALE_UNIFORM_TOP /obj/item/clothing/under/rank/civilian/lawyer/blue name = "lawyer blue suit" icon_state = "lawyer_blue" item_state = "lawyer_blue" - item_color = "lawyer_blue" /obj/item/clothing/under/rank/civilian/lawyer/blue/skirt name = "lawyer blue suitskirt" icon_state = "lawyer_blue_skirt" item_state = "lawyer_blue" - item_color = "lawyer_blue_skirt" fitted = FEMALE_UNIFORM_TOP /obj/item/clothing/under/rank/civilian/lawyer/bluesuit @@ -233,7 +205,6 @@ desc = "A classy suit and tie." icon_state = "bluesuit" item_state = "b_suit" - item_color = "bluesuit" can_adjust = TRUE alt_covers_chest = TRUE @@ -242,7 +213,6 @@ desc = "A classy suitskirt and tie." icon_state = "bluesuit_skirt" item_state = "b_suit" - item_color = "bluesuit_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -251,7 +221,6 @@ name = "purple suit" icon_state = "lawyer_purp" item_state = "p_suit" - item_color = "lawyer_purp" fitted = NO_FEMALE_UNIFORM can_adjust = TRUE alt_covers_chest = TRUE @@ -260,7 +229,6 @@ name = "purple suitskirt" icon_state = "lawyer_purp_skirt" item_state = "p_suit" - item_color = "lawyer_purp_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP diff --git a/code/modules/clothing/under/jobs/civilian/clown_mime.dm b/code/modules/clothing/under/jobs/civilian/clown_mime.dm index 7e85d60dbc..848a15f83b 100644 --- a/code/modules/clothing/under/jobs/civilian/clown_mime.dm +++ b/code/modules/clothing/under/jobs/civilian/clown_mime.dm @@ -4,14 +4,11 @@ desc = "It's not very colourful." icon_state = "mime" item_state = "mime" - item_color = "mime" /obj/item/clothing/under/rank/civilian/mime/skirt name = "mime's skirt" desc = "It's not very colourful." icon_state = "mime_skirt" - item_state = "mime" - item_color = "mime_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -21,7 +18,6 @@ desc = "The only time when you DON'T enjoy looking at someone's rack." icon_state = "sexymime" item_state = "sexymime" - item_color = "sexymime" body_parts_covered = CHEST|GROIN|LEGS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -31,7 +27,6 @@ desc = "'HONK!'" icon_state = "clown" item_state = "clown" - item_color = "clown" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -40,7 +35,6 @@ desc = "'BLUE HONK!'" icon_state = "blueclown" item_state = "blueclown" - item_color = "blueclown" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE mutantrace_variation = NONE @@ -50,7 +44,6 @@ desc = "'GREEN HONK!'" icon_state = "greenclown" item_state = "greenclown" - item_color = "greenclown" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE mutantrace_variation = NONE @@ -60,7 +53,6 @@ desc = "'YELLOW HONK!'" icon_state = "yellowclown" item_state = "yellowclown" - item_color = "yellowclown" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE mutantrace_variation = NONE @@ -70,7 +62,6 @@ desc = "'PURPLE HONK!'" icon_state = "purpleclown" item_state = "purpleclown" - item_color = "purpleclown" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE mutantrace_variation = NONE @@ -80,7 +71,6 @@ desc = "'ORANGE HONK!'" icon_state = "orangeclown" item_state = "orangeclown" - item_color = "orangeclown" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE mutantrace_variation = NONE @@ -90,7 +80,6 @@ desc = "'R A I N B O W HONK!'" icon_state = "rainbowclown" item_state = "rainbowclown" - item_color = "rainbowclown" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE mutantrace_variation = NONE @@ -99,7 +88,6 @@ name = "jester suit" desc = "A jolly dress, well suited to entertain your master, nuncle." icon_state = "jester" - item_color = "jester" can_adjust = FALSE /obj/item/clothing/under/rank/civilian/clown/jester/alt @@ -110,7 +98,6 @@ desc = "It makes you look HONKable!" icon_state = "sexyclown" item_state = "sexyclown" - item_color = "sexyclown" can_adjust = FALSE /obj/item/clothing/under/rank/civilian/clown/Initialize() diff --git a/code/modules/clothing/under/jobs/civilian/curator.dm b/code/modules/clothing/under/jobs/civilian/curator.dm index 741407d71d..792aa64a2b 100644 --- a/code/modules/clothing/under/jobs/civilian/curator.dm +++ b/code/modules/clothing/under/jobs/civilian/curator.dm @@ -3,15 +3,11 @@ desc = "It's very... sensible." icon_state = "red_suit" item_state = "red_suit" - item_color = "red_suit" can_adjust = FALSE /obj/item/clothing/under/rank/civilian/curator/skirt name = "sensible suitskirt" - desc = "It's very... sensible." icon_state = "red_suit_skirt" - item_state = "red_suit" - item_color = "red_suit_skirt" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP @@ -20,14 +16,12 @@ desc = "A rugged uniform suitable for treasure hunting." icon_state = "curator" item_state = "curator" - item_color = "curator" /obj/item/clothing/under/rank/civilian/curator/nasa name = "\improper NASA jumpsuit" desc = "It has a NASA logo on it and is made of space-proofed materials." icon_state = "black" item_state = "bl_suit" - item_color = "black" w_class = WEIGHT_CLASS_BULKY gas_transfer_coefficient = 0.01 permeability_coefficient = 0.02 diff --git a/code/modules/clothing/under/jobs/command.dm b/code/modules/clothing/under/jobs/command.dm index 30560e76b4..885ffaed7a 100644 --- a/code/modules/clothing/under/jobs/command.dm +++ b/code/modules/clothing/under/jobs/command.dm @@ -3,7 +3,6 @@ name = "captain's jumpsuit" icon_state = "captain" item_state = "b_suit" - item_color = "captain" sensor_mode = SENSOR_COORDS random_sensor = FALSE @@ -12,7 +11,6 @@ desc = "It's a blue jumpskirt with some gold markings denoting the rank of \"Captain\"." icon_state = "captain_skirt" item_state = "b_suit" - item_color = "captain_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -22,7 +20,6 @@ desc = "A green suit and yellow necktie. Exemplifies authority." icon_state = "green_suit" item_state = "dg_suit" - item_color = "green_suit" can_adjust = FALSE /obj/item/clothing/under/rank/captain/suit/skirt @@ -30,7 +27,6 @@ desc = "A green suitskirt and yellow necktie. Exemplifies authority." icon_state = "green_suit_skirt" item_state = "dg_suit" - item_color = "green_suit_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -40,7 +36,6 @@ desc = "A captain's luxury-wear, for special occasions." icon_state = "captain_parade" item_state = "by_suit" - item_color = "captain_parade" can_adjust = FALSE /obj/item/clothing/under/rank/captain/femformal @@ -48,6 +43,5 @@ desc = "An ironically skimpy blue dress with gold markings denoting the rank of \"Captain\"." icon_state = "lewdcap" item_state = "lewdcap" - item_color = "lewdcap" can_adjust = FALSE mutantrace_variation = NONE diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index ae0ded5888..365d90e188 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -4,16 +4,14 @@ name = "chief engineer's jumpsuit" icon_state = "chiefengineer" item_state = "gy_suit" - item_color = "chief" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 80, "acid" = 40) resistance_flags = NONE /obj/item/clothing/under/rank/engineering/chief_engineer/skirt name = "chief engineer's jumpskirt" desc = "It's a high visibility jumpskirt given to those engineers insane enough to achieve the rank of \"Chief Engineer\". It has minor radiation shielding." - icon_state = "chief_skirt" + icon_state = "chiefengineer_skirt" item_state = "gy_suit" - item_color = "chief_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -23,7 +21,6 @@ name = "atmospheric technician's jumpsuit" icon_state = "atmos" item_state = "atmos_suit" - item_color = "atmos" resistance_flags = NONE /obj/item/clothing/under/rank/engineering/atmospheric_technician/skirt @@ -31,7 +28,6 @@ desc = "It's a jumpskirt worn by atmospheric technicians." icon_state = "atmos_skirt" item_state = "atmos_suit" - item_color = "atmos_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -41,7 +37,6 @@ name = "engineer's jumpsuit" icon_state = "engine" item_state = "engi_suit" - item_color = "engine" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20) resistance_flags = NONE @@ -50,7 +45,6 @@ desc = "A high visibility jumpsuit made from heat and radiation resistant materials." icon_state = "hazard" item_state = "suit-orange" - item_color = "hazard" alt_covers_chest = TRUE /obj/item/clothing/under/rank/engineering/engineer/skirt @@ -58,7 +52,6 @@ desc = "It's an orange high visibility jumpskirt worn by engineers." icon_state = "engine_skirt" item_state = "engi_suit" - item_color = "engine_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP diff --git a/code/modules/clothing/under/jobs/medical.dm b/code/modules/clothing/under/jobs/medical.dm index 0c2b885bec..d5f4f1f5f9 100644 --- a/code/modules/clothing/under/jobs/medical.dm +++ b/code/modules/clothing/under/jobs/medical.dm @@ -3,7 +3,6 @@ name = "chief medical officer's jumpsuit" icon_state = "cmo" item_state = "w_suit" - item_color = "cmo" permeability_coefficient = 0.5 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) @@ -12,7 +11,6 @@ desc = "It's a jumpskirt worn by those with the experience to be \"Chief Medical Officer\". It provides minor biological protection." icon_state = "cmo_skirt" item_state = "w_suit" - item_color = "cmo_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -20,11 +18,10 @@ /obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck desc = "It's a turtleneck worn by those with the experience to be \"Chief Medical Officer\". It provides minor biological protection, for an officer with a superior sense of style and practicality." name = "chief medical officer's turtleneck" - alternate_worn_icon = 'modular_citadel/icons/mob/clothing/turtlenecks.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/clothing/turtlenecks.dmi' icon = 'modular_citadel/icons/obj/clothing/turtlenecks.dmi' icon_state = "cmoturtle" item_state = "w_suit" - item_color = "cmoturtle" alt_covers_chest = TRUE mutantrace_variation = NONE @@ -33,16 +30,14 @@ name = "geneticist's jumpsuit" icon_state = "genetics" item_state = "w_suit" - item_color = "geneticswhite" permeability_coefficient = 0.5 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) /obj/item/clothing/under/rank/medical/geneticist/skirt name = "geneticist's jumpskirt" desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it." - icon_state = "geneticswhite_skirt" + icon_state = "genetics_skirt" item_state = "w_suit" - item_color = "geneticswhite_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -52,16 +47,14 @@ name = "virologist's jumpsuit" icon_state = "virology" item_state = "w_suit" - item_color = "virologywhite" permeability_coefficient = 0.5 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) /obj/item/clothing/under/rank/medical/virologist/skirt name = "virologist's jumpskirt" desc = "It's made of a special fiber that gives special protection against biohazards. It has a virologist rank stripe on it." - icon_state = "virologywhite_skirt" + icon_state = "virology_skirt" item_state = "w_suit" - item_color = "virologywhite_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -71,16 +64,14 @@ name = "chemist's jumpsuit" icon_state = "chemistry" item_state = "w_suit" - item_color = "chemistrywhite" permeability_coefficient = 0.5 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65) /obj/item/clothing/under/rank/medical/chemist/skirt name = "chemist's jumpskirt" desc = "It's made of a special fiber that gives special protection against biohazards. It has a chemist rank stripe on it." - icon_state = "chemistrywhite_skirt" + icon_state = "chemistry_skirt" item_state = "w_suit" - item_color = "chemistrywhite_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -90,7 +81,6 @@ name = "paramedic jumpsuit" icon_state = "paramedic-dark" item_state = "w_suit" - item_color = "paramedic-dark" permeability_coefficient = 0.5 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) can_adjust = FALSE @@ -98,7 +88,6 @@ /obj/item/clothing/under/rank/medical/paramedic/light desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic." icon_state = "paramedic-light" - item_color = "paramedic-light" can_adjust = TRUE /obj/item/clothing/under/rank/medical/paramedic/skirt @@ -106,7 +95,6 @@ desc = "It's made of a special fiber that provides minor protection against biohazards. It has a white cross on the chest denoting that the wearer is a trained paramedic." icon_state = "paramedic-dark_skirt" item_state = "w_suit" - item_color = "paramedic-dark_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -114,14 +102,12 @@ /obj/item/clothing/under/rank/medical/paramedic/skirt/light desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic." icon_state = "paramedic_skirt" - item_color = "paramedic_skirt" /obj/item/clothing/under/rank/medical/doctor/nurse desc = "It's a jumpsuit commonly worn by nursing staff in the medical department." name = "nurse's suit" icon_state = "nursesuit" item_state = "w_suit" - item_color = "nursesuit" permeability_coefficient = 0.5 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) body_parts_covered = CHEST|GROIN|ARMS @@ -133,7 +119,6 @@ name = "medical doctor's jumpsuit" icon_state = "medical" item_state = "w_suit" - item_color = "medical" permeability_coefficient = 0.5 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) @@ -141,21 +126,18 @@ name = "blue medical scrubs" desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue." icon_state = "scrubsblue" - item_color = "scrubsblue" can_adjust = FALSE /obj/item/clothing/under/rank/medical/doctor/green name = "green medical scrubs" desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in dark green." icon_state = "scrubsgreen" - item_color = "scrubsgreen" can_adjust = FALSE /obj/item/clothing/under/rank/medical/doctor/purple name = "purple medical scrubs" desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in deep purple." icon_state = "scrubspurple" - item_color = "scrubspurple" can_adjust = FALSE /obj/item/clothing/under/rank/medical/doctor/skirt @@ -163,7 +145,6 @@ desc = "It's made of a special fiber that provides minor protection against biohazards. It has a cross on the chest denoting that the wearer is trained medical personnel." icon_state = "medical_skirt" item_state = "w_suit" - item_color = "medical_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE - fitted = FEMALE_UNIFORM_TOP \ No newline at end of file + fitted = FEMALE_UNIFORM_TOP diff --git a/code/modules/clothing/under/jobs/rnd.dm b/code/modules/clothing/under/jobs/rnd.dm index 5af6ce26bf..71c5766849 100644 --- a/code/modules/clothing/under/jobs/rnd.dm +++ b/code/modules/clothing/under/jobs/rnd.dm @@ -3,7 +3,6 @@ name = "research director's vest suit" icon_state = "director" item_state = "lb_suit" - item_color = "director" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 35) can_adjust = FALSE @@ -12,7 +11,6 @@ desc = "It's a suitskirt worn by those with the know-how to achieve the position of \"Research Director\". Its fabric provides minor protection from biological contaminants." icon_state = "director_skirt" item_state = "lb_suit" - item_color = "director_skirt" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP @@ -21,7 +19,6 @@ name = "research director's tan suit" icon_state = "rdwhimsy" item_state = "rdwhimsy" - item_color = "rdwhimsy" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) can_adjust = TRUE alt_covers_chest = TRUE @@ -31,7 +28,6 @@ desc = "Maybe you'll engineer your own half-man, half-pig creature some day. Its fabric provides minor protection from biological contaminants." icon_state = "rdwhimsy_skirt" item_state = "rdwhimsy" - item_color = "rdwhimsy_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -41,7 +37,6 @@ name = "research director's turtleneck" icon_state = "rdturtle" item_state = "p_suit" - item_color = "rdturtle" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) can_adjust = TRUE alt_covers_chest = TRUE @@ -51,7 +46,6 @@ desc = "A dark purple turtleneck and tan khaki skirt, for a director with a superior sense of style." icon_state = "rdturtle_skirt" item_state = "p_suit" - item_color = "rdturtle_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -61,16 +55,14 @@ name = "scientist's jumpsuit" icon_state = "toxins" item_state = "w_suit" - item_color = "toxinswhite" permeability_coefficient = 0.5 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) /obj/item/clothing/under/rank/rnd/scientist/skirt name = "scientist's jumpskirt" desc = "It's made of a special fiber that provides minor protection against explosives. It has markings that denote the wearer as a scientist." - icon_state = "toxinswhite_skirt" + icon_state = "toxins_skirt" item_state = "w_suit" - item_color = "toxinswhite_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -80,7 +72,6 @@ name = "roboticist's jumpsuit" icon_state = "robotics" item_state = "robotics" - item_color = "robotics" resistance_flags = NONE /obj/item/clothing/under/rank/rnd/roboticist/skirt @@ -88,7 +79,6 @@ desc = "It's a slimming black with reinforced seams; great for industrial work." icon_state = "robotics_skirt" item_state = "robotics" - item_color = "robotics_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index e91125c152..0d4b916610 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -19,7 +19,6 @@ desc = "A tactical security jumpsuit for officers complete with Nanotrasen belt buckle." icon_state = "rsecurity" item_state = "r_suit" - item_color = "rsecurity" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) /obj/item/clothing/under/rank/security/officer/grey @@ -27,14 +26,12 @@ desc = "A tactical relic of years past before Nanotrasen decided it was cheaper to dye the suits red instead of washing out the blood." icon_state = "security" item_state = "gy_suit" - item_color = "security" /obj/item/clothing/under/rank/security/officer/skirt name = "security jumpskirt" desc = "A \"tactical\" security jumpsuit with the legs replaced by a skirt." icon_state = "secskirt" item_state = "r_suit" - item_color = "secskirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE //you know now that i think of it if you adjust the skirt and the sprite disappears isn't that just like flashing everyone fitted = FEMALE_UNIFORM_TOP @@ -44,7 +41,6 @@ desc = "The latest in fashionable security outfits." icon_state = "officerblueclothes" item_state = "officerblueclothes" - item_color = "officerblueclothes" alt_covers_chest = TRUE /obj/item/clothing/under/rank/security/officer/blueshirt @@ -52,7 +48,6 @@ desc = "I'm a little busy right now, Calhoun." icon_state = "blueshift" item_state = "blueshift" - item_color = "blueshift" can_adjust = FALSE /obj/item/clothing/under/rank/security/officer/spacepol @@ -60,7 +55,6 @@ desc = "Space not controlled by megacorporations, planets, or pirates is under the jurisdiction of Spacepol." icon_state = "spacepol" item_state = "spacepol" - item_color = "spacepol" can_adjust = FALSE /* @@ -72,7 +66,6 @@ desc = "A formal security suit for officers complete with Nanotrasen belt buckle." icon_state = "rwarden" item_state = "r_suit" - item_color = "rwarden" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) /obj/item/clothing/under/rank/security/warden/grey @@ -80,14 +73,12 @@ desc = "A formal relic of years past before Nanotrasen decided it was cheaper to dye the suits red instead of washing out the blood." icon_state = "warden" item_state = "gy_suit" - item_color = "warden" /obj/item/clothing/under/rank/security/warden/skirt name = "warden's suitskirt" desc = "A formal security suitskirt for officers complete with Nanotrasen belt buckle." icon_state = "rwarden_skirt" item_state = "r_suit" - item_color = "rwarden_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -97,7 +88,6 @@ name = "warden's formal uniform" icon_state = "wardenblueclothes" item_state = "wardenblueclothes" - item_color = "wardenblueclothes" alt_covers_chest = TRUE /* @@ -109,7 +99,6 @@ desc = "Someone who wears this means business." icon_state = "detective" item_state = "det" - item_color = "detective" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) /obj/item/clothing/under/rank/security/detective/skirt @@ -117,7 +106,6 @@ desc = "Someone who wears this means business." icon_state = "detective_skirt" item_state = "det" - item_color = "detective_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -127,14 +115,12 @@ desc = "A hard-boiled private investigator's grey suit, complete with tie clip." icon_state = "greydet" item_state = "greydet" - item_color = "greydet" /obj/item/clothing/under/rank/security/detective/grey/skirt name = "noir suitskirt" desc = "A hard-boiled private investigator's grey suitskirt, complete with tie clip." icon_state = "greydet_skirt" item_state = "greydet" - item_color = "greydet_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -148,7 +134,6 @@ desc = "A security jumpsuit decorated for those few with the dedication to achieve the position of Head of Security." icon_state = "rhos" item_state = "r_suit" - item_color = "rhos" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) strip_delay = 60 @@ -157,7 +142,6 @@ desc = "A security jumpskirt decorated for those few with the dedication to achieve the position of Head of Security." icon_state = "rhos_skirt" item_state = "r_suit" - item_color = "rhos_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -167,21 +151,18 @@ desc = "There are old men, and there are bold men, but there are very few old, bold men." icon_state = "hos" item_state = "gy_suit" - item_color = "hos" /obj/item/clothing/under/rank/security/head_of_security/alt name = "head of security's turtleneck" desc = "A stylish alternative to the normal head of security jumpsuit, complete with tactical pants." icon_state = "hosalt" item_state = "bl_suit" - item_color = "hosalt" /obj/item/clothing/under/rank/security/head_of_security/alt/skirt name = "head of security's turtleneck skirt" desc = "A stylish alternative to the normal head of security jumpsuit, complete with a tactical skirt." icon_state = "hosalt_skirt" item_state = "bl_suit" - item_color = "hosalt_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -191,14 +172,12 @@ name = "head of security's formal uniform" icon_state = "hosblueclothes" item_state = "hosblueclothes" - item_color = "hosblueclothes" /obj/item/clothing/under/rank/security/head_of_security/parade name = "head of security's parade uniform" desc = "A male head of security's luxury-wear, for special occasions." icon_state = "hos_parade_male" item_state = "r_suit" - item_color = "hos_parade_male" can_adjust = FALSE /obj/item/clothing/under/rank/security/head_of_security/parade/female @@ -206,5 +185,4 @@ desc = "A female head of security's luxury-wear, for special occasions." icon_state = "hos_parade_fem" item_state = "r_suit" - item_color = "hos_parade_fem" fitted = FEMALE_UNIFORM_TOP diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index fb5ff7b0f4..d475ca8100 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -2,7 +2,6 @@ name = "red pj's" desc = "Sleepwear." icon_state = "red_pyjamas" - item_color = "red_pyjamas" item_state = "w_suit" can_adjust = FALSE @@ -10,7 +9,6 @@ name = "blue pj's" desc = "Sleepwear." icon_state = "blue_pyjamas" - item_color = "blue_pyjamas" item_state = "w_suit" can_adjust = FALSE @@ -19,7 +17,6 @@ desc = "Motorcycle not included." icon_state = "ek" item_state = "ek" - item_color = "ek" can_adjust = FALSE /obj/item/clothing/under/rank/prisoner @@ -27,7 +24,6 @@ desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position." icon_state = "prisoner" item_state = "o_suit" - item_color = "prisoner" has_sensor = LOCKED_SENSORS sensor_mode = SENSOR_COORDS random_sensor = FALSE @@ -37,7 +33,6 @@ desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position." icon_state = "prisoner_skirt" item_state = "o_suit" - item_color = "prisoner_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -47,21 +42,18 @@ desc = "'Special delivery!'" icon_state = "mailman" item_state = "b_suit" - item_color = "mailman" /obj/item/clothing/under/misc/psyche name = "psychedelic jumpsuit" desc = "Groovy!" icon_state = "psyche" item_state = "p_suit" - item_color = "psyche" /obj/item/clothing/under/misc/vice_officer name = "vice officer's jumpsuit" desc = "It's the standard issue pretty-boy outfit, as seen on Holo-Vision." icon_state = "vice" item_state = "gy_suit" - item_color = "vice" can_adjust = FALSE @@ -69,7 +61,6 @@ name = "administrative cybernetic jumpsuit" icon_state = "syndicate" item_state = "bl_suit" - item_color = "syndicate" desc = "A cybernetically enhanced jumpsuit used for administrative duties." gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 @@ -87,7 +78,6 @@ desc = "Traditional burial garments from the early 22nd century." icon_state = "burial" item_state = "burial" - item_color = "burial" has_sensor = NO_SENSORS /obj/item/clothing/under/misc/overalls @@ -95,7 +85,6 @@ desc = "A set of durable overalls for getting the job done." icon_state = "overalls" item_state = "lb_suit" - item_color = "overalls" can_adjust = FALSE /obj/item/clothing/under/misc/assistantformal @@ -103,24 +92,21 @@ desc = "An assistant's formal-wear. Why an assistant needs formal-wear is still unknown." icon_state = "assistant_formal" item_state = "gy_suit" - item_color = "assistant_formal" can_adjust = FALSE /obj/item/clothing/under/misc/staffassistant name = "staff assistant's jumpsuit" desc = "It's a generic grey jumpsuit. That's about what assistants are worth, anyway." icon = 'goon/icons/obj/item_js_rank.dmi' - alternate_worn_icon = 'goon/icons/mob/worn_js_rank.dmi' + mob_overlay_icon = 'goon/icons/mob/worn_js_rank.dmi' icon_state = "assistant" item_state = "gy_suit" - item_color = "assistant" mutantrace_variation = NONE /obj/item/clothing/under/croptop name = "crop top" desc = "We've saved money by giving you half a shirt!" icon_state = "croptop" - item_color = "croptop" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -130,7 +116,6 @@ desc = "A special containment suit that allows plasma-based lifeforms to exist safely in an oxygenated environment, and automatically extinguishes them in a crisis. Despite being airtight, it's not spaceworthy." icon_state = "plasmaman" item_state = "plasmaman" - item_color = "plasmaman" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) slowdown = 1 body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -170,7 +155,6 @@ to_chat(user, "You refill the suit's built-in extinguisher, using up the cartridge.") qdel(E) return - return return /obj/item/extinguisher_refill @@ -192,7 +176,6 @@ desc = "A jumpsuit made from durathread, its resilient fibres provide some protection to the wearer." icon_state = "durathread" item_state = "durathread" - item_color = "durathread" can_adjust = TRUE armor = list("melee" = 10, "laser" = 10, "fire" = 40, "acid" = 10, "bomb" = 5) @@ -209,7 +192,6 @@ desc = "Cyka blyat." icon_state = "squatteroutfit" item_state = "squatteroutfit" - item_color = "squatteroutfit" can_adjust = FALSE mutantrace_variation = NONE @@ -218,7 +200,6 @@ desc = "Drop and give me dvadtsat!" icon_state = "russobluecamo" item_state = "russobluecamo" - item_color = "russobluecamo" can_adjust = FALSE mutantrace_variation = NONE @@ -227,7 +208,6 @@ desc = "What is the point of this, anyway?" icon_state = "keyholesweater" item_state = "keyholesweater" - item_color = "keyholesweater" can_adjust = FALSE mutantrace_variation = NONE @@ -235,7 +215,6 @@ name = "pink stripper outfit" icon_state = "stripper_p" item_state = "stripper_p" - item_color = "stripper_p" body_parts_covered = CHEST|GROIN can_adjust = FALSE @@ -243,13 +222,11 @@ name = "green stripper outfit" icon_state = "stripper_g" item_state = "stripper_g" - item_color = "stripper_g" /obj/item/clothing/under/misc/stripper/mankini name = "pink mankini" icon_state = "mankini" item_state = "mankini" - item_color = "mankini" /obj/item/clothing/under/misc/corporateuniform name = "corporate uniform" @@ -263,76 +240,68 @@ name = "polychromic button-up shirt" desc = "A fancy button-up shirt made with polychromic threads." icon_state = "polysuit" - item_color = "polysuit" item_state = "sl_suit" - hasprimary = TRUE - hassecondary = TRUE - hastertiary = TRUE - primary_color = "#FFFFFF" - secondary_color = "#353535" - tertiary_color = "#353535" mutantrace_variation = NONE +/obj/item/clothing/under/misc/poly_shirt/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, list("#FFFFFF", "#353535", "#353535"), 3) + /obj/item/clothing/under/misc/polyshorts name = "polychromic shorts" desc = "For ease of movement and style." icon_state = "polyshorts" - item_color = "polyshorts" item_state = "rainbow" - hasprimary = TRUE - hassecondary = TRUE - hastertiary = TRUE - primary_color = "#353535" - secondary_color = "#808080" - tertiary_color = "#808080" can_adjust = FALSE body_parts_covered = CHEST|GROIN|ARMS +/obj/item/clothing/under/misc/polyshorts/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, list("#353535", "#808080", "#808080"), 3) + /obj/item/clothing/under/misc/polyjumpsuit name = "polychromic tri-tone jumpsuit" desc = "A fancy jumpsuit made with polychromic threads." icon_state = "polyjump" - item_color = "polyjump" item_state = "rainbow" - hasprimary = TRUE - hassecondary = TRUE - hastertiary = TRUE - primary_color = "#FFFFFF" - secondary_color = "#808080" - tertiary_color = "#FF3535" can_adjust = FALSE mutantrace_variation = NONE +/obj/item/clothing/under/misc/polyjumpsuit/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, list("#FFFFFF", "#808080", "#353535"), 3) + /obj/item/clothing/under/misc/poly_bottomless name = "polychromic bottomless shirt" - desc = "Great for showing off your junk in dubious style." + desc = "Great for showing off your underwear in dubious style." icon_state = "polybottomless" - item_color = "polybottomless" item_state = "rainbow" - primary_color = "#808080" - secondary_color = "#FF3535" body_parts_covered = CHEST|ARMS //Because there's no bottom included can_adjust = FALSE mutantrace_variation = NONE +/obj/item/clothing/under/misc/poly_bottomless/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, list("#808080", "#FF3535"), 2) + /obj/item/clothing/under/misc/poly_tanktop name = "polychromic tank top" desc = "For those lazy summer days." icon_state = "polyshimatank" - item_color = "polyshimatank" item_state = "rainbow" - primary_color = "#808080" - secondary_color = "#FFFFFF" - tertiary_color = "#8CC6FF" body_parts_covered = CHEST|GROIN can_adjust = FALSE mutantrace_variation = NONE + var/list/poly_states = 3 + var/list/poly_colors = list("#808080", "#FFFFFF", "#8CC6FF") + +/obj/item/clothing/under/misc/poly_tanktop/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, poly_colors, poly_states) /obj/item/clothing/under/misc/poly_tanktop/female name = "polychromic feminine tank top" desc = "Great for showing off your chest in style. Not recommended for males." icon_state = "polyfemtankpantsu" - item_color = "polyfemtankpantsu" - hastertiary = FALSE - primary_color = "#808080" - secondary_color = "#FF3535" + poly_states = 2 + poly_colors = list("#808080", "#FF3535") diff --git a/code/modules/clothing/under/pants.dm b/code/modules/clothing/under/pants.dm index 4b0c92af88..d0048326ff 100644 --- a/code/modules/clothing/under/pants.dm +++ b/code/modules/clothing/under/pants.dm @@ -8,101 +8,84 @@ name = "classic jeans" desc = "You feel cooler already." icon_state = "jeansclassic" - item_color = "jeansclassic" /obj/item/clothing/under/pants/mustangjeans name = "Must Hang jeans" desc = "Made in the finest space jeans factory this side of Alpha Centauri." icon_state = "jeansmustang" - item_color = "jeansmustang" /obj/item/clothing/under/pants/blackjeans name = "black jeans" desc = "Only for those who can pull it off." icon_state = "jeansblack" - item_color = "jeansblack" /obj/item/clothing/under/pants/youngfolksjeans name = "Young Folks jeans" desc = "For those tired of boring old jeans. Relive the passion of your youth!" icon_state = "jeansyoungfolks" - item_color = "jeansyoungfolks" /obj/item/clothing/under/pants/white name = "white pants" desc = "Plain white pants. Boring." icon_state = "whitepants" - item_color = "whitepants" /obj/item/clothing/under/pants/red name = "red pants" desc = "Bright red pants. Overflowing with personality." icon_state = "redpants" - item_color = "redpants" /obj/item/clothing/under/pants/black name = "black pants" desc = "These pants are dark, like your soul." icon_state = "blackpants" - item_color = "blackpants" /obj/item/clothing/under/pants/tan name = "tan pants" desc = "Some tan pants. You look like a white collar worker with these on." icon_state = "tanpants" - item_color = "tanpants" /obj/item/clothing/under/pants/track name = "track pants" desc = "A pair of track pants, for the athletic." icon_state = "trackpants" - item_color = "trackpants" /obj/item/clothing/under/pants/jeans name = "jeans" desc = "A nondescript pair of tough blue jeans." icon_state = "jeans" - item_color = "jeans" /obj/item/clothing/under/pants/khaki name = "khaki pants" desc = "A pair of dust beige khaki pants." icon_state = "khaki" - item_color = "khaki" /obj/item/clothing/under/pants/camo name = "camo pants" desc = "A pair of woodland camouflage pants. Probably not the best choice for a space station." icon_state = "camopants" - item_color = "camopants" /obj/item/clothing/under/pants/jeanripped name = "ripped jeans" desc = "If you're wearing this you're poor or a rebel" icon_state = "jean_ripped" - item_color = "jean_ripped" /obj/item/clothing/under/pants/jeanshort name = "jean shorts" desc = "These are really just jeans cut in half" icon_state = "jean_shorts" - item_color = "jean_shorts" /obj/item/clothing/under/pants/denimskirt name = "denim skirt" desc = "These are really just a jean leg hole cut from a pair" icon_state = "denim_skirt" - item_color = "denim_skirt" /obj/item/clothing/under/pants/chaps name = "black chaps" body_parts_covered = LEGS desc = "Yeehaw" icon_state = "chaps" - item_color = "chaps" /obj/item/clothing/under/pants/yoga name = "yoga pants" desc = "Comfy!" icon_state = "yoga_pants" - item_color = "yoga_pants" diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm index b66df87347..f61a41e4c3 100644 --- a/code/modules/clothing/under/shorts.dm +++ b/code/modules/clothing/under/shorts.dm @@ -9,53 +9,44 @@ /obj/item/clothing/under/shorts/red name = "red athletic shorts" icon_state = "redshorts" - item_color = "redshorts" /obj/item/clothing/under/shorts/green name = "green athletic shorts" icon_state = "greenshorts" - item_color = "greenshorts" /obj/item/clothing/under/shorts/blue name = "blue athletic shorts" icon_state = "blueshorts" - item_color = "blueshorts" /obj/item/clothing/under/shorts/black name = "black athletic shorts" icon_state = "blackshorts" - item_color = "blackshorts" /obj/item/clothing/under/shorts/grey name = "grey athletic shorts" icon_state = "greyshorts" - item_color = "greyshorts" /obj/item/clothing/under/shorts/purple name = "purple athletic shorts" icon_state = "purpleshorts" - item_color = "purpleshorts" /obj/item/clothing/under/shorts/polychromic name = "polychromic athletic shorts" desc = "95% Polychrome, 5% Spandex!" icon_state = "polyshortpants" - item_color = "polyshortpants" item_state = "rainbow" - hasprimary = TRUE - hassecondary = TRUE - primary_color = "#FFFFFF" - secondary_color = "#F08080" mutantrace_variation = NONE + var/list/poly_colors = list("#FFFFFF", "#F08080") + +/obj/item/clothing/under/shorts/polychromic/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, poly_colors, 2) /obj/item/clothing/under/shorts/polychromic/pantsu name = "polychromic panties" desc = "Topless striped panties. Now with 120% more polychrome!" icon_state = "polypantsu" - item_color = "polypantsu" item_state = "rainbow" - hastertiary = FALSE - primary_color = "#FFFFFF" - secondary_color = "#8CC6FF" body_parts_covered = GROIN mutantrace_variation = NONE + poly_colors = list("#FFFFFF", "#8CC6FF") diff --git a/code/modules/clothing/under/skirt_dress.dm b/code/modules/clothing/under/skirt_dress.dm index 02c2b06546..fa2c9eed71 100644 --- a/code/modules/clothing/under/skirt_dress.dm +++ b/code/modules/clothing/under/skirt_dress.dm @@ -3,7 +3,6 @@ name = "black skirt" desc = "A black skirt, very fancy!" icon_state = "blackskirt" - item_color = "blackskirt" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -12,7 +11,6 @@ name = "blue skirt" desc = "A blue, casual skirt." icon_state = "blueskirt" - item_color = "blueskirt" item_state = "b_suit" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP @@ -22,7 +20,6 @@ name = "red skirt" desc = "A red, casual skirt." icon_state = "redskirt" - item_color = "redskirt" item_state = "r_suit" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP @@ -32,7 +29,6 @@ name = "purple skirt" desc = "A purple, casual skirt." icon_state = "purpleskirt" - item_color = "purpleskirt" item_state = "p_suit" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP @@ -43,7 +39,6 @@ desc = "Makes you want to frolic in a field of daisies." icon_state = "sundress" item_state = "sundress" - item_color = "sundress" body_parts_covered = CHEST|GROIN fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -51,13 +46,11 @@ /obj/item/clothing/under/dress/sundress/white name = "white sundress" icon_state = "sundress_white" - item_color = "sundress_white" /obj/item/clothing/under/dress/green name = "green dress" desc = "A tight green dress" icon_state = "dress_green" - item_color = "dress_green" body_parts_covered = CHEST|GROIN fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -66,7 +59,6 @@ name = "pink dress" desc = "A tight pink dress" icon_state = "dress_pink" - item_color = "dress_pink" body_parts_covered = CHEST|GROIN fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -76,7 +68,6 @@ desc = "Filled with Latin fire." icon_state = "black_tango" item_state = "wcoat" - item_color = "black_tango" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -85,7 +76,6 @@ desc = "Filled with Western fire." icon_state = "western_bustle" item_state = "wcoat" - item_color = "western_bustle" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -94,7 +84,6 @@ desc = "Filled with Latin fire." icon_state = "flamenco" item_state = "wcoat" - item_color = "flamenco" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -103,7 +92,6 @@ desc = "Fashion in space." icon_state = "striped_dress" item_state = "stripeddress" - item_color = "striped_dress" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_FULL can_adjust = FALSE @@ -113,7 +101,6 @@ desc = "Formal wear for a leading lady." icon_state = "sailor_dress" item_state = "sailordress" - item_color = "sailor_dress" body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -123,7 +110,6 @@ desc = "Lovely dress." icon_state = "flower_dress" item_state = "sailordress" - item_color = "flower_dress" body_parts_covered = CHEST|GROIN|LEGS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -132,7 +118,6 @@ name = "swept skirt" desc = "Formal skirt." icon_state = "skirt_swept" - item_color = "skirt_swept" body_parts_covered = GROIN fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -141,7 +126,6 @@ name = "black corset" desc = "Nanotrasen is not resposible for any organ damage." icon_state = "corset" - item_color = "corset" body_parts_covered = CHEST|GROIN fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -151,7 +135,6 @@ desc = "Fancy dress for space bar singers." icon_state = "red_evening_gown" item_state = "redeveninggown" - item_color = "red_evening_gown" fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE @@ -160,7 +143,6 @@ desc = "A preppy red skirt with a white blouse." icon_state = "plaid_red" item_state = "plaid_red" - item_color = "plaid_red" fitted = FEMALE_UNIFORM_TOP can_adjust = TRUE alt_covers_chest = TRUE @@ -170,7 +152,6 @@ desc = "A preppy blue skirt with a white blouse." icon_state = "plaid_blue" item_state = "plaid_blue" - item_color = "plaid_blue" fitted = FEMALE_UNIFORM_TOP can_adjust = TRUE alt_covers_chest = TRUE @@ -180,7 +161,6 @@ desc = "A preppy purple skirt with a white blouse." icon_state = "plaid_purple" item_state = "plaid_purple" - item_color = "plaid_purple" fitted = FEMALE_UNIFORM_TOP can_adjust = TRUE alt_covers_chest = TRUE @@ -190,7 +170,6 @@ desc = "A preppy green skirt with a white blouse." icon_state = "plaid_green" item_state = "plaid_green" - item_color = "plaid_green" fitted = FEMALE_UNIFORM_TOP can_adjust = TRUE alt_covers_chest = TRUE @@ -200,7 +179,6 @@ desc = "A white wedding gown made from the finest silk." icon_state = "bride_white" item_state = "bride_white" - item_color = "bride_white" can_adjust = FALSE mutantrace_variation = NONE @@ -209,51 +187,42 @@ desc = "A big and puffy orange dress." icon_state = "bride_orange" item_state = "bride_orange" - item_color = "bride_orange" /obj/item/clothing/under/dress/wedding/purple name = "purple wedding dress" desc = "A big and puffy purple dress." icon_state = "bride_purple" item_state = "bride_purple" - item_color = "bride_purple" /obj/item/clothing/under/dress/wedding/blue name = "blue wedding dress" desc = "A big and puffy blue dress." icon_state = "bride_blue" item_state = "bride_blue" - item_color = "bride_blue" /obj/item/clothing/under/dress/wedding/red name = "red wedding dress" desc = "A big and puffy red dress." icon_state = "bride_red" item_state = "bride_red" - item_color = "bride_red" /obj/item/clothing/under/dress/skirt/polychromic name = "polychromic skirt" desc = "A fancy skirt made with polychromic threads." icon_state = "polyskirt" - item_color = "polyskirt" item_state = "rainbow" - hasprimary = TRUE - hassecondary = TRUE - hastertiary = TRUE - primary_color = "#FFFFFF" - secondary_color = "#F08080" - tertiary_color = "#808080" mutantrace_variation = NONE + var/list/poly_colors = list("#FFFFFF", "#F08080", "#808080") + +/obj/item/clothing/under/dress/skirt/polychromic/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, poly_colors, 3) /obj/item/clothing/under/dress/skirt/polychromic/pleated name = "polychromic pleated skirt" desc = "A magnificent pleated skirt complements the woolen polychromatic sweater." icon_state = "polypleat" - item_color = "polypleat" item_state = "rainbow" - primary_color = "#8CC6FF" - secondary_color = "#808080" - tertiary_color = "#FF3535" body_parts_covered = CHEST|GROIN|ARMS mutantrace_variation = NONE + poly_colors = list("#8CC6FF", "#808080", "#FF3535") diff --git a/code/modules/clothing/under/suits.dm b/code/modules/clothing/under/suits.dm index 1b99fbc549..087262dd1e 100644 --- a/code/modules/clothing/under/suits.dm +++ b/code/modules/clothing/under/suits.dm @@ -4,7 +4,6 @@ desc = "A white suit, suitable for an excellent host." icon_state = "scratch" item_state = "scratch" - item_color = "scratch" can_adjust = FALSE /obj/item/clothing/under/suit/white_on_white/skirt @@ -12,7 +11,6 @@ desc = "A white suitskirt, suitable for an excellent host." icon_state = "white_suit_skirt" item_state = "scratch" - item_color = "white_suit_skirt" body_parts_covered = CHEST|GROIN|ARMS can_adjust = FALSE fitted = FEMALE_UNIFORM_TOP @@ -21,7 +19,6 @@ desc = "It's a very amish looking suit." name = "amish suit" icon_state = "sl_suit" - item_color = "sl_suit" can_adjust = FALSE /obj/item/clothing/under/suit/waiter @@ -29,7 +26,6 @@ desc = "It's a very smart uniform with a special pocket for tip." icon_state = "waiter" item_state = "waiter" - item_color = "waiter" can_adjust = FALSE /obj/item/clothing/under/suit/black @@ -37,7 +33,6 @@ desc = "A black suit and red tie. Very formal." icon_state = "black_suit" item_state = "bl_suit" - item_color = "black_suit" can_adjust = FALSE /obj/item/clothing/under/suit/black_really @@ -45,21 +40,18 @@ desc = "A formal black suit and red tie, intended for the station's finest." icon_state = "really_black_suit" item_state = "bl_suit" - item_color = "really_black_suit" /obj/item/clothing/under/suit/black/skirt name = "executive suit" desc = "A formal trouser suit for women, intended for the station's finest." icon_state = "black_suit_fem" item_state = "black_suit_fem" - item_color = "black_suit_fem" /obj/item/clothing/under/suit/green name = "green suit" desc = "A green suit and yellow necktie. Baller." icon_state = "green_suit" item_state = "dg_suit" - item_color = "green_suit" can_adjust = FALSE /obj/item/clothing/under/suit/red @@ -67,49 +59,42 @@ desc = "A red suit and blue tie. Somewhat formal." icon_state = "red_suit" item_state = "r_suit" - item_color = "red_suit" /obj/item/clothing/under/suit/charcoal name = "charcoal suit" desc = "A charcoal suit and red tie. Very professional." icon_state = "charcoal_suit" item_state = "charcoal_suit" - item_color = "charcoal_suit" /obj/item/clothing/under/suit/navy name = "navy suit" desc = "A navy suit and red tie, intended for the station's finest." icon_state = "navy_suit" item_state = "navy_suit" - item_color = "navy_suit" /obj/item/clothing/under/suit/burgundy name = "burgundy suit" desc = "A burgundy suit and black tie. Somewhat formal." icon_state = "burgundy_suit" item_state = "burgundy_suit" - item_color = "burgundy_suit" /obj/item/clothing/under/suit/checkered name = "checkered suit" desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?" icon_state = "checkered_suit" item_state = "checkered_suit" - item_color = "checkered_suit" /obj/item/clothing/under/suit/tan name = "tan suit" desc = "A tan suit with a yellow tie. Smart, but casual." icon_state = "tan_suit" item_state = "tan_suit" - item_color = "tan_suit" /obj/item/clothing/under/suit/white name = "white suit" desc = "A white suit and jacket with a blue shirt. You wanna play rough? OKAY!" icon_state = "white_suit" item_state = "white_suit" - item_color = "white_suit" /obj/item/clothing/under/suit/telegram name = "telegram suit" @@ -123,13 +108,10 @@ name = "polychromic suit" desc = "For when you want to show off your horrible colour coordination skills." icon_state = "polysuit" - item_color = "polysuit" item_state = "sl_suit" - hasprimary = TRUE - hassecondary = TRUE - hastertiary = TRUE - primary_color = "#FFFFFF" - secondary_color = "#FFFFFF" - tertiary_color = "#808080" can_adjust = FALSE mutantrace_variation = NONE + +/obj/item/clothing/under/suit/polychromic/ComponentInitialize() + . = ..() + AddElement(/datum/element/polychromic, list("#FFFFFF", "#FFFFFF", "#808080"), 3) diff --git a/code/modules/clothing/under/sweaters.dm b/code/modules/clothing/under/sweaters.dm index 13f336bfbd..d8e8373d71 100644 --- a/code/modules/clothing/under/sweaters.dm +++ b/code/modules/clothing/under/sweaters.dm @@ -3,39 +3,33 @@ desc = "Why trade style for comfort? Now you can go commando down south and still be cozy up north." icon_state = "bb_turtle" item_state = "w_suit" - item_color = "bb_turtle" body_parts_covered = CHEST|GROIN|ARMS can_adjust = TRUE icon = 'modular_citadel/icons/obj/clothing/turtlenecks.dmi' - alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi' mutantrace_variation = NONE /obj/item/clothing/under/sweater/black name = "black sweater" icon_state = "bb_turtleblk" item_state = "bl_suit" - item_color = "bb_turtleblk" /obj/item/clothing/under/sweater/purple name = "purple sweater" icon_state = "bb_turtlepur" item_state = "p_suit" - item_color = "bb_turtlepur" /obj/item/clothing/under/sweater/green name = "green sweater" icon_state = "bb_turtlegrn" item_state = "g_suit" - item_color = "bb_turtlegrn" /obj/item/clothing/under/sweater/red name = "red sweater" icon_state = "bb_turtlered" item_state = "r_suit" - item_color = "bb_turtlered" /obj/item/clothing/under/sweater/blue name = "blue sweater" icon_state = "bb_turtleblu" item_state = "b_suit" - item_color = "bb_turtleblu" diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm index 676138d734..986196a212 100644 --- a/code/modules/clothing/under/syndicate.dm +++ b/code/modules/clothing/under/syndicate.dm @@ -3,7 +3,6 @@ desc = "A non-descript and slightly suspicious looking turtleneck with digital camouflage cargo pants." icon_state = "syndicate" item_state = "bl_suit" - item_color = "syndicate" has_sensor = NO_SENSORS armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) alt_covers_chest = TRUE @@ -13,7 +12,6 @@ desc = "A non-descript and slightly suspicious looking skirtleneck." icon_state = "syndicate_skirt" item_state = "bl_suit" - item_color = "syndicate_skirt" has_sensor = NO_SENSORS armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) alt_covers_chest = TRUE @@ -24,7 +22,6 @@ desc = "An insidious armored jumpsuit lined with Syndicate nanofibers and prototype platings, slightly resistant to most forms of damage, but is far too bulky to have anything attached to it. It still counts as stealth if there are no witnesses." icon_state = "bloodred_pajamas" item_state = "bl_suit" - item_color = "bloodred_pajamas" dummy_thick = TRUE armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 50, "acid" = 40) resistance_flags = FIRE_PROOF | ACID_PROOF @@ -35,7 +32,6 @@ desc = "Do operatives dream of nuclear sheep?" icon_state = "bloodred_pajamas" item_state = "bl_suit" - item_color = "bloodred_pajamas" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) /obj/item/clothing/under/syndicate/tacticool @@ -43,7 +39,6 @@ desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." icon_state = "tactifool" item_state = "bl_suit" - item_color = "tactifool" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) /obj/item/clothing/under/syndicate/tacticool/skirt @@ -51,7 +46,6 @@ desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." icon_state = "tactifool_skirt" item_state = "bl_suit" - item_color = "tactifool_skirt" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) fitted = FEMALE_UNIFORM_TOP @@ -60,7 +54,6 @@ desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." icon_state = "tactifool" item_state = "bl_suit" - item_color = "tactifool" has_sensor = TRUE mutantrace_variation = NONE armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0) @@ -70,7 +63,6 @@ desc = "A double seamed tactical turtleneck disguised as a civilian grade silk suit. Intended for the most formal operator. The collar is really sharp." icon_state = "really_black_suit" item_state = "bl_suit" - item_color = "black_suit" can_adjust = FALSE /obj/item/clothing/under/syndicate/camo @@ -78,14 +70,12 @@ desc = "A green military camouflage uniform." icon_state = "camogreen" item_state = "g_suit" - item_color = "camogreen" can_adjust = FALSE /obj/item/clothing/under/syndicate/soviet name = "Ratnik 5 tracksuit" desc = "Badly translated labels tell you to clean this in Vodka. Great for squatting in." icon_state = "trackpants" - item_color = "trackpants" can_adjust = FALSE armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) resistance_flags = NONE @@ -94,14 +84,12 @@ name = "combat uniform" desc = "With a suit lined with this many pockets, you are ready to operate." icon_state = "syndicate_combat" - item_color = "syndicate_combat" can_adjust = FALSE /obj/item/clothing/under/syndicate/rus_army name = "advanced military tracksuit" desc = "Military grade tracksuits for frontline squatting." icon_state = "rus_under" - item_color = "rus_under" can_adjust = FALSE armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) resistance_flags = NONE @@ -111,7 +99,6 @@ desc = "A major league outfit with the number faded number on the back. Seems rather robust for just a game..." icon_state = "syndicatebaseball" item_state = "syndicatebaseball" - item_color = "syndicatebaseball" has_sensor = NO_SENSORS armor = list("melee" = 15, "bullet" = 5, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) alt_covers_chest = TRUE diff --git a/code/modules/clothing/under/trek.dm b/code/modules/clothing/under/trek.dm index 2fb33d1b19..a9709a4c95 100644 --- a/code/modules/clothing/under/trek.dm +++ b/code/modules/clothing/under/trek.dm @@ -13,14 +13,12 @@ name = "command uniform" desc = "The uniform worn by command officers in the mid 2260s." icon_state = "trek_command" - item_color = "trek_command" item_state = "y_suit" /obj/item/clothing/under/trek/engsec name = "operations uniform" desc = "The uniform worn by operations officers of the mid 2260s. You feel strangely vulnerable just seeing this..." icon_state = "trek_engsec" - item_color = "trek_engsec" item_state = "r_suit" strip_delay = 50 @@ -28,7 +26,6 @@ name = "medsci uniform" desc = "The uniform worn by medsci officers in the mid 2260s." icon_state = "trek_medsci" - item_color = "trek_medsci" item_state = "b_suit" permeability_coefficient = 0.50 @@ -37,38 +34,32 @@ /obj/item/clothing/under/trek/command/next desc = "The uniform worn by command officers. This one's from the mid 2360s." icon_state = "trek_next_command" - item_color = "trek_next_command" item_state = "r_suit" /obj/item/clothing/under/trek/engsec/next desc = "The uniform worn by operation officers. This one's from the mid 2360s." icon_state = "trek_next_engsec" - item_color = "trek_next_engsec" item_state = "y_suit" /obj/item/clothing/under/trek/medsci/next desc = "The uniform worn by medsci officers. This one's from the mid 2360s." icon_state = "trek_next_medsci" - item_color = "trek_next_medsci" //ENT /obj/item/clothing/under/trek/command/ent desc = "The uniform worn by command officers of the 2140s." icon_state = "trek_ent_command" - item_color = "trek_ent_command" item_state = "bl_suit" /obj/item/clothing/under/trek/engsec/ent desc = "The uniform worn by operations officers of the 2140s." icon_state = "trek_ent_engsec" - item_color = "trek_ent_engsec" item_state = "bl_suit" /obj/item/clothing/under/trek/medsci/ent desc = "The uniform worn by medsci officers of the 2140s." icon_state = "trek_ent_medsci" - item_color = "trek_ent_medsci" item_state = "bl_suit" @@ -111,5 +102,4 @@ name = "french marshall's uniform" desc = "Something about it feels off..." icon_state = "trek_Q" - item_color = "trek_Q" item_state = "r_suit" diff --git a/code/modules/food_and_drinks/food/snacks_bread.dm b/code/modules/food_and_drinks/food/snacks_bread.dm index 204e5ce455..99fd2af9bb 100644 --- a/code/modules/food_and_drinks/food/snacks_bread.dm +++ b/code/modules/food_and_drinks/food/snacks_bread.dm @@ -179,6 +179,18 @@ tastes = list("bread" = 1) foodtype = GRAIN +/obj/item/reagent_containers/food/snacks/garlicbread + name = "garlic bread" + desc = "Alas, it is limited." + icon = 'icons/obj/food/burgerbread.dmi' + icon_state = "garlicbread" + item_state = "garlicbread" + bonus_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 2) + list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin= 4, /datum/reagent/consumable/garlic = 2) + bitesize = 3 + tastes = list("bread" = 1, "garlic" = 1, "butter" = 1) + foodtype = GRAIN + /obj/item/reagent_containers/food/snacks/deepfryholder name = "Deep Fried Foods Holder Obj" desc = "If you can see this description the code for the deep fryer fucked up." diff --git a/code/modules/food_and_drinks/food/snacks_egg.dm b/code/modules/food_and_drinks/food/snacks_egg.dm index 0f2856c090..fbed6327b5 100644 --- a/code/modules/food_and_drinks/food/snacks_egg.dm +++ b/code/modules/food_and_drinks/food/snacks_egg.dm @@ -41,7 +41,7 @@ /obj/item/reagent_containers/food/snacks/egg/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/toy/crayon)) var/obj/item/toy/crayon/C = W - var/clr = C.item_color + var/clr = C.crayon_color if(!(clr in list("blue", "green", "mime", "orange", "purple", "rainbow", "red", "yellow"))) to_chat(usr, "[src] refuses to take on this colour!") @@ -49,41 +49,32 @@ to_chat(usr, "You colour [src] with [W].") icon_state = "egg-[clr]" - item_color = clr else ..() /obj/item/reagent_containers/food/snacks/egg/blue icon_state = "egg-blue" - item_color = "blue" /obj/item/reagent_containers/food/snacks/egg/green icon_state = "egg-green" - item_color = "green" /obj/item/reagent_containers/food/snacks/egg/mime icon_state = "egg-mime" - item_color = "mime" /obj/item/reagent_containers/food/snacks/egg/orange icon_state = "egg-orange" - item_color = "orange" /obj/item/reagent_containers/food/snacks/egg/purple icon_state = "egg-purple" - item_color = "purple" /obj/item/reagent_containers/food/snacks/egg/rainbow icon_state = "egg-rainbow" - item_color = "rainbow" /obj/item/reagent_containers/food/snacks/egg/red icon_state = "egg-red" - item_color = "red" /obj/item/reagent_containers/food/snacks/egg/yellow icon_state = "egg-yellow" - item_color = "yellow" /obj/item/reagent_containers/food/snacks/friedegg name = "fried egg" diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm index a7cad1d7bb..d02ad0f1a0 100644 --- a/code/modules/food_and_drinks/food/snacks_meat.dm +++ b/code/modules/food_and_drinks/food/snacks_meat.dm @@ -207,7 +207,7 @@ name = "raw khinkali" desc = "One hundred khinkalis? Do I look like a pig?" icon_state = "khinkali" - list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1) + list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1, /datum/reagent/consumable/garlic = 1) cooked_type = /obj/item/reagent_containers/food/snacks/khinkali tastes = list("meat" = 1, "onions" = 1, "garlic" = 1) foodtype = MEAT @@ -216,7 +216,7 @@ name = "khinkali" desc = "One hundred khinkalis? Do I look like a pig?" icon_state = "khinkali" - list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/vitamin = 2) + list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/garlic = 1) bitesize = 3 filling_color = "#F0F0F0" tastes = list("meat" = 1, "onions" = 1, "garlic" = 1) diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index 2adff414e8..a8bb6dc187 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -287,7 +287,7 @@ /obj/machinery/microwave/proc/loop(type, time, wait = max(12 - 2 * efficiency, 2)) // standard wait is 10 if(stat & (NOPOWER|BROKEN)) - if(MICROWAVE_PRE) + if(type == MICROWAVE_PRE) pre_fail() return if(!time) @@ -353,4 +353,4 @@ #undef MICROWAVE_NORMAL #undef MICROWAVE_MUCK -#undef MICROWAVE_PRE \ No newline at end of file +#undef MICROWAVE_PRE diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index b163c6ba97..94c8d7219c 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -86,8 +86,8 @@ tag_overlay.pixel_y = boxes.len * 3 add_overlay(tag_overlay) -/obj/item/pizzabox/worn_overlays(isinhands, icon_file, style_flags = NONE) - . = list() +/obj/item/pizzabox/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) + . = ..() var/current_offset = 2 if(isinhands) for(var/V in boxes) //add EXTRA BOX per box diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm index c3890b28eb..335078eb4c 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm @@ -125,6 +125,16 @@ result = /obj/item/reagent_containers/food/snacks/baguette subcategory = CAT_BREAD +/datum/crafting_recipe/food/garlicbread + name = "Garlic Bread" + time = 40 + reqs = list(/obj/item/reagent_containers/food/snacks/grown/garlic = 1, + /obj/item/reagent_containers/food/snacks/breadslice/plain = 1, + /obj/item/reagent_containers/food/snacks/butter = 1 + ) + result = /obj/item/reagent_containers/food/snacks/garlicbread + subcategory = CAT_BREAD + /datum/crafting_recipe/food/butterbiscuit name = "Butter Biscuit" reqs = list( diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm index 528fc61156..385d7fa359 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm @@ -37,7 +37,8 @@ name = "Raw Khinkali" reqs = list( /obj/item/reagent_containers/food/snacks/doughslice = 1, - /obj/item/reagent_containers/food/snacks/faggot = 1 + /obj/item/reagent_containers/food/snacks/faggot = 1, + /obj/item/reagent_containers/food/snacks/grown/garlic = 1 ) result = /obj/item/reagent_containers/food/snacks/rawkhinkali subcategory = CAT_MISCFOOD diff --git a/code/modules/holiday/easter.dm b/code/modules/holiday/easter.dm index 5f2d92fc93..94c13999ba 100644 --- a/code/modules/holiday/easter.dm +++ b/code/modules/holiday/easter.dm @@ -113,8 +113,6 @@ . = ..() var/eggcolor = pick("blue","green","mime","orange","purple","rainbow","red","yellow") icon_state = "egg-[eggcolor]" - item_color = "[eggcolor]" - /obj/item/reagent_containers/food/snacks/egg/proc/dispensePrize(turf/where) var/won = pick(/obj/item/clothing/head/bunnyhead, /obj/item/clothing/suit/bunnysuit, diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 638d1427bc..7f6d48e731 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -390,7 +390,7 @@ desc = "A jacqueline o' lantern! You can't seem to get rid of it." icon_state = "hardhat0_pumpkin_j" item_state = "hardhat0_pumpkin_j" - item_color = "pumpkin_j" + hat_type = "pumpkin_j" brightness_on = 4 /obj/item/clothing/head/hardhat/pumpkinhead/jaqc/Initialize() diff --git a/code/modules/holodeck/area_copy.dm b/code/modules/holodeck/area_copy.dm index 9fb97c08a7..316bdb8289 100644 --- a/code/modules/holodeck/area_copy.dm +++ b/code/modules/holodeck/area_copy.dm @@ -63,23 +63,34 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars_by_type, typecacheof_assoc_list(list( var/src_min_x = 99999 var/src_min_y = 99999 + var/src_max_x = 0 + var/src_max_y = 0 var/list/refined_src = new/list() for (var/turf/T in turfs_src) src_min_x = min(src_min_x,T.x) src_min_y = min(src_min_y,T.y) + src_max_x = max(src_max_x,T.y) + src_max_y = max(src_max_y,T.y) for (var/turf/T in turfs_src) refined_src[T] = "[T.x - src_min_x].[T.y - src_min_y]" var/trg_min_x = 99999 var/trg_min_y = 99999 + var/trg_max_x = 0 + var/trg_max_y = 0 var/list/refined_trg = new/list() for (var/turf/T in turfs_trg) trg_min_x = min(trg_min_x,T.x) trg_min_y = min(trg_min_y,T.y) + trg_max_x = max(trg_max_x,T.y) + trg_max_y = max(trg_max_y,T.y) + + var/diff_x = round(((src_max_x - src_min_x) - (trg_max_x - trg_min_x))/2) + var/diff_y = round(((src_max_y - src_min_y) - (trg_max_y - trg_min_y))/2) for (var/turf/T in turfs_trg) - refined_trg["[T.x - trg_min_x].[T.y - trg_min_y]"] = T + refined_trg["[T.x - trg_min_x + diff_x].[T.y - trg_min_y + diff_y]"] = T var/list/toupdate = new/list() diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm index b5cbed8b79..3c87082393 100644 --- a/code/modules/holodeck/computer.dm +++ b/code/modules/holodeck/computer.dm @@ -2,7 +2,10 @@ Holodeck Update The on-station holodeck area is of type [holodeck_type]. - All subtypes of [program_type] are loaded into the program cache or emag programs list. + All types found in GLOB.holodeck_areas_per_comp_type[src.type], generated on make_datum_references_lists(), + are loaded into the program cache or emag programs list. + Paths with their abstract_type variable equal to themselves will be skipped. + If init_program is null, a random program will be loaded on startup. If you don't wish this, set it to the offline program or another of your choosing. @@ -12,7 +15,6 @@ 3) Create a new control console that uses those areas Non-mapped areas should be skipped but you should probably comment them out anyway. - The base of program_type will always be ignored; only subtypes will be loaded. */ #define HOLODECK_CD 25 @@ -35,7 +37,6 @@ // Splitting this up allows two holodecks of the same size // to use the same source patterns. Y'know, if you want to. var/holodeck_type = /area/holodeck/rec_center // locate(this) to get the target holodeck - var/program_type = /area/holodeck/rec_center // subtypes of this (but not this itself) are loadable programs var/active = FALSE var/damaged = FALSE @@ -181,7 +182,7 @@ return ..() /obj/machinery/computer/holodeck/proc/generate_program_list() - for(var/typekey in subtypesof(program_type)) + for(var/typekey in GLOB.holodeck_areas_prototypes[type]) var/area/holodeck/A = GLOB.areas_by_type[typekey] if(!A || !A.contents.len) continue diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm index 884769ebd4..3fac417605 100644 --- a/code/modules/holodeck/items.dm +++ b/code/modules/holodeck/items.dm @@ -24,33 +24,34 @@ hitsound = "swing_hit" armour_penetration = 50 var/active = 0 + var/saber_color /obj/item/holo/esword/green/Initialize() . = ..() - item_color = "green" + saber_color = "green" /obj/item/holo/esword/red/Initialize() . = ..() - item_color = "red" + saber_color = "red" -/obj/item/holo/esword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(active) +/obj/item/holo/esword/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!active) return ..() - return 0 + return ..() /obj/item/holo/esword/attack(target as mob, mob/user as mob) ..() /obj/item/holo/esword/Initialize() . = ..() - item_color = pick("red","blue","green","purple") + saber_color = pick("red","blue","green","purple") /obj/item/holo/esword/attack_self(mob/living/user as mob) active = !active if (active) force = 30 - icon_state = "sword[item_color]" + icon_state = "sword[saber_color]" w_class = WEIGHT_CLASS_BULKY hitsound = 'sound/weapons/blade1.ogg' playsound(user, 'sound/weapons/saberon.ogg', 20, 1) diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm index 80792538d6..eba7a3d3c4 100644 --- a/code/modules/hydroponics/grown/berries.dm +++ b/code/modules/hydroponics/grown/berries.dm @@ -90,7 +90,7 @@ lifespan = 30 endurance = 25 mutatelist = list() - genes = list(/datum/plant_gene/trait/glow/white, /datum/plant_gene/trait/noreact, /datum/plant_gene/trait/repeated_harvest) + genes = list(/datum/plant_gene/trait/glow/white, /datum/plant_gene/trait/repeated_harvest) reagents_add = list(/datum/reagent/uranium = 0.25, /datum/reagent/iodine = 0.2, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) rarity = 20 diff --git a/code/modules/hydroponics/grown/garlic.dm b/code/modules/hydroponics/grown/garlic.dm new file mode 100644 index 0000000000..4184b85008 --- /dev/null +++ b/code/modules/hydroponics/grown/garlic.dm @@ -0,0 +1,29 @@ +/obj/item/seeds/garlic + name = "pack of garlic seeds" + desc = "A packet of extremely pungent seeds." + icon_state = "seed-garlic" + species = "garlic" + plantname = "Garlic Sprouts" + product = /obj/item/reagent_containers/food/snacks/grown/garlic + yield = 6 + potency = 25 + growthstages = 3 + growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' + reagents_add = list(/datum/reagent/consumable/garlic = 0.15, /datum/reagent/consumable/nutriment = 0.1) + +/obj/item/reagent_containers/food/snacks/grown/garlic + seed = /obj/item/seeds/garlic + name = "garlic" + desc = "Delicious, but with a potentially overwhelming odor." + icon_state = "garlic" + filling_color = "#C0C9A0" + bitesize_mod = 2 + tastes = list("garlic" = 1) + wine_power = 10 + +/obj/item/clothing/neck/garlic_necklace + name = "garlic necklace" + desc = "A clove of garlic on a cable, tied to itself in a circle, just might fit around your neck. For loonies people who fear getting their blood sucked." + icon_state = "garlic_necklace" + item_state = "garlic_necklace" + \ No newline at end of file diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm index 44abb4939b..f356ed7b68 100644 --- a/code/modules/hydroponics/grown/misc.dm +++ b/code/modules/hydroponics/grown/misc.dm @@ -492,9 +492,6 @@ return var/turf/T = get_turf(src) reagents.chem_temp = 1000 - //Disable seperated contents when the grenade primes - if (seed.get_gene(/datum/plant_gene/trait/noreact)) - DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT) reagents.handle_reactions() log_game("Coconut bomb detonation at [AREACOORD(T)], location [loc]") qdel(src) diff --git a/code/modules/hydroponics/grown/onion.dm b/code/modules/hydroponics/grown/onion.dm index 2ebaa6d5e2..a75b9caf5f 100644 --- a/code/modules/hydroponics/grown/onion.dm +++ b/code/modules/hydroponics/grown/onion.dm @@ -14,7 +14,7 @@ weed_chance = 3 growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) - mutatelist = list(/obj/item/seeds/onion/red) + mutatelist = list(/obj/item/seeds/onion/red, /obj/item/seeds/garlic) /obj/item/reagent_containers/food/snacks/grown/onion seed = /obj/item/seeds/onion diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 3769f9eacc..aeddf771b8 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -78,7 +78,7 @@ make_podman = 1 break else - if(M.ckey == ckey && M.stat == DEAD && !M.suiciding) + if(M.ckey == ckey && M.stat == DEAD && !M.suiciding && AmBloodsucker(M)) make_podman = 1 if(isliving(M)) var/mob/living/L = M diff --git a/code/modules/hydroponics/grown/tobacco.dm b/code/modules/hydroponics/grown/tobacco.dm index 1e2d25d825..db929d45fb 100644 --- a/code/modules/hydroponics/grown/tobacco.dm +++ b/code/modules/hydroponics/grown/tobacco.dm @@ -34,6 +34,7 @@ mutatelist = list() reagents_add = list(/datum/reagent/medicine/salbutamol = 0.05, /datum/reagent/drug/nicotine = 0.08, /datum/reagent/consumable/nutriment = 0.03) rarity = 20 + genes = list(/datum/plant_gene/trait/smoke) //get it? because you smoke tobacco? i'm hilarious. /obj/item/reagent_containers/food/snacks/grown/tobacco/space seed = /obj/item/seeds/tobacco/space diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index bf8aa888cc..ef2eff707f 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -216,6 +216,10 @@ name = "Liquid Contents" examine_line = "It has a lot of liquid contents inside." +/datum/plant_gene/trait/squash/on_slip(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/C) + // Squash the plant on slip. + G.squash(C) + /datum/plant_gene/trait/slip // Makes plant slippery, unless it has a grown-type trash. Then the trash gets slippery. // Applies other trait effects (teleporting, etc) to the target by on_slip. @@ -364,20 +368,6 @@ new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect... qdel(G) - -/datum/plant_gene/trait/noreact - // Makes plant reagents not react until squashed. - name = "Separated Chemicals" - -/datum/plant_gene/trait/noreact/on_new(obj/item/reagent_containers/food/snacks/grown/G, newloc) - ..() - ENABLE_BITFIELD(G.reagents.reagents_holder_flags, NO_REACT) - -/datum/plant_gene/trait/noreact/on_squash(obj/item/reagent_containers/food/snacks/grown/G, atom/target) - DISABLE_BITFIELD(G.reagents.reagents_holder_flags, NO_REACT) - G.reagents.handle_reactions() - - /datum/plant_gene/trait/maxchem // 2x to max reagents volume. name = "Densified Chemicals" diff --git a/code/modules/instruments/instrument_data/_instrument_data.dm b/code/modules/instruments/instrument_data/_instrument_data.dm new file mode 100644 index 0000000000..447bcdffb1 --- /dev/null +++ b/code/modules/instruments/instrument_data/_instrument_data.dm @@ -0,0 +1,107 @@ +/proc/path_to_instrument_ids(path) + if(!ispath(path)) + path = text2path(path) + if(!ispath(path)) + return + if(!ispath(path, /datum/instrument)) + return + . = list() + for(var/i in typesof(path)) + var/datum/instrument/I = i + var/init_id = initial(I.id) + if(init_id) + . |= init_id + +/// Get all non admin_only instruments. +/proc/get_allowed_instrument_ids() + . = list() + for(var/id in SSinstruments.instrument_data) + var/datum/instrument/I = SSinstruments.instrument_data[id] + if(!I.admin_only) + . += I.id + +/datum/instrument + /// Name of the instrument + var/name = "Generic instrument" + /// Uniquely identifies this instrument so runtime changes are possible as opposed to paths. If this is unset, things will use path instead. + var/id + /// Category + var/category = "Unsorted" + /// Used for categorization subtypes + var/abstract_type = /datum/instrument + /// Write here however many samples, follow this syntax: "%note num%"='%sample file%' eg. "27"='synthesizer/e2.ogg'. Key must never be lower than 0 and higher than 127 + var/list/real_samples + /// assoc list key = /datum/instrument_key. do not fill this yourself! + var/list/samples + /// See __DEFINES/flags/instruments.dm + var/instrument_flags = NONE + /// For legacy instruments, the path to our notes + var/legacy_instrument_path + /// For legacy instruments, our file extension + var/legacy_instrument_ext + /// What songs are using us + var/list/datum/song/songs_using = list() + /// Don't touch this + var/static/HIGHEST_KEY = 127 + /// Don't touch this x2 + var/static/LOWEST_KEY = 0 + /// Oh no - For truly troll instruments. + var/admin_only = FALSE + /// Volume multiplier. Synthesized instruments are quite loud and I don't like to cut off potential detail via editing. (someone correct me if this isn't a thing) + var/volume_multiplier = 1/3 + +/datum/instrument/New() + if(isnull(id)) + id = "[type]" + +/datum/instrument/proc/Initialize() + if(CHECK_BITFIELD(instrument_flags, INSTRUMENT_LEGACY | INSTRUMENT_DO_NOT_AUTOSAMPLE)) + return + calculate_samples() + +/datum/instrument/proc/ready() + if(CHECK_BITFIELD(instrument_flags, INSTRUMENT_LEGACY)) + return legacy_instrument_path && legacy_instrument_ext + else if(CHECK_BITFIELD(instrument_flags, INSTRUMENT_DO_NOT_AUTOSAMPLE)) + return length(samples) + return (length(samples) >= 128) + +/datum/instrument/Destroy() + SSinstruments.instrument_data -= id + for(var/i in songs_using) + var/datum/song/S = i + S.set_instrument(null) + real_samples = null + samples = null + songs_using = null + return ..() + +/datum/instrument/proc/calculate_samples() + if(!length(real_samples)) + CRASH("No real samples defined for [id] [type] on calculate_samples() call.") + var/list/real_keys = list() + samples = list() + for(var/key in real_samples) + real_keys += text2num(key) + sortTim(real_keys, /proc/cmp_numeric_asc, associative = FALSE) + + for(var/i in 1 to (length(real_keys) - 1)) + var/from_key = real_keys[i] + var/to_key = real_keys[i+1] + var/sample1 = real_samples[num2text(from_key)] + var/sample2 = real_samples[num2text(to_key)] + var/pivot = FLOOR((from_key + to_key) / 2, 1) //original code was a round but I replaced it because that's effectively a floor, thanks Baystation! who knows what was intended. + for(var/key in from_key to pivot) + samples[num2text(key)] = new /datum/instrument_key(sample1, key, key - from_key) + for(var/key in (pivot + 1) to to_key) + samples[num2text(key)] = new /datum/instrument_key(sample2, key, key - to_key) + + // Fill in 0 to first key and last key to 127 + var/first_key = real_keys[1] + var/last_key = real_keys[length(real_keys)] + var/first_sample = real_samples[num2text(first_key)] + var/last_sample = real_samples[num2text(last_key)] + for(var/key in LOWEST_KEY to (first_key - 1)) + samples[num2text(key)] = new /datum/instrument_key(first_sample, key, key - first_key) + for(var/key in last_key to HIGHEST_KEY) + samples[num2text(key)] = new /datum/instrument_key(last_sample, key, key - last_key) diff --git a/code/modules/instruments/instrument_data/_instrument_key.dm b/code/modules/instruments/instrument_data/_instrument_key.dm new file mode 100644 index 0000000000..012270ae11 --- /dev/null +++ b/code/modules/instruments/instrument_data/_instrument_key.dm @@ -0,0 +1,20 @@ +/datum/instrument_key + var/key //1 to 127 + var/sample //file + var/frequency //frequency generated + var/deviation //deviation up/down towards pivot from sample (??) + +/datum/instrument_key/New(sample = src.sample, key = src.key, deviation = src.deviation, frequency = src.frequency) + src.sample = sample + src.key = key + src.deviation = deviation + src.frequency = frequency + if(!frequency && deviation) + calculate() + +/datum/instrument_key/proc/calculate() + if(!deviation) + CRASH("Invalid calculate call: No deviation or sample in instrument_key") + #define KEY_TWELTH (1/12) + frequency = 2 ** (KEY_TWELTH * deviation) + #undef KEY_TWELTH diff --git a/code/modules/instruments/instrument_data/brass.dm b/code/modules/instruments/instrument_data/brass.dm new file mode 100644 index 0000000000..7f8f103831 --- /dev/null +++ b/code/modules/instruments/instrument_data/brass.dm @@ -0,0 +1,26 @@ +/datum/instrument/brass + name = "Generic brass instrument" + category = "Brass" + abstract_type = /datum/instrument/brass + +/datum/instrument/brass/crisis_section + name = "Crisis Brass Section" + id = "crbrass" + real_samples = list("36"='sound/instruments/synthesis_samples/brass/crisis_brass/c2.ogg', + "48"='sound/instruments/synthesis_samples/brass/crisis_brass/c3.ogg', + "60"='sound/instruments/synthesis_samples/brass/crisis_brass/c4.ogg', + "72"='sound/instruments/synthesis_samples/brass/crisis_brass/c5.ogg') + +/datum/instrument/brass/crisis_trombone + name = "Crisis Trombone" + id = "crtrombone" + real_samples = list("36"='sound/instruments/synthesis_samples/brass/crisis_trombone/c2.ogg', + "48"='sound/instruments/synthesis_samples/brass/crisis_trombone/c3.ogg', + "60"='sound/instruments/synthesis_samples/brass/crisis_trombone/c4.ogg', + "72"='sound/instruments/synthesis_samples/brass/crisis_trombone/c5.ogg') + +/datum/instrument/brass/crisis_trumpet + name = "Crisis Trumpet" + id = "crtrumpet" + real_samples = list("60"='sound/instruments/synthesis_samples/brass/crisis_trumpet/c4.ogg', + "72"='sound/instruments/synthesis_samples/brass/crisis_trumpet/c5.ogg') diff --git a/code/modules/instruments/instrument_data/chromatic_percussion.dm b/code/modules/instruments/instrument_data/chromatic_percussion.dm new file mode 100644 index 0000000000..cafa9e31ed --- /dev/null +++ b/code/modules/instruments/instrument_data/chromatic_percussion.dm @@ -0,0 +1,31 @@ +/datum/instrument/chromatic + name = "Generic chromatic percussion instrument" + category = "Chromatic percussion" + abstract_type = /datum/instrument/chromatic + +/datum/instrument/chromatic/vibraphone1 + name = "Crisis Vibraphone" + id = "crvibr" + real_samples = list("36"='sound/instruments/synthesis_samples/chromatic/vibraphone1/c2.ogg', + "48"='sound/instruments/synthesis_samples/chromatic/vibraphone1/c3.ogg', + "60"='sound/instruments/synthesis_samples/chromatic/vibraphone1/c4.ogg', + "72"='sound/instruments/synthesis_samples/chromatic/vibraphone1/c5.ogg') + +/datum/instrument/chromatic/musicbox1 + name = "SGM Music Box" + id = "sgmmbox" + real_samples = list("36"='sound/instruments/synthesis_samples/chromatic/sgmbox/c2.ogg', + "48"='sound/instruments/synthesis_samples/chromatic/sgmbox/c3.ogg', + "60"='sound/instruments/synthesis_samples/chromatic/sgmbox/c4.ogg', + "72"='sound/instruments/synthesis_samples/chromatic/sgmbox/c5.ogg') + +/datum/instrument/chromatic/fluid_celeste + name = "FluidR3 Celeste" + id = "r3celeste" + real_samples = list("36"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c2.ogg', + "48"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c3.ogg', + "60"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c4.ogg', + "72"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c5.ogg', + "84"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c6.ogg', + "96"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c7.ogg', + "108"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c8.ogg') diff --git a/code/modules/instruments/instrument_data/fun.dm b/code/modules/instruments/instrument_data/fun.dm new file mode 100644 index 0000000000..44d78b8ccd --- /dev/null +++ b/code/modules/instruments/instrument_data/fun.dm @@ -0,0 +1,25 @@ +/datum/instrument/fun + name = "Generic Fun Instrument" + category = "Fun" + abstract_type = /datum/instrument/fun + +/datum/instrument/fun/honk + name = "!!HONK!!" + id = "honk" + real_samples = list("74"='sound/items/bikehorn.ogg') // Cluwne Heaven + +/datum/instrument/fun/signal + name = "Ping" + id = "ping" + real_samples = list("79"='sound/machines/ping.ogg') + +/datum/instrument/fun/chime + name = "Chime" + id = "chime" + real_samples = list("79"='sound/machines/chime.ogg') + +/datum/instrument/fun/nya + name = "NYA NYA NYA" + id = "nyanyanya" + real_samples = list("79" = 'modular_citadel/sound/voice/nya.ogg') + admin_only = TRUE diff --git a/code/modules/instruments/instrument_data/guitar.dm b/code/modules/instruments/instrument_data/guitar.dm new file mode 100644 index 0000000000..be7cfbe467 --- /dev/null +++ b/code/modules/instruments/instrument_data/guitar.dm @@ -0,0 +1,36 @@ +/datum/instrument/guitar + name = "Generic guitar-like instrument" + category = "Guitar" + abstract_type = /datum/instrument/guitar + +/datum/instrument/guitar/steel_crisis + name = "Crisis Steel String Guitar" + id = "csteelgt" + real_samples = list("36"='sound/instruments/synthesis_samples/guitar/crisis_steel/c2.ogg', + "48"='sound/instruments/synthesis_samples/guitar/crisis_steel/c3.ogg', + "60"='sound/instruments/synthesis_samples/guitar/crisis_steel/c4.ogg', + "72"='sound/instruments/synthesis_samples/guitar/crisis_steel/c5.ogg') + +/datum/instrument/guitar/nylon_crisis + name = "Crisis Nylon String Guitar" + id = "cnylongt" + real_samples = list("36"='sound/instruments/synthesis_samples/guitar/crisis_nylon/c2.ogg', + "48"='sound/instruments/synthesis_samples/guitar/crisis_nylon/c3.ogg', + "60"='sound/instruments/synthesis_samples/guitar/crisis_nylon/c4.ogg', + "72"='sound/instruments/synthesis_samples/guitar/crisis_nylon/c5.ogg') + +/datum/instrument/guitar/clean_crisis + name = "Crisis Clean Guitar" + id = "ccleangt" + real_samples = list("36"='sound/instruments/synthesis_samples/guitar/crisis_clean/c2.ogg', + "48"='sound/instruments/synthesis_samples/guitar/crisis_clean/c3.ogg', + "60"='sound/instruments/synthesis_samples/guitar/crisis_clean/c4.ogg', + "72"='sound/instruments/synthesis_samples/guitar/crisis_clean/c5.ogg') + +/datum/instrument/guitar/muted_crisis + name = "Crisis Muted Guitar" + id = "cmutedgt" + real_samples = list("36"='sound/instruments/synthesis_samples/guitar/crisis_muted/c2.ogg', + "48"='sound/instruments/synthesis_samples/guitar/crisis_muted/c3.ogg', + "60"='sound/instruments/synthesis_samples/guitar/crisis_muted/c4.ogg', + "72"='sound/instruments/synthesis_samples/guitar/crisis_muted/c5.ogg') diff --git a/code/modules/instruments/instrument_data/hardcoded.dm b/code/modules/instruments/instrument_data/hardcoded.dm new file mode 100644 index 0000000000..757fea08a8 --- /dev/null +++ b/code/modules/instruments/instrument_data/hardcoded.dm @@ -0,0 +1,86 @@ +//THESE ARE HARDCODED INSTRUMENT SAMPLES. +//SONGS WILL BE AUTOMATICALLY SWITCHED TO LEGACY MODE IF THEY USE THIS KIND OF INSTRUMENT! +//I'd prefer these stayed. They sound different from the mechanical synthesis of synthed instruments, and I quite like them that way. It's not legacy, it's hardcoded, old style. - kevinz000 +/datum/instrument/hardcoded + abstract_type = /datum/instrument/hardcoded + category = "Non-Synthesized" + instrument_flags = INSTRUMENT_LEGACY + volume_multiplier = 1 //not as loud as synth'd + +/datum/instrument/hardcoded/accordian + name = "Accordian" + id = "accordian" + legacy_instrument_ext = "mid" + legacy_instrument_path = "accordian" + +/datum/instrument/hardcoded/bikehorn + name = "Bike Horn" + id = "bikehorn" + legacy_instrument_ext = "ogg" + legacy_instrument_path = "bikehorn" + +/datum/instrument/hardcoded/eguitar + name = "Electric Guitar" + id = "eguitar" + legacy_instrument_ext = "ogg" + legacy_instrument_path = "eguitar" + +/datum/instrument/hardcoded/glockenspiel + name = "Glockenspiel" + id = "glockenspiel" + legacy_instrument_ext = "mid" + legacy_instrument_path = "glockenspiel" + +/datum/instrument/hardcoded/guitar + name = "Guitar" + id = "guitar" + legacy_instrument_ext = "ogg" + legacy_instrument_path = "guitar" + +/datum/instrument/hardcoded/harmonica + name = "Harmonica" + id = "harmonica" + legacy_instrument_ext = "mid" + legacy_instrument_path = "harmonica" + +/datum/instrument/hardcoded/piano + name = "Piano" + id = "piano" + legacy_instrument_ext = "ogg" + legacy_instrument_path = "piano" + +/datum/instrument/hardcoded/recorder + name = "Recorder" + id = "recorder" + legacy_instrument_ext = "mid" + legacy_instrument_path = "recorder" + +/datum/instrument/hardcoded/saxophone + name = "Saxophone" + id = "saxophone" + legacy_instrument_ext = "mid" + legacy_instrument_path = "saxophone" + +/datum/instrument/hardcoded/trombone + name = "Trombone" + id = "trombone" + legacy_instrument_ext = "mid" + legacy_instrument_path = "trombone" + +/datum/instrument/hardcoded/violin + name = "Violin" + id = "violin" + legacy_instrument_ext = "mid" + legacy_instrument_path = "violin" + +/datum/instrument/hardcoded/xylophone + name = "Xylophone" + id = "xylophone" + legacy_instrument_ext = "mid" + legacy_instrument_path = "xylophone" + +/datum/instrument/hardcoded/banjo + name = "Banjo" + id = "banjo" + legacy_instrument_ext = "ogg" + legacy_instrument_path = "banjo" diff --git a/code/modules/instruments/instrument_data/organ.dm b/code/modules/instruments/instrument_data/organ.dm new file mode 100644 index 0000000000..25da740998 --- /dev/null +++ b/code/modules/instruments/instrument_data/organ.dm @@ -0,0 +1,43 @@ +/datum/instrument/organ + name = "Generic organ" + category = "Organ" + abstract_type = /datum/instrument/organ + +/datum/instrument/organ/crisis_church + name = "Crisis Church Organ" + id = "crichugan" + real_samples = list("36"='sound/instruments/synthesis_samples/organ/crisis_church/c2.ogg', + "48"='sound/instruments/synthesis_samples/organ/crisis_church/c3.ogg', + "60"='sound/instruments/synthesis_samples/organ/crisis_church/c4.ogg', + "72"='sound/instruments/synthesis_samples/organ/crisis_church/c5.ogg') + +/datum/instrument/organ/crisis_hammond + name = "Crisis Hammond Organ" + id = "crihamgan" + real_samples = list("36"='sound/instruments/synthesis_samples/organ/crisis_hammond/c2.ogg', + "48"='sound/instruments/synthesis_samples/organ/crisis_hammond/c3.ogg', + "60"='sound/instruments/synthesis_samples/organ/crisis_hammond/c4.ogg', + "72"='sound/instruments/synthesis_samples/organ/crisis_hammond/c5.ogg') + +/datum/instrument/organ/crisis_accordian + name = "Crisis Accordian" + id = "crack" + real_samples = list("36"='sound/instruments/synthesis_samples/organ/crisis_accordian/c2.ogg', + "48"='sound/instruments/synthesis_samples/organ/crisis_accordian/c3.ogg', + "60"='sound/instruments/synthesis_samples/organ/crisis_accordian/c4.ogg', + "72"='sound/instruments/synthesis_samples/organ/crisis_accordian/c5.ogg') + +/datum/instrument/organ/crisis_harmonica + name = "Crisis Harmonica" + id = "crharmony" + real_samples = list("48"='sound/instruments/synthesis_samples/organ/crisis_harmonica/c3.ogg', + "60"='sound/instruments/synthesis_samples/organ/crisis_harmonica/c4.ogg', + "72"='sound/instruments/synthesis_samples/organ/crisis_harmonica/c5.ogg') + +/datum/instrument/organ/crisis_tango_accordian + name = "Crisis Tango Accordian" + id = "crtango" + real_samples = list("36"='sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c2.ogg', + "48"='sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c3.ogg', + "60"='sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c4.ogg', + "72"='sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c5.ogg') diff --git a/code/modules/instruments/instrument_data/piano.dm b/code/modules/instruments/instrument_data/piano.dm new file mode 100644 index 0000000000..fdd2f6e938 --- /dev/null +++ b/code/modules/instruments/instrument_data/piano.dm @@ -0,0 +1,56 @@ +/datum/instrument/piano + name = "Generic piano" + category = "Piano" + abstract_type = /datum/instrument/piano + +/datum/instrument/piano/fluid_piano + name = "FluidR3 Grand Piano" + id = "r3grand" + real_samples = list("36"='sound/instruments/synthesis_samples/piano/fluid_piano/c2.ogg', + "48"='sound/instruments/synthesis_samples/piano/fluid_piano/c3.ogg', + "60"='sound/instruments/synthesis_samples/piano/fluid_piano/c4.ogg', + "72"='sound/instruments/synthesis_samples/piano/fluid_piano/c5.ogg', + "84"='sound/instruments/synthesis_samples/piano/fluid_piano/c6.ogg', + "96"='sound/instruments/synthesis_samples/piano/fluid_piano/c7.ogg', + "108"='sound/instruments/synthesis_samples/piano/fluid_piano/c8.ogg') + +/datum/instrument/piano/fluid_harpsichord + name = "FluidR3 Harpsichord" + id = "r3harpsi" + real_samples = list("36"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c2.ogg', + "48"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c3.ogg', + "60"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c4.ogg', + "72"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c5.ogg', + "84"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c6.ogg', + "96"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c7.ogg', + "108"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c8.ogg') + +/datum/instrument/piano/crisis_harpsichord + name = "Crisis Harpsichord" + id = "crharpsi" + real_samples = list("36"='sound/instruments/synthesis_samples/piano/crisis_harpsichord/c2.ogg', + "48"='sound/instruments/synthesis_samples/piano/crisis_harpsichord/c3.ogg', + "60"='sound/instruments/synthesis_samples/piano/crisis_harpsichord/c4.ogg', + "72"='sound/instruments/synthesis_samples/piano/crisis_harpsichord/c5.ogg') + +/datum/instrument/piano/crisis_grandpiano_uni + name = "Crisis Grand Piano One" + id = "crgrand1" + real_samples = list("36"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c2.ogg', + "48"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c3.ogg', + "60"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c4.ogg', + "72"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c5.ogg', + "84"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c6.ogg', + "96"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c7.ogg', + "108"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c8.ogg') + +/datum/instrument/piano/crisis_brightpiano_uni + name = "Crisis Bright Piano One" + id = "crbright1" + real_samples = list("36"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c2.ogg', + "48"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c3.ogg', + "60"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c4.ogg', + "72"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c5.ogg', + "84"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c6.ogg', + "96"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c7.ogg', + "108"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c8.ogg') diff --git a/code/modules/instruments/instrument_data/synth_tones.dm b/code/modules/instruments/instrument_data/synth_tones.dm new file mode 100644 index 0000000000..9ad9250f40 --- /dev/null +++ b/code/modules/instruments/instrument_data/synth_tones.dm @@ -0,0 +1,19 @@ +/datum/instrument/tones + name = "Ideal tone" + category = "Tones" + abstract_type = /datum/instrument/tones + +/datum/instrument/tones/square_wave + name = "Ideal square wave" + id = "square" + real_samples = list("81"='sound/instruments/synthesis_samples/tones/Square.ogg') + +/datum/instrument/tones/sine_wave + name = "Ideal sine wave" + id = "sine" + real_samples = list("81"='sound/instruments/synthesis_samples/tones/Sine.ogg') + +/datum/instrument/tones/saw_wave + name = "Ideal sawtooth wave" + id = "saw" + real_samples = list("81"='sound/instruments/synthesis_samples/tones/Sawtooth.ogg') diff --git a/code/game/objects/items/devices/instruments.dm b/code/modules/instruments/instruments/item.dm similarity index 78% rename from code/game/objects/items/devices/instruments.dm rename to code/modules/instruments/instruments/item.dm index 8dedc2cb86..fa3e75e431 100644 --- a/code/game/objects/items/devices/instruments.dm +++ b/code/modules/instruments/instruments/item.dm @@ -1,83 +1,80 @@ //copy pasta of the space piano, don't hurt me -Pete /obj/item/instrument name = "generic instrument" - resistance_flags = FLAMMABLE force = 10 max_integrity = 100 + resistance_flags = FLAMMABLE icon = 'icons/obj/musician.dmi' lefthand_file = 'icons/mob/inhands/equipment/instruments_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/instruments_righthand.dmi' var/datum/song/handheld/song - var/instrumentId = "generic" - var/instrumentExt = "mid" - var/tune_time = 0 - -/obj/item/instrument/Initialize() - . = ..() - song = new(instrumentId, src, instrumentExt) - -/obj/item/instrument/Destroy() - if (tune_time) - STOP_PROCESSING(SSobj, src) - qdel(song) - song = null - return ..() - -/obj/item/instrument/suicide_act(mob/user) - user.visible_message("[user] begins to play 'Gloomy Sunday'! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) + var/list/allowed_instrument_ids + var/tune_time_left = 0 /obj/item/instrument/Initialize(mapload) . = ..() - if(mapload) - song.tempo = song.sanitize_tempo(song.tempo) // tick_lag isn't set when the map is loaded + song = new(src, allowed_instrument_ids) + allowed_instrument_ids = null //We don't need this clogging memory after it's used. -/obj/item/instrument/attack_self(mob/user) - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return 1 - interact(user) +/obj/item/instrument/Destroy() + QDEL_NULL(song) + if(tune_time_left) + STOP_PROCESSING(SSprocessing, src) + return ..() -/obj/item/instrument/interact(mob/user) - ui_interact(user) +/obj/item/instrument/proc/should_stop_playing(mob/user) + return !user.CanReach(src) || !user.canUseTopic(src, FALSE, TRUE, FALSE, FALSE) -/obj/item/instrument/ui_interact(mob/user) - if(!user) - return - - if(!isliving(user) || user.stat || user.restrained() || user.lying) - return - - user.set_machine(src) - song.interact(user) - -/obj/item/instrument/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/musicaltuner)) - var/mob/living/carbon/human/H = user - if (HAS_TRAIT(H, TRAIT_MUSICIAN)) - if (!tune_time) - H.visible_message("[H] tunes the [src] to perfection!", "You tune the [src] to perfection!") - tune_time = 300 - START_PROCESSING(SSobj, src) - else - to_chat(H, "[src] is already well tuned!") - else - to_chat(H, "You have no idea how to use this.") - -/obj/item/instrument/process() - if (tune_time) +/obj/item/instrument/process(wait) + if(is_tuned()) if (song.playing) for (var/mob/living/M in song.hearing_mobs) M.dizziness = max(0,M.dizziness-2) M.jitteriness = max(0,M.jitteriness-2) M.confused = max(M.confused-1) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "goodmusic", /datum/mood_event/goodmusic) - tune_time-- + tune_time_left -= wait else - if (!tune_time) - if (song.playing) - loc.visible_message("[src] starts sounding a little off...") - STOP_PROCESSING(SSobj, src) + tune_time_left = 0 + if (song.playing) + loc.visible_message("[src] starts sounding a little off...") + STOP_PROCESSING(SSprocessing, src) + +/obj/item/instrument/suicide_act(mob/user) + user.visible_message("[user] begins to play 'Gloomy Sunday'! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/instrument/attack_self(mob/user) + if(!user.IsAdvancedToolUser()) + to_chat(user, "You don't have the dexterity to do this!") + return TRUE + interact(user) + +/obj/item/instrument/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/musicaltuner)) + var/mob/living/carbon/human/H = user + if (HAS_TRAIT(H, TRAIT_MUSICIAN)) + if (!is_tuned()) + H.visible_message("[H] tunes the [src] to perfection!", "You tune the [src] to perfection!") + tune_time_left = 600 SECONDS + START_PROCESSING(SSprocessing, src) + else + to_chat(H, "[src] is already well tuned!") + else + to_chat(H, "You have no idea how to use this.") + +/obj/item/instrument/proc/is_tuned() + return tune_time_left > 0 + +/obj/item/instrument/interact(mob/user) + ui_interact(user) + +/obj/item/instrument/ui_interact(mob/living/user) + if(!isliving(user) || user.stat || user.restrained()) + return + + user.set_machine(src) + song.ui_interact(user) /obj/item/instrument/violin name = "space violin" @@ -85,7 +82,7 @@ icon_state = "violin" item_state = "violin" hitsound = "swing_hit" - instrumentId = "violin" + allowed_instrument_ids = "violin" /obj/item/instrument/violin/golden name = "golden violin" @@ -99,40 +96,20 @@ desc = "An advanced electronic synthesizer that can be used as various instruments." icon_state = "synth" item_state = "synth" - instrumentId = "piano" - instrumentExt = "ogg" - var/static/list/insTypes = list("accordion" = "mid", "bikehorn" = "ogg", "glockenspiel" = "mid", "banjo" = "ogg", "guitar" = "ogg", "harmonica" = "mid", "piano" = "ogg", "recorder" = "mid", "saxophone" = "mid", "trombone" = "mid", "violin" = "mid", "xylophone" = "mid") //No eguitar you ear-rapey fuckers. - actions_types = list(/datum/action/item_action/synthswitch) + allowed_instrument_ids = "piano" -/obj/item/instrument/piano_synth/proc/changeInstrument(name = "piano") - song.instrumentDir = name - song.instrumentExt = insTypes[name] - -/obj/item/instrument/piano_synth/proc/selectInstrument() // Moved here so it can be used by the action and PAI software panel without copypasta - var/chosen = input("Choose the type of instrument you want to use", "Instrument Selection", song.instrumentDir) as null|anything in insTypes - if(!insTypes[chosen]) - return - return changeInstrument(chosen) - -/obj/item/instrument/banjo - name = "banjo" - desc = "A 'Mura' brand banjo. It's pretty much just a drum with a neck and strings." - icon_state = "banjo" - item_state = "banjo" - instrumentExt = "ogg" - attack_verb = list("scruggs-styled", "hum-diggitied", "shin-digged", "clawhammered") - hitsound = 'sound/weapons/banjoslap.ogg' - instrumentId = "banjo" +/obj/item/instrument/piano_synth/Initialize() + . = ..() + song.allowed_instrument_ids = get_allowed_instrument_ids() /obj/item/instrument/guitar name = "guitar" desc = "It's made of wood and has bronze strings." icon_state = "guitar" item_state = "guitar" - instrumentExt = "ogg" attack_verb = list("played metal on", "serenaded", "crashed", "smashed") hitsound = 'sound/weapons/stringsmash.ogg' - instrumentId = "guitar" + allowed_instrument_ids = "guitar" /obj/item/instrument/eguitar name = "electric guitar" @@ -142,29 +119,28 @@ force = 12 attack_verb = list("played metal on", "shredded", "crashed", "smashed") hitsound = 'sound/weapons/stringsmash.ogg' - instrumentId = "eguitar" - instrumentExt = "ogg" + allowed_instrument_ids = "eguitar" /obj/item/instrument/glockenspiel name = "glockenspiel" desc = "Smooth metal bars perfect for any marching band." icon_state = "glockenspiel" item_state = "glockenspiel" - instrumentId = "glockenspiel" + allowed_instrument_ids = "glockenspiel" /obj/item/instrument/accordion name = "accordion" desc = "Pun-Pun not included." icon_state = "accordion" item_state = "accordion" - instrumentId = "accordion" + allowed_instrument_ids = "accordion" /obj/item/instrument/trumpet name = "trumpet" desc = "To announce the arrival of the king!" icon_state = "trumpet" item_state = "trombone" - instrumentId = "trombone" + allowed_instrument_ids = "trombone" /obj/item/instrument/trumpet/spectral name = "spectral trumpet" @@ -172,7 +148,6 @@ icon_state = "trumpet" item_state = "trombone" force = 0 - instrumentId = "trombone" attack_verb = list("played","jazzed","trumpeted","mourned","dooted","spooked") /obj/item/instrument/trumpet/spectral/Initialize() @@ -188,14 +163,13 @@ desc = "This soothing sound will be sure to leave your audience in tears." icon_state = "saxophone" item_state = "saxophone" - instrumentId = "saxophone" + allowed_instrument_ids = "saxophone" /obj/item/instrument/saxophone/spectral name = "spectral saxophone" desc = "This spooky sound will be sure to leave mortals in bones." icon_state = "saxophone" item_state = "saxophone" - instrumentId = "saxophone" force = 0 attack_verb = list("played","jazzed","saxxed","mourned","dooted","spooked") @@ -204,7 +178,7 @@ AddComponent(/datum/component/spooky) /obj/item/instrument/saxophone/spectral/attack(mob/living/carbon/C, mob/user) - playsound (loc, 'sound/instruments/saxophone/En4.mid', 100,1,-1) + playsound(loc, 'sound/instruments/saxophone/En4.mid', 100,1,-1) ..() /obj/item/instrument/trombone @@ -212,12 +186,11 @@ desc = "How can any pool table ever hope to compete?" icon_state = "trombone" item_state = "trombone" - instrumentId = "trombone" + allowed_instrument_ids = "trombone" /obj/item/instrument/trombone/spectral name = "spectral trombone" desc = "A skeleton's favorite instrument. Apply directly on the mortals." - instrumentId = "trombone" icon_state = "trombone" item_state = "trombone" force = 0 @@ -237,14 +210,14 @@ force = 5 icon_state = "recorder" item_state = "recorder" - instrumentId = "recorder" + allowed_instrument_ids = "recorder" /obj/item/instrument/harmonica name = "harmonica" desc = "For when you get a bad case of the space blues." icon_state = "harmonica" item_state = "harmonica" - instrumentId = "harmonica" + allowed_instrument_ids = "harmonica" slot_flags = ITEM_SLOT_MASK force = 5 w_class = WEIGHT_CLASS_SMALL @@ -271,14 +244,22 @@ lefthand_file = 'icons/mob/inhands/equipment/horns_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/horns_righthand.dmi' attack_verb = list("beautifully honks") - instrumentId = "bikehorn" - instrumentExt = "ogg" + allowed_instrument_ids = "bikehorn" w_class = WEIGHT_CLASS_TINY force = 0 throw_speed = 3 throw_range = 15 hitsound = 'sound/items/bikehorn.ogg' +/obj/item/instrument/banjo + name = "banjo" + desc = "A 'Mura' brand banjo. It's pretty much just a drum with a neck and strings." + icon_state = "banjo" + item_state = "banjo" + attack_verb = list("scruggs-styled", "hum-diggitied", "shin-digged", "clawhammered") + hitsound = 'sound/weapons/banjoslap.ogg' + allowed_instrument_ids = "banjo" + /obj/item/musicaltuner name = "musical tuner" desc = "A device for tuning musical instruments both manual and electronic alike." diff --git a/code/modules/instruments/instruments/stationary.dm b/code/modules/instruments/instruments/stationary.dm new file mode 100644 index 0000000000..f236927c38 --- /dev/null +++ b/code/modules/instruments/instruments/stationary.dm @@ -0,0 +1,52 @@ +/obj/structure/musician + name = "Not A Piano" + desc = "Something broke, contact coderbus." + interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT | INTERACT_ATOM_REQUIRES_DEXTERITY + var/can_play_unanchored = FALSE + var/list/allowed_instrument_ids + var/datum/song/song + +/obj/structure/musician/Initialize(mapload) + . = ..() + song = new(src, allowed_instrument_ids) + allowed_instrument_ids = null + +/obj/structure/musician/Destroy() + QDEL_NULL(song) + return ..() + +/obj/structure/musician/proc/should_stop_playing(mob/user) + if(!(anchored || can_play_unanchored)) + return TRUE + if(!user) + return FALSE + return !user.canUseTopic(src, FALSE, TRUE, FALSE, FALSE) //can play with TK and while resting because fun. + +/obj/structure/musician/ui_interact(mob/user) + . = ..() + song.ui_interact(user) + +/obj/structure/musician/wrench_act(mob/living/user, obj/item/I) + default_unfasten_wrench(user, I, 40) + return TRUE + +/obj/structure/musician/piano + name = "space minimoog" + icon = 'icons/obj/musician.dmi' + icon_state = "minimoog" + anchored = TRUE + density = TRUE + +/obj/structure/musician/piano/unanchored + anchored = FALSE + +/obj/structure/musician/piano/Initialize(mapload) + . = ..() + if(prob(50) && icon_state == initial(icon_state)) + name = "space minimoog" + desc = "This is a minimoog, like a space piano, but more spacey!" + icon_state = "minimoog" + else + name = "space piano" + desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't." + icon_state = "piano" diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm new file mode 100644 index 0000000000..67feb14457 --- /dev/null +++ b/code/modules/instruments/songs/_song.dm @@ -0,0 +1,301 @@ +#define MUSICIAN_HEARCHECK_MINDELAY 4 +#define MUSIC_MAXLINES 1000 +#define MUSIC_MAXLINECHARS 300 + +/datum/song + /// Name of the song + var/name = "Untitled" + + /// The atom we're attached to/playing from + var/atom/parent + + /// Our song lines + var/list/lines + + /// delay between notes in deciseconds + var/tempo = 5 + + /// Are we currently playing? + var/playing = FALSE + + /// Are we currently editing? + var/editing = TRUE + /// Is the help screen open? + var/help = FALSE + + /// Repeats left + var/repeat = 0 + /// Maximum times we can repeat + var/max_repeats = 10 + + /// Our volume + var/volume = 75 + /// Max volume + var/max_volume = 75 + /// Min volume - This is so someone doesn't decide it's funny to set it to 0 and play invisible songs. + var/min_volume = 1 + + /// What instruments our built in picker can use. The picker won't show unless this is longer than one. + var/list/allowed_instrument_ids = list("r3grand") + + //////////// Cached instrument variables ///////////// + /// Instrument we are currently using + var/datum/instrument/using_instrument + /// Cached legacy ext for legacy instruments + var/cached_legacy_ext + /// Cached legacy dir for legacy instruments + var/cached_legacy_dir + /// Cached list of samples, referenced directly from the instrument for synthesized instruments + var/list/cached_samples + /// Are we operating in legacy mode (so if the instrument is a legacy instrument) + var/legacy = FALSE + ////////////////////////////////////////////////////// + + /////////////////// Playing variables //////////////// + /** + * Only used in synthesized playback - The chords we compiled. Non assoc list of lists: + * list(list(key1, key2, key3..., tempo_divisor), list(key1, key2..., tempo_divisor), ...) + * tempo_divisor always exists + * if key1 (and so if there's no keys) doesn't exist it's a rest + * Compilation happens when we start playing and is cleared after we finish playing. + */ + var/list/compiled_chords + /// Channel as text = current volume percentage but it's 0 to 100 instead of 0 to 1. + var/list/channels_playing = list() + /// List of channels that aren't being used, as text. This is to prevent unnecessary freeing and reallocations from SSsounds/SSinstruments. + var/list/channels_idle = list() + ////////////////////////////////////////////////////// + + /// Last world.time we checked for who can hear us + var/last_hearcheck = 0 + /// The list of mobs that can hear us + var/list/hearing_mobs + /// If this is enabled, some things won't be strictly cleared when they usually are (liked compiled_chords on play stop) + var/debug_mode = FALSE + /// Last time we processed decay + var/last_process_decay + /// Max sound channels to occupy + var/max_sound_channels = CHANNELS_PER_INSTRUMENT + /// Current channels, so we can save a length() call. + var/using_sound_channels = 0 + /// Last channel to play. text. + var/last_channel_played + /// Should we not decay our last played note? + var/full_sustain_held_note = TRUE + + /////////////////////// DO NOT TOUCH THESE /////////////////// + var/octave_min = INSTRUMENT_MIN_OCTAVE + var/octave_max = INSTRUMENT_MAX_OCTAVE + var/key_min = INSTRUMENT_MIN_KEY + var/key_max = INSTRUMENT_MAX_KEY + var/static/list/note_offset_lookup = list(9, 11, 0, 2, 4, 5, 7) + var/static/list/accent_lookup = list("b" = -1, "s" = 1, "#" = 1, "n" = 0) + ////////////////////////////////////////////////////////////// + + ///////////// !!FUN!! - Only works in synthesized mode! ///////////////// + /// Note numbers to shift. + var/note_shift = 0 + var/note_shift_min = -100 + var/note_shift_max = 100 + var/can_noteshift = TRUE + /// The kind of sustain we're using + var/sustain_mode = SUSTAIN_LINEAR + /// When a note is considered dead if it is below this in volume + var/sustain_dropoff_volume = 0 + /// Total duration of linear sustain for 100 volume note to get to SUSTAIN_DROPOFF + var/sustain_linear_duration = 5 + /// Exponential sustain dropoff rate per decisecond + var/sustain_exponential_dropoff = 1.4 + ////////// DO NOT DIRECTLY SET THESE! + /// Do not directly set, use update_sustain() + var/cached_linear_dropoff = 10 + /// Do not directly set, use update_sustain() + var/cached_exponential_dropoff = 1.045 + ///////////////////////////////////////////////////////////////////////// + +/datum/song/New(atom/parent, list/instrument_ids) + SSinstruments.on_song_new(src) + lines = list() + tempo = sanitize_tempo(tempo) + src.parent = parent + if(instrument_ids) + allowed_instrument_ids = islist(instrument_ids)? instrument_ids : list(instrument_ids) + if(length(allowed_instrument_ids)) + set_instrument(allowed_instrument_ids[1]) + hearing_mobs = list() + volume = clamp(volume, min_volume, max_volume) + update_sustain() + +/datum/song/Destroy() + stop_playing() + SSinstruments.on_song_del(src) + lines = null + using_instrument = null + allowed_instrument_ids = null + parent = null + return ..() + +/datum/song/proc/do_hearcheck() + last_hearcheck = world.time + var/list/old = hearing_mobs.Copy() + hearing_mobs.len = 0 + var/turf/source = get_turf(parent) + for(var/mob/M in get_hearers_in_view(15, source)) + if(!(M?.client?.prefs?.toggles & SOUND_INSTRUMENTS)) + continue + hearing_mobs[M] = get_dist(M, source) + var/list/exited = old - hearing_mobs + for(var/i in exited) + terminate_sound_mob(i) + +/// I can either be a datum, id, or path (if the instrument has no id). +/datum/song/proc/set_instrument(datum/instrument/I) + if(using_instrument) + using_instrument.songs_using -= src + using_instrument = null + cached_samples = null + cached_legacy_ext = null + cached_legacy_dir = null + legacy = null + if(istext(I) || ispath(I)) + I = SSinstruments.instrument_data[I] + if(istype(I)) + using_instrument = I + I.songs_using += src + var/instrument_legacy = CHECK_BITFIELD(I.instrument_flags, INSTRUMENT_LEGACY) + if(instrument_legacy) + cached_legacy_ext = I.legacy_instrument_ext + cached_legacy_dir = I.legacy_instrument_path + legacy = TRUE + else + cached_samples = I.samples + legacy = FALSE + +/// THIS IS A BLOCKING CALL. +/datum/song/proc/start_playing(mob/user) + if(playing) + return + if(!using_instrument?.ready()) + to_chat(user, "An error has occured with [src]. Please reset the instrument.") + return + playing = TRUE + updateDialog() + //we can not afford to runtime, since we are going to be doing sound channel reservations and if we runtime it means we have a channel allocation leak. + //wrap the rest of the stuff to ensure stop_playing() is called. + last_process_decay = world.time + START_PROCESSING(SSinstruments, src) + . = do_play_lines(user) + stop_playing() + +/datum/song/proc/stop_playing() + if(!playing) + return + playing = FALSE + if(!debug_mode) + compiled_chords = null + STOP_PROCESSING(SSinstruments, src) + terminate_all_sounds(TRUE) + hearing_mobs.len = 0 + updateDialog() + +/// THIS IS A BLOCKING CALL. +/datum/song/proc/do_play_lines(user) + if(!playing) + return + do_hearcheck() + if(legacy) + do_play_lines_legacy(user) + else + do_play_lines_synthesized(user) + +/datum/song/proc/should_stop_playing(mob/user) + return QDELETED(parent) || !using_instrument || !playing + +/datum/song/proc/sanitize_tempo(new_tempo) + new_tempo = abs(new_tempo) + return CLAMP(round(new_tempo, world.tick_lag), world.tick_lag, 5 SECONDS) + +/datum/song/proc/get_bpm() + return 600 / tempo + +/datum/song/proc/set_bpm(bpm) + tempo = sanitize_tempo(600 / bpm) + +/// Updates the window for our user. Override in subtypes. +/datum/song/proc/updateDialog(mob/user) + ui_interact(user) + +/datum/song/process(wait) + if(!playing) + return PROCESS_KILL + var/delay = world.time - last_process_decay + process_decay(delay) + last_process_decay = world.time + +/datum/song/proc/update_sustain() + // Exponential is easy + cached_exponential_dropoff = sustain_exponential_dropoff + // Linear, not so much, since it's a target duration from 100 volume rather than an exponential rate. + var/target_duration = sustain_linear_duration + var/volume_diff = max(0, 100 - sustain_dropoff_volume) + var/volume_decrease_per_decisecond = volume_diff / target_duration + cached_linear_dropoff = volume_decrease_per_decisecond + +/datum/song/proc/set_volume(volume) + src.volume = CLAMP(volume, max(0, min_volume), min(100, max_volume)) + update_sustain() + updateDialog() + +/datum/song/proc/set_dropoff_volume(volume) + sustain_dropoff_volume = CLAMP(volume, INSTRUMENT_MIN_SUSTAIN_DROPOFF, 100) + update_sustain() + updateDialog() + +/datum/song/proc/set_exponential_drop_rate(drop) + sustain_exponential_dropoff = CLAMP(drop, INSTRUMENT_EXP_FALLOFF_MIN, INSTRUMENT_EXP_FALLOFF_MAX) + update_sustain() + updateDialog() + +/datum/song/proc/set_linear_falloff_duration(duration) + sustain_linear_duration = CLAMP(duration, 0.1, INSTRUMENT_MAX_TOTAL_SUSTAIN) + update_sustain() + updateDialog() + +/datum/song/vv_edit_var(var_name, var_value) + . = ..() + if(.) + switch(var_name) + if(NAMEOF(src, volume)) + set_volume(var_value) + if(NAMEOF(src, sustain_dropoff_volume)) + set_dropoff_volume(var_value) + if(NAMEOF(src, sustain_exponential_dropoff)) + set_exponential_drop_rate(var_value) + if(NAMEOF(src, sustain_linear_duration)) + set_linear_falloff_duration(var_value) + +// subtype for handheld instruments, like violin +/datum/song/handheld + +/datum/song/handheld/updateDialog(mob/user) + parent.ui_interact(user || usr) + +/datum/song/handheld/should_stop_playing(mob/user) + . = ..() + if(.) + return TRUE + var/obj/item/instrument/I = parent + return I.should_stop_playing(user) + +// subtype for stationary structures, like pianos +/datum/song/stationary + +/datum/song/stationary/updateDialog(mob/user) + parent.ui_interact(user || usr) + +/datum/song/stationary/should_stop_playing(mob/user) + . = ..() + if(.) + return TRUE + var/obj/structure/musician/M = parent + return M.should_stop_playing(user) diff --git a/code/modules/instruments/songs/editor.dm b/code/modules/instruments/songs/editor.dm new file mode 100644 index 0000000000..873ff0e1a7 --- /dev/null +++ b/code/modules/instruments/songs/editor.dm @@ -0,0 +1,246 @@ +/datum/song/proc/instrument_status_ui() + . = list() + . += "
" + . += "Current instrument: " + if(!using_instrument) + . += "No instrument loaded!
" + else + . += "[using_instrument.name]
" + . += "Playback Settings:
" + if(can_noteshift) + . += "Note Shift/Note Transpose: [note_shift] keys / [round(note_shift / 12, 0.01)] octaves
" + var/smt + var/modetext = "" + switch(sustain_mode) + if(SUSTAIN_LINEAR) + smt = "Linear" + modetext = "Linear Sustain Duration: [sustain_linear_duration / 10] seconds
" + if(SUSTAIN_EXPONENTIAL) + smt = "Exponential" + modetext = "Exponential Falloff Factor: [sustain_exponential_dropoff]% per decisecond
" + . += "Sustain Mode: [smt]
" + . += modetext + . += using_instrument?.ready()? "Status: Ready
" : "Status: !Instrument Definition Error!
" + . += "Instrument Type: [legacy? "Legacy" : "Synthesized"]
" + . += "Volume: [volume]
" + . += "Volume Dropoff Threshold: [sustain_dropoff_volume]
" + . += "Sustain indefinitely last held note: [full_sustain_held_note? "Enabled" : "Disabled"].
" + . += "
" + +/datum/song/ui_interact(mob/user) + var/list/dat = list() + + dat += instrument_status_ui() + + if(lines.len > 0) + dat += "

Playback

" + if(!playing) + dat += "Play Stop

" + dat += "Repeat Song: " + dat += repeat > 0 ? "--" : "--" + dat += " [repeat] times " + dat += repeat < max_repeats ? "++" : "++" + dat += "
" + else + dat += "Play Stop
" + dat += "Repeats left: [repeat]
" + if(!editing) + dat += "
Show Editor
" + else + dat += "

Editing

" + dat += "Hide Editor" + dat += " Start a New Song" + dat += " Import a Song

" + var/bpm = round(600 / tempo) + dat += "Tempo: - [bpm] BPM +

" + var/linecount = 0 + for(var/line in lines) + linecount += 1 + dat += "Line [linecount]: Edit X [line]
" + dat += "Add Line

" + if(help) + dat += "Hide Help
" + dat += {" + Lines are a series of chords, separated by commas (,), each with notes separated by hyphens (-).
+ Every note in a chord will play together, with chord timed by the tempo.
+
+ Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.
+ By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.
+ Example: C,D,E,F,G,A,B will play a C major scale.
+ After a note has an accidental placed, it will be remembered: C,C4,C,C3 is C3,C4,C4,C3
+ Chords can be played simply by seperating each note with a hyphon: A-C#,Cn-E,E-G#,Gn-B
+ A pause may be denoted by an empty chord: C,E,,C,G
+ To make a chord be a different time, end it with /x, where the chord length will be length
+ defined by tempo / x: C,G/2,E/4
+ Combined, an example is: E-E4/4,F#/2,G#/8,B/8,E3-E4/4 +
+ Lines may be up to [MUSIC_MAXLINECHARS] characters.
+ A song may only contain up to [MUSIC_MAXLINES] lines.
+ "} + else + dat += "Show Help
" + + var/datum/browser/popup = new(user, "instrument", parent?.name || "instrument", 700, 500) + popup.set_content(dat.Join("")) + popup.set_title_image(user.browse_rsc_icon(parent.icon, parent.icon_state)) + popup.open() + +/datum/song/proc/ParseSong(text) + set waitfor = FALSE + //split into lines + lines = splittext(text, "\n") + if(lines.len) + var/bpm_string = "BPM: " + if(findtext(lines[1], bpm_string, 1, length(bpm_string) + 1)) + var/divisor = text2num(copytext(lines[1], length(bpm_string) + 1)) || 120 // default + tempo = sanitize_tempo(600 / round(divisor, 1)) + lines.Cut(1, 2) + else + tempo = sanitize_tempo(5) // default 120 BPM + if(lines.len > MUSIC_MAXLINES) + to_chat(usr, "Too many lines!") + lines.Cut(MUSIC_MAXLINES + 1) + var/linenum = 1 + for(var/l in lines) + if(length_char(l) > MUSIC_MAXLINECHARS) + to_chat(usr, "Line [linenum] too long!") + lines.Remove(l) + else + linenum++ + updateDialog(usr) // make sure updates when complete + +/datum/song/Topic(href, href_list) + if(!usr.canUseTopic(parent, TRUE, FALSE, FALSE, FALSE)) + usr << browse(null, "window=instrument") + usr.unset_machine() + return + + parent.add_fingerprint(usr) + + if(href_list["newsong"]) + lines = new() + tempo = sanitize_tempo(5) // default 120 BPM + name = "" + + else if(href_list["import"]) + var/t = "" + do + t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", name), t) as message) + if(!in_range(parent, usr)) + return + + if(length_char(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS) + var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") + if(cont == "no") + break + while(length_char(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS) + ParseSong(t) + + else if(href_list["help"]) + help = text2num(href_list["help"]) - 1 + + else if(href_list["edit"]) + editing = text2num(href_list["edit"]) - 1 + + if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. + if(playing) + return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. + repeat += round(text2num(href_list["repeat"])) + if(repeat < 0) + repeat = 0 + if(repeat > max_repeats) + repeat = max_repeats + + else if(href_list["tempo"]) + tempo = sanitize_tempo(tempo + text2num(href_list["tempo"])) + + else if(href_list["play"]) + INVOKE_ASYNC(src, .proc/start_playing, usr) + + else if(href_list["newline"]) + var/newline = html_encode(input("Enter your line: ", parent.name) as text|null) + if(!newline || !in_range(parent, usr)) + return + if(lines.len > MUSIC_MAXLINES) + return + if(length(newline) > MUSIC_MAXLINECHARS) + newline = copytext(newline, 1, MUSIC_MAXLINECHARS) + lines.Add(newline) + + else if(href_list["deleteline"]) + var/num = round(text2num(href_list["deleteline"])) + if(num > lines.len || num < 1) + return + lines.Cut(num, num+1) + + else if(href_list["modifyline"]) + var/num = round(text2num(href_list["modifyline"]),1) + var/content = stripped_input(usr, "Enter your line: ", parent.name, lines[num], MUSIC_MAXLINECHARS) + if(!content || !in_range(parent, usr)) + return + if(num > lines.len || num < 1) + return + lines[num] = content + + else if(href_list["stop"]) + stop_playing() + + else if(href_list["setlinearfalloff"]) + var/amount = input(usr, "Set linear sustain duration in seconds", "Linear Sustain Duration") as null|num + if(!isnull(amount)) + set_linear_falloff_duration(round(amount * 10, world.tick_lag)) + + else if(href_list["setexpfalloff"]) + var/amount = input(usr, "Set exponential sustain factor", "Exponential sustain factor") as null|num + if(!isnull(amount)) + set_exponential_drop_rate(round(amount, 0.00001)) + + else if(href_list["setvolume"]) + var/amount = input(usr, "Set volume", "Volume") as null|num + if(!isnull(amount)) + set_volume(round(amount, 1)) + + else if(href_list["setdropoffvolume"]) + var/amount = input(usr, "Set dropoff threshold", "Dropoff Threshold Volume") as null|num + if(!isnull(amount)) + set_dropoff_volume(round(amount, 0.01)) + + else if(href_list["switchinstrument"]) + if(!length(allowed_instrument_ids)) + return + else if(length(allowed_instrument_ids) == 1) + set_instrument(allowed_instrument_ids[1]) + return + var/list/categories = list() + for(var/i in allowed_instrument_ids) + var/datum/instrument/I = SSinstruments.get_instrument(i) + if(I) + LAZYSET(categories[I.category || "ERROR CATEGORY"], I.name, I.id) + var/cat = input(usr, "Select Category", "Instrument Category") as null|anything in categories + if(!cat) + return + var/list/instruments = categories[cat] + var/choice = input(usr, "Select Instrument", "Instrument Selection") as null|anything in instruments + if(!choice) + return + choice = instruments[choice] //get id + if(choice) + set_instrument(choice) + + else if(href_list["setnoteshift"]) + var/amount = input(usr, "Set note shift", "Note Shift") as null|num + if(!isnull(amount)) + note_shift = CLAMP(amount, note_shift_min, note_shift_max) + + else if(href_list["setsustainmode"]) + var/choice = input(usr, "Choose a sustain mode", "Sustain Mode") as null|anything in list("Linear", "Exponential") + switch(choice) + if("Linear") + sustain_mode = SUSTAIN_LINEAR + if("Exponential") + sustain_mode = SUSTAIN_EXPONENTIAL + + else if(href_list["togglesustainhold"]) + full_sustain_held_note = !full_sustain_held_note + + updateDialog() diff --git a/code/modules/instruments/songs/play_legacy.dm b/code/modules/instruments/songs/play_legacy.dm new file mode 100644 index 0000000000..fa64656ebc --- /dev/null +++ b/code/modules/instruments/songs/play_legacy.dm @@ -0,0 +1,82 @@ +/// Playing legacy instruments - None of the "advanced" like sound reservations and decay are invoked. +/datum/song/proc/do_play_lines_legacy(mob/user) + while(repeat >= 0) + var/cur_oct[7] + var/cur_acc[7] + for(var/i = 1 to 7) + cur_oct[i] = 3 + cur_acc[i] = "n" + + for(var/line in lines) + for(var/beat in splittext(lowertext(line), ",")) + if(should_stop_playing(user)) + return + var/list/notes = splittext(beat, "/") + if(length(notes)) //because some jack-butts are going to do ,,,, to symbolize 3 rests instead of something reasonable like ,/1. + for(var/note in splittext(notes[1], "-")) + if(length(note) == 0) + continue + var/cur_note = text2ascii(note) - 96 + if(cur_note < 1 || cur_note > 7) + continue + for(var/i=2 to length(note)) + var/ni = copytext(note,i,i+1) + if(!text2num(ni)) + if(ni == "#" || ni == "b" || ni == "n") + cur_acc[cur_note] = ni + else if(ni == "s") + cur_acc[cur_note] = "#" // so shift is never required + else + cur_oct[cur_note] = text2num(ni) + playnote_legacy(cur_note, cur_acc[cur_note], cur_oct[cur_note]) + if(notes.len >= 2 && text2num(notes[2])) + sleep(sanitize_tempo(tempo / text2num(notes[2]))) + else + sleep(tempo) + if(should_stop_playing(user)) + return + repeat-- + updateDialog() + repeat = 0 + +// note is a number from 1-7 for A-G +// acc is either "b", "n", or "#" +// oct is 1-8 (or 9 for C) +/datum/song/proc/playnote_legacy(note, acc as text, oct) + // handle accidental -> B<>C of E<>F + if(acc == "b" && (note == 3 || note == 6)) // C or F + if(note == 3) + oct-- + note-- + acc = "n" + else if(acc == "#" && (note == 2 || note == 5)) // B or E + if(note == 2) + oct++ + note++ + acc = "n" + else if(acc == "#" && (note == 7)) //G# + note = 1 + acc = "b" + else if(acc == "#") // mass convert all sharps to flats, octave jump already handled + acc = "b" + note++ + + // check octave, C is allowed to go to 9 + if(oct < 1 || (note == 3 ? oct > 9 : oct > 8)) + return + + // now generate name + var/soundfile = "sound/instruments/[cached_legacy_dir]/[ascii2text(note+64)][acc][oct].[cached_legacy_ext]" + soundfile = file(soundfile) + // make sure the note exists + if(!fexists(soundfile)) + return + // and play + var/turf/source = get_turf(parent) + if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck) + do_hearcheck() + var/sound/music_played = sound(soundfile) + for(var/i in hearing_mobs) + var/mob/M = i + M.playsound_local(source, null, volume * using_instrument.volume_multiplier, falloff = 5, S = music_played) + // Could do environment and echo later but not for now diff --git a/code/modules/instruments/songs/play_synthesized.dm b/code/modules/instruments/songs/play_synthesized.dm new file mode 100644 index 0000000000..2573da324a --- /dev/null +++ b/code/modules/instruments/songs/play_synthesized.dm @@ -0,0 +1,135 @@ +/datum/song/proc/do_play_lines_synthesized(mob/user) + compile_lines() + while(repeat >= 0) + if(should_stop_playing(user)) + return + var/warned = FALSE + for(var/_chord in compiled_chords) + if(should_stop_playing(user)) + return + var/list/chord = _chord + var/tempodiv = chord[chord.len] + for(var/i in 1 to chord.len - 1) + var/key = chord[i] + if(!playkey_synth(key)) + if(!warned) + warned = TRUE + to_chat(user, "Your instrument has ran out of channels. You might be playing your song too fast or be setting sustain to too high of a value. This warning will be suppressed for the rest of this cycle.") + sleep(sanitize_tempo(tempo / (tempodiv || 1))) + repeat-- + updateDialog() + repeat = 0 + +/// C-Db2-A-A4/2,A-B#4-C/3,/4,A,A-B-C as an example +/datum/song/proc/compile_lines() + if(!length(src.lines)) + return + var/list/lines = src.lines //cache for hyepr speed! + compiled_chords = list() + var/list/octaves = list(3, 3, 3, 3, 3, 3, 3) + var/list/accents = list("n", "n", "n", "n", "n", "n", "n") + for(var/line in lines) + var/list/chords = splittext(lowertext(line), ",") + for(var/chord in chords) + var/list/compiled_chord = list() + var/tempodiv = 1 + var/list/notes_tempodiv = splittext(chord, "/") + var/len = length(notes_tempodiv) + if(len >= 2) + tempodiv = text2num(notes_tempodiv[2]) + if(len) //some dunkass is going to do ,,,, to make 3 rests instead of ,/1 because there's no standardization so let's be prepared for that. + var/list/notes = splittext(notes_tempodiv[1], "-") + for(var/note in notes) + if(length(note) == 0) + continue + // 1-7, A-G + var/key = text2ascii(note) - 96 + if((key < 1) || (key > 7)) + continue + for(var/i in 2 to length(note)) + var/oct_acc = copytext(note, i, i + 1) + var/num = text2num(oct_acc) + if(!num) //it's an accidental + accents[key] = oct_acc //if they misspelled it/fucked up that's on them lmao, no safety checks. + else //octave + octaves[key] = CLAMP(num, octave_min, octave_max) + compiled_chord += CLAMP((note_offset_lookup[key] + octaves[key] * 12 + accent_lookup[accents[key]]), key_min, key_max) + compiled_chord += tempodiv //this goes last + if(length(compiled_chord)) + compiled_chords[++compiled_chords.len] = compiled_chord + CHECK_TICK + return compiled_chords + +/datum/song/proc/playkey_synth(key) + if(can_noteshift) + key = clamp(key + note_shift, key_min, key_max) + if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck) + do_hearcheck() + var/datum/instrument_key/K = using_instrument.samples[num2text(key)] //See how fucking easy it is to make a number text? You don't need a complicated 9 line proc! + //Should probably add channel limiters here at some point but I don't care right now. + var/channel = pop_channel() + if(isnull(channel)) + return FALSE + . = TRUE + var/sound/copy = sound(K.sample) + var/volume = src.volume * using_instrument.volume_multiplier + copy.frequency = K.frequency + copy.volume = volume + var/channel_text = num2text(channel) + channels_playing[channel_text] = 100 + last_channel_played = channel_text + for(var/i in hearing_mobs) + var/mob/M = i + M.playsound_local(get_turf(parent), null, volume, FALSE, K.frequency, INSTRUMENT_DISTANCE_NO_FALLOFF, channel, null, copy, distance_multiplier = INSTRUMENT_DISTANCE_FALLOFF_BUFF) + // Could do environment and echo later but not for now + +/datum/song/proc/terminate_all_sounds(clear_channels = TRUE) + for(var/i in hearing_mobs) + terminate_sound_mob(i) + if(clear_channels) + channels_playing.len = 0 + channels_idle.len = 0 + SSinstruments.current_instrument_channels -= using_sound_channels + using_sound_channels = 0 + SSsounds.free_datum_channels(src) + +/datum/song/proc/terminate_sound_mob(mob/M) + for(var/channel in channels_playing) + M.stop_sound_channel(text2num(channel)) + +/datum/song/proc/pop_channel() + if(length(channels_idle)) //just pop one off of here if we have one available + . = text2num(channels_idle[1]) + channels_idle.Cut(1,2) + return + if(using_sound_channels >= max_sound_channels) + return + . = SSinstruments.reserve_instrument_channel(src) + if(!isnull(.)) + using_sound_channels++ + +/datum/song/proc/process_decay(wait_ds) + var/linear_dropoff = cached_linear_dropoff * wait_ds + var/exponential_dropoff = cached_exponential_dropoff ** wait_ds + for(var/channel in channels_playing) + if(full_sustain_held_note && (channel == last_channel_played)) + continue + var/current_volume = channels_playing[channel] + switch(sustain_mode) + if(SUSTAIN_LINEAR) + current_volume -= linear_dropoff + if(SUSTAIN_EXPONENTIAL) + current_volume /= exponential_dropoff + channels_playing[channel] = current_volume + var/dead = current_volume <= sustain_dropoff_volume + var/channelnumber = text2num(channel) + if(dead) + channels_playing -= channel + channels_idle += channel + for(var/i in hearing_mobs) + var/mob/M = i + M.stop_sound_channel(channelnumber) + else + for(var/i in hearing_mobs) + var/mob/M = i + M.set_sound_channel_volume(channelnumber, (current_volume * 0.01) * volume * using_instrument.volume_multiplier) diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm index d4c565c49a..d0c47f0950 100644 --- a/code/modules/integrated_electronics/subtypes/smart.dm +++ b/code/modules/integrated_electronics/subtypes/smart.dm @@ -18,8 +18,8 @@ var/datum/integrated_io/I = inputs[1] set_pin_data(IC_OUTPUT, 1, null) if(!isweakref(I.data)) - return activate_pin(3) + return var/atom/A = I.data.resolve() if(!A) activate_pin(3) diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index c5065cd169..0d70e872ac 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -42,7 +42,7 @@ uniform = /obj/item/clothing/under/rank/engineering/chief_engineer shoes = /obj/item/clothing/shoes/sneakers/brown head = /obj/item/clothing/head/hardhat/white - gloves = /obj/item/clothing/gloves/color/black/ce + gloves = /obj/item/clothing/gloves/color/black backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced=1) backpack = /obj/item/storage/backpack/industrial diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index 811dff87e7..3cf4fbb102 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -42,7 +42,7 @@ uniform = /obj/item/clothing/under/rank/security/head_of_security shoes = /obj/item/clothing/shoes/jackboots suit = /obj/item/clothing/suit/armor/hos/trenchcoat - gloves = /obj/item/clothing/gloves/color/black/hos + gloves = /obj/item/clothing/gloves/color/black head = /obj/item/clothing/head/HoS/beret glasses = /obj/item/clothing/glasses/hud/security/sunglasses suit_store = /obj/item/gun/energy/e_gun diff --git a/code/modules/language/vampiric.dm b/code/modules/language/vampiric.dm index 6da54ce844..ab48a17d2f 100644 --- a/code/modules/language/vampiric.dm +++ b/code/modules/language/vampiric.dm @@ -1,4 +1,4 @@ -// VAMPIRE LANGUAGE // +// BLOODSUCKER LANGUAGE // /datum/language/vampiric name = "Blah-Sucker" diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index e83ac26153..30eed6c8f0 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -117,10 +117,10 @@ glass_overlay.appearance_flags = RESET_COLOR . += glass_overlay -/obj/item/clothing/head/helmet/space/hostile_environment/worn_overlays(isinhands, icon_file, style_flags = NONE) +/obj/item/clothing/head/helmet/space/hostile_environment/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) - var/mutable_appearance/M = mutable_appearance('icons/mob/head.dmi', "hostile_env_glass") + var/mutable_appearance/M = mutable_appearance('icons/mob/clothing/head.dmi', "hostile_env_glass") M.appearance_flags = RESET_COLOR . += M diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index b515ebbc13..1fd1b31b69 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -433,19 +433,23 @@ desc = "A glowing trinket that was originally the Hierophant's beacon. Suitable as a trophy for a kinetic crusher." icon_state = "vortex_talisman" denied_type = /obj/item/crusher_trophy/vortex_talisman + var/vortex_cd /obj/item/crusher_trophy/vortex_talisman/effect_desc() - return "mark detonation to create a barrier you can pass" + return "mark detonation to create a barrier you can pass that lasts for 7.5 seconds, with a cooldown of 9 seconds after creation." /obj/item/crusher_trophy/vortex_talisman/on_mark_detonation(mob/living/target, mob/living/user) + if(vortex_cd >= world.time) + return var/turf/T = get_turf(user) - new /obj/effect/temp_visual/hierophant/wall/crusher(T, user) //a wall only you can pass! + var/obj/effect/temp_visual/hierophant/wall/crusher/W = new (T, user) //a wall only you can pass! var/turf/otherT = get_step(T, turn(user.dir, 90)) if(otherT) new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user) otherT = get_step(T, turn(user.dir, -90)) if(otherT) new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user) + vortex_cd = world.time + W.duration * 1.2 /obj/effect/temp_visual/hierophant/wall/crusher duration = 75 diff --git a/code/modules/mining/equipment/regenerative_core.dm b/code/modules/mining/equipment/regenerative_core.dm index ae451ba1a8..c14aa097bb 100644 --- a/code/modules/mining/equipment/regenerative_core.dm +++ b/code/modules/mining/equipment/regenerative_core.dm @@ -26,8 +26,8 @@ slot = "hivecore" force = 0 actions_types = list(/datum/action/item_action/organ_action/use) - var/inert = 0 - var/preserved = 0 + var/inert + var/preserved /obj/item/organ/regenerative_core/Initialize() . = ..() @@ -38,7 +38,9 @@ go_inert() /obj/item/organ/regenerative_core/proc/preserved(implanted = 0) - inert = FALSE + if(inert) + name = initial(name) + inert = FALSE preserved = TRUE update_icon() desc = "All that remains of a hivelord. It is preserved, allowing you to use it to heal completely without danger of decay." @@ -69,14 +71,15 @@ /obj/item/organ/regenerative_core/afterattack(atom/target, mob/user, proximity_flag) . = ..() - if(proximity_flag && ishuman(target)) + if(proximity_flag) + apply_healing_core(target, user) + +/obj/item/organ/regenerative_core/proc/apply_healing_core(atom/target, mob/user) + if(ishuman(target)) var/mob/living/carbon/human/H = target if(inert) to_chat(user, "[src] has decayed and can no longer be used to heal.") return - if(isvamp(user)) - to_chat(user, "[src] breaks down as it fails to heal your unholy self") - return else if(H.stat == DEAD) to_chat(user, "[src] are useless on the dead.") @@ -87,22 +90,16 @@ else to_chat(user, "You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.") SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self")) - H.revive(full_heal = 1) + if(AmBloodsucker(H)) + H.revive(full_heal = FALSE) + else + H.revive(full_heal = TRUE) qdel(src) user.log_message("[user] used [src] to heal [H]! Wake the fuck up, Samurai!", LOG_ATTACK, color="green") //Logging for 'old' style legion core use, when clicking on a sprite of yourself or another. /obj/item/organ/regenerative_core/attack_self(mob/user) //Knouli's first hack! Allows for the use of the core in hand rather than needing to click on the target, yourself, to selfheal. Its a rip of the proc just above - but skips on distance check and only uses 'user' rather than 'target' - if(ishuman(user)) //Check if user is human, no need for distance check as it's self heal - var/mob/living/carbon/human/H = user //Set H to user rather than target - if(inert) //Inert cores are useless - to_chat(user, "[src] has decayed and can no longer be used to heal.") - return - else //Skip on check if the target to be healed is dead as, if you are dead, you're not going to be able to use it on yourself! - to_chat(user, "You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.") - SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self")) - H.revive(full_heal = 1) - qdel(src) - H.log_message("[H] used [src] to heal themselves! Making use of Knouli's sexy and intelligent use-in-hand proc!", LOG_ATTACK, color="green") //Logging for 'new' style legion core use, when using the core in-hand. + . = ..() + apply_healing_core(user) /obj/item/organ/regenerative_core/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index a95c0e24ed..56e1a04b95 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -835,9 +835,9 @@ force = CLAMP((ghost_counter * 4), 0, 75) user.visible_message("[user] strikes with the force of [ghost_counter] vengeful spirits!") - ..() + return ..() -/obj/item/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) +/obj/item/melee/ghost_sword/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) var/ghost_counter = ghost_check() final_block_chance += CLAMP((ghost_counter * 5), 0, 75) owner.visible_message("[owner] is protected by a ring of [ghost_counter] ghosts!") diff --git a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm index 4365e59a7a..ab278b2e82 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm @@ -76,7 +76,7 @@ var/list/recommended_species /datum/sprite_accessory/underwear - icon = 'icons/mob/underwear.dmi' + icon = 'icons/mob/clothing/underwear.dmi' var/has_color = FALSE var/has_digitigrade = FALSE var/covers_groin = FALSE diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 3023b93856..b2d02d8fa2 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -276,7 +276,23 @@ Works together with spawning an observer, noted above. if (!(client.prefs.chat_toggles & CHAT_OOC)) client.prefs.chat_toggles ^= CHAT_OOC transfer_ckey(ghost, FALSE) - ghost.AddElement(/datum/element/ghost_role_eligibility,penalize) // technically already run earlier, but this adds the penalty + if(penalize) + var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) MINUTES + var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES + if(world.time < roundstart_quit_limit) //add up the time difference to their antag rolling penalty if they quit before half a (ingame) hour even passed. + penalty += roundstart_quit_limit - world.time + if(penalty) + penalty += world.realtime + if(SSautotransfer.can_fire && SSautotransfer.maxvotes) + 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) + return + GLOB.client_ghost_timeouts[ckey] = max(GLOB.client_ghost_timeouts[ckey],penalty) // needs to be done AFTER the ckey transfer, too return ghost diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index ef6a372f9e..42b2c4433b 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -21,14 +21,13 @@ Doesn't work on other aliens/AI.*/ . = ..() action = new(src) -/obj/effect/proc_holder/alien/Click() - if(!iscarbon(usr)) - return 1 - var/mob/living/carbon/user = usr - if(cost_check(check_turf,user)) +/obj/effect/proc_holder/alien/Trigger(mob/living/carbon/user, skip_cost_check) + if(!istype(user)) + return TRUE + if(!skip_cost_check || cost_check(check_turf,user)) if(fire(user) && user) // Second check to prevent runtimes when evolving user.adjustPlasma(-plasma_cost) - return 1 + return TRUE /obj/effect/proc_holder/alien/on_gain(mob/living/carbon/user) return diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index e0647159a5..faea8e9bbc 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -63,13 +63,13 @@ if(hit_atom) if(isliving(hit_atom)) var/mob/living/L = hit_atom - if(!L.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK)) + if(L.run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS) + DefaultCombatKnockdown(40, 1, 1) + else L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") L.DefaultCombatKnockdown(100) sleep(2)//Runtime prevention (infinite bump() calls on hulks) step_towards(src,L) - else - DefaultCombatKnockdown(40, 1, 1) toggle_leap(0) else if(hit_atom.density && !hit_atom.CanPass(src)) diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index 6947ab28f8..eb1b38b9ff 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -247,13 +247,13 @@ /proc/CanHug(mob/living/M) if(!istype(M)) - return 0 + return FALSE if(M.stat == DEAD) - return 0 + return FALSE if(M.getorgan(/obj/item/organ/alien/hivenode)) - return 0 - if(isvamp(M)) - return 0 + return FALSE + if(AmBloodsucker(M)) + return FALSE if(ismonkey(M)) return 1 @@ -262,9 +262,9 @@ if(ishuman(C) && !(SLOT_WEAR_MASK in C.dna.species.no_equip)) var/mob/living/carbon/human/H = C if(H.is_mouth_covered(head_only = 1)) - return 0 - return 1 - return 0 + return FALSE + return TRUE + return FALSE #undef MIN_ACTIVE_TIME #undef MAX_ACTIVE_TIME diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index fc85fc25c4..40b8de36c5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -430,7 +430,6 @@ else dropItemToGround(I) return - return TRUE /mob/living/carbon/get_standard_pixel_y_offset(lying = 0) if(lying) @@ -855,7 +854,7 @@ /mob/living/carbon/proc/can_defib() var/tlimit = DEFIB_TIME_LIMIT * 10 var/obj/item/organ/heart = getorgan(/obj/item/organ/heart) - if(suiciding || hellbound || HAS_TRAIT(src, TRAIT_HUSK)) + if(suiciding || hellbound || HAS_TRAIT(src, TRAIT_HUSK) || AmBloodsucker(src)) return if((world.time - timeofdeath) > tlimit) return diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 836560ca99..9c4f0316b7 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -9,7 +9,7 @@ if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses var/obj/item/clothing/glasses/GFP = src.glasses number += GFP.flash_protect - + if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask var/obj/item/clothing/mask/MFP = src.wear_mask number += MFP.flash_protect @@ -86,13 +86,10 @@ if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) totitemdamage *= 1.5 //CIT CHANGES END HERE - if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration)) + var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected) + if((user != src) && (run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone) & BLOCK_SUCCESS)) return FALSE - var/obj/item/bodypart/affecting - if(user == src) - affecting = get_bodypart(check_zone(user.zone_selected)) //we're self-mutilating! yay! - else - affecting = get_bodypart(ran_zone(user.zone_selected)) + var/obj/item/bodypart/affecting = get_bodypart(impacting_zone) if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest) affecting = bodyparts[1] SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting) @@ -278,6 +275,8 @@ if(health >= 0 && !(HAS_TRAIT(src, TRAIT_FAKEDEATH))) var/friendly_check = FALSE + if(run_block(M, 0, M.name, ATTACK_TYPE_UNARMED)) + return if(lying) if(buckled) to_chat(M, "You need to unbuckle [src] first to do that!") diff --git a/code/modules/mob/living/carbon/human/human_block.dm b/code/modules/mob/living/carbon/human/human_block.dm new file mode 100644 index 0000000000..b1a5153ce5 --- /dev/null +++ b/code/modules/mob/living/carbon/human/human_block.dm @@ -0,0 +1,8 @@ +/mob/living/carbon/human/get_blocking_items() + . = ..() + if(wear_suit) + . += wear_suit + if(w_uniform) + . += w_uniform + if(wear_neck) + . += wear_neck diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index f4227e390e..324420a7dd 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -52,36 +52,12 @@ return martial_art_result return ..() -/mob/living/carbon/human/check_reflect(def_zone) - if(wear_suit?.IsReflect(def_zone)) - return TRUE - return ..() - -/mob/living/carbon/human/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) - . = ..() - if(.) - return - var/block_chance_modifier = round(damage / -3) - if(wear_suit) - var/final_block_chance = wear_suit.block_chance - (CLAMP((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier - if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) - return TRUE - if(w_uniform) - var/final_block_chance = w_uniform.block_chance - (CLAMP((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier - if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) - return TRUE - if(wear_neck) - var/final_block_chance = wear_neck.block_chance - (CLAMP((armour_penetration-wear_neck.armour_penetration)/2,0,100)) + block_chance_modifier - if(wear_neck.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) - return TRUE - return FALSE - /mob/living/carbon/human/can_embed(obj/item/I) if(I.get_sharpness() || is_pointed(I) || is_type_in_typecache(I, GLOB.can_embed_types)) return TRUE return FALSE -/mob/living/carbon/human/proc/check_block() +/mob/living/carbon/human/proc/check_martial_melee_block() if(mind) if(mind.martial_art && prob(mind.martial_art.block_chance) && mind.martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE)) return TRUE diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 34c65982dc..e39ce7d488 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -893,7 +893,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) accessory_overlay.icon_state = "m_ears_none_[layertext]" if(bodypart == "tail") accessory_overlay.icon_state = "m_tail_husk_[layertext]" - if(MATRIXED) + if(S.color_src == MATRIXED) var/list/husklist = list() husklist += ReadRGB("#a3a3a3") husklist += ReadRGB("#a3a3a3") @@ -1437,7 +1437,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) to_chat(user, "You do not breathe, so you cannot perform CPR.") /datum/species/proc/grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) - if(target.check_block()) + if(target.check_martial_melee_block()) target.visible_message("[target] blocks [user]'s grab attempt!") return 0 if(attacker_style && attacker_style.grab_act(user,target)) @@ -1453,9 +1453,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(IS_STAMCRIT(user)) //CITADEL CHANGE - makes it impossible to punch while in stamina softcrit to_chat(user, "You're too exhausted.") //CITADEL CHANGE - ditto return FALSE //CITADEL CHANGE - ditto - if(target.check_block()) + if(target.check_martial_melee_block()) target.visible_message("[target] blocks [user]'s attack!") return FALSE + + if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount + user.adjustStaminaLossBuffered(1.5) + else + user.adjustStaminaLossBuffered(3.5) + if(attacker_style && attacker_style.harm_act(user,target)) return TRUE else @@ -1474,8 +1480,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) else user.do_attack_animation(target, ATTACK_EFFECT_PUNCH) - user.adjustStaminaLossBuffered(3.5) //CITADEL CHANGE - makes punching cause staminaloss - var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh) var/puncherstam = user.getStaminaLoss() var/puncherbrute = user.getBruteLoss() @@ -1534,13 +1538,24 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if((target.stat != DEAD) && damage >= user.dna.species.punchstunthreshold) if((punchedstam > 50) && prob(punchedstam*0.5)) //If our punch victim has been hit above the threshold, and they have more than 50 stamina damage, roll for stun, probability of 1% per 2 stamina damage + target.visible_message("[user] knocks [target] down!", \ "You're knocked down by [user]!", "You hear aggressive shuffling followed by a loud thud!", COMBAT_MESSAGE_RANGE, user) to_chat(user, "You knock [target] down!") + var/knockdown_duration = 40 + (punchedstam + (punchedbrute*0.5))*0.8 - armor_block target.DefaultCombatKnockdown(knockdown_duration) target.forcesay(GLOB.hit_appends) log_combat(user, target, "got a stun punch with their previous punch") + + if(HAS_TRAIT(user, TRAIT_KI_VAMPIRE) && !HAS_TRAIT(target, TRAIT_NOBREATH) && (punchedbrute < 100)) //If we're a ki vampire we also sap them of lifeforce, but only if they're not too beat up. Also living organics only. + user.adjustBruteLoss(-5) + user.adjustFireLoss(-5) + user.adjustStaminaLoss(-20) + + target.adjustCloneLoss(10) + target.adjustBruteLoss(10) + else if(!(target.mobility_flags & MOBILITY_STAND)) target.forcesay(GLOB.hit_appends) @@ -1557,6 +1572,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/aim_for_groin = user.zone_selected == "groin" var/target_aiming_for_groin = target.zone_selected == "groin" + if(target.check_martial_melee_block()) //END EDIT + target.visible_message("[target] blocks [user]'s disarm attempt!") + return FALSE if(IS_STAMCRIT(user)) to_chat(user, "You're too exhausted!") return FALSE @@ -1685,9 +1703,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) // Allows you to put in item-specific reactions based on species if(user != H) - if(H.check_shields(I, I.force, "the [I.name]", MELEE_ATTACK, I.armour_penetration)) + if(H.run_block(I, I.force, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone) & BLOCK_SUCCESS) return 0 - if(H.check_block()) + if(H.check_martial_melee_block()) H.visible_message("[H] blocks [I]!") return 0 @@ -1803,7 +1821,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) return TRUE if(M.mind) attacker_style = M.mind.martial_art - if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK)) + if((M != H) && M.a_intent != INTENT_HELP && (H.run_block(M, 0, "[M]", ATTACK_TYPE_UNARMED, 0, M, M.zone_selected) & BLOCK_SUCCESS)) log_combat(M, H, "attempted to touch") H.visible_message("[M] attempted to touch [H]!") return TRUE @@ -1841,7 +1859,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(IS_STAMCRIT(user)) to_chat(user, "You're too exhausted.") return FALSE - if(target.check_block()) + if(target.check_martial_melee_block()) target.visible_message("[target] blocks [user]'s shoving attempt!") return FALSE if(attacker_style && attacker_style.disarm_act(user,target)) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 446e726256..abc2288e9b 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -11,7 +11,7 @@ siemens_coeff = 0 punchdamagelow = 5 punchdamagehigh = 14 - punchstunthreshold = 11 //about 40% chance to stun + punchstunthreshold = 10 no_equip = list(SLOT_WEAR_MASK, SLOT_WEAR_SUIT, SLOT_GLOVES, SLOT_SHOES, SLOT_W_UNIFORM, SLOT_S_STORE) nojumpsuit = 1 sexes = 1 @@ -168,7 +168,7 @@ name = "Silver Golem" id = "silver golem" fixed_mut_color = "ddd" - punchstunthreshold = 9 //60% chance, from 40% + punchstunthreshold = 9 meat = /obj/item/stack/ore/silver info_text = "As a Silver Golem, your attacks have a higher chance of stunning. Being made of silver, your body is immune to most types of magic." prefix = "Silver" @@ -190,7 +190,7 @@ stunmod = 0.4 punchdamagelow = 12 punchdamagehigh = 21 - punchstunthreshold = 18 //still 40% stun chance + punchstunthreshold = 18 speedmod = 4 //pretty fucking slow meat = /obj/item/stack/ore/iron info_text = "As a Plasteel Golem, you are slower, but harder to stun, and hit very hard when punching." @@ -469,7 +469,7 @@ var/cooldown = 150 var/last_teleport = 0 -/datum/action/innate/unstable_teleport/IsAvailable() +/datum/action/innate/unstable_teleport/IsAvailable(silent = FALSE) if(..()) if(world.time > last_teleport + cooldown) return 1 diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 9937b52002..775f36cfc7 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -43,7 +43,7 @@ C.faction |= "slime" /datum/species/jelly/spec_life(mob/living/carbon/human/H) - if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for vampires + if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for blooduskers return if(!H.blood_volume) H.blood_volume += 5 @@ -84,7 +84,7 @@ background_icon_state = "bg_alien" required_mobility_flags = NONE -/datum/action/innate/regenerate_limbs/IsAvailable() +/datum/action/innate/regenerate_limbs/IsAvailable(silent = FALSE) if(..()) var/mob/living/carbon/human/H = owner var/list/limbs_to_heal = H.get_missing_limbs() @@ -223,7 +223,7 @@ icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" -/datum/action/innate/split_body/IsAvailable() +/datum/action/innate/split_body/IsAvailable(silent = FALSE) if(..()) var/mob/living/carbon/human/H = owner if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT) @@ -776,7 +776,7 @@ ..() species = _species -/datum/action/innate/use_extract/IsAvailable() +/datum/action/innate/use_extract/IsAvailable(silent = FALSE) if(..()) if(species && species.current_extract && (world.time > species.extract_cooldown)) return TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 3c17ef9066..cb8fdbf101 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -12,9 +12,9 @@ inherent_traits = list(TRAIT_NOBREATH) speedmod = 1.5 //faster than golems but not by much - punchdamagelow = 6 - punchdamagehigh = 14 - punchstunthreshold = 14 //about 44% chance to stun + punchdamagelow = 2 + punchdamagehigh = 12 //still better than humans + punchstunthreshold = 10 no_equip = list(SLOT_WEAR_MASK, SLOT_WEAR_SUIT, SLOT_GLOVES, SLOT_SHOES, SLOT_W_UNIFORM) diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm index 1700927a24..6c42e622fe 100644 --- a/code/modules/mob/living/carbon/human/species_types/synths.dm +++ b/code/modules/mob/living/carbon/human/species_types/synths.dm @@ -23,7 +23,7 @@ armor = 25 punchdamagelow = 10 punchdamagehigh = 19 - punchstunthreshold = 14 //about 50% chance to stun + punchstunthreshold = 14 disguise_fail_health = 50 /datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species) diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 7c5f0f473a..415cd9889c 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -81,6 +81,9 @@ if(H.blood_volume >= BLOOD_VOLUME_MAXIMUM) to_chat(H, "You're already full!") return + //This checks whether or not they are wearing a garlic clove on their neck + if(!blood_sucking_checks(victim, TRUE, FALSE)) + return if(victim.stat == DEAD) to_chat(H, "You need a living victim!") return @@ -92,6 +95,9 @@ to_chat(victim, "[H] tries to bite you, but stops before touching you!") to_chat(H, "[victim] is blessed! You stop just in time to avoid catching fire.") return + //Here we check now for both the garlic cloves on the neck and for blood in the victims bloodstream. + if(!blood_sucking_checks(victim, TRUE, TRUE)) + return if(!do_after(H, 30, target = victim)) return var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index cb603dee90..63e772e07c 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -118,17 +118,15 @@ There are several things that need to be remembered: return - var/t_color = U.item_color - if(!t_color) - t_color = U.icon_state + var/target_overlay = U.icon_state if(U.adjusted == ALT_STYLE) - t_color = "[t_color]_d" + target_overlay = "[target_overlay]_d" - var/alt_worn = U.alternate_worn_icon || 'icons/mob/uniform.dmi' + var/alt_worn = U.mob_overlay_icon || 'icons/mob/clothing/uniform.dmi' var/variant_flag = NONE if((DIGITIGRADE in dna.species.species_traits) && U.mutantrace_variation & STYLE_DIGITIGRADE) - alt_worn = 'icons/mob/uniform_digi.dmi' + alt_worn = 'icons/mob/clothing/uniform_digi.dmi' variant_flag |= STYLE_DIGITIGRADE var/mutable_appearance/uniform_overlay @@ -136,10 +134,10 @@ There are several things that need to be remembered: if(dna && dna.species.sexes) var/G = (dna.features["body_model"] == FEMALE) ? "f" : "m" if(G == "f" && U.fitted != NO_FEMALE_UNIFORM) - uniform_overlay = U.build_worn_icon(t_color, UNIFORM_LAYER, alt_worn, FALSE, U.fitted, variant_flag, FALSE) + uniform_overlay = U.build_worn_icon(UNIFORM_LAYER, alt_worn, FALSE, U.fitted, target_overlay, variant_flag, FALSE) if(!uniform_overlay) - uniform_overlay = U.build_worn_icon(t_color, UNIFORM_LAYER, alt_worn, FALSE, NO_FEMALE_UNIFORM, variant_flag, FALSE) + uniform_overlay = U.build_worn_icon( UNIFORM_LAYER, alt_worn, FALSE, NO_FEMALE_UNIFORM, target_overlay, variant_flag, FALSE) if(OFFSET_UNIFORM in dna.species.offset_features) @@ -167,7 +165,7 @@ There are several things that need to be remembered: update_observer_view(wear_id) //TODO: add an icon file for ID slot stuff, so it's less snowflakey - id_overlay = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi') + id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi', override_state = wear_id.item_state) if(OFFSET_ID in dna.species.offset_features) id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1] id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2] @@ -199,10 +197,7 @@ There are several things that need to be remembered: if(hud_used.inventory_shown) client.screen += gloves update_observer_view(gloves,1) - var/t_state = gloves.item_state - if(!t_state) - t_state = gloves.icon_state - overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/hands.dmi') + overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/clothing/hands.dmi') gloves_overlay = overlays_standing[GLOVES_LAYER] if(OFFSET_GLOVES in dna.species.offset_features) gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1] @@ -228,7 +223,7 @@ There are several things that need to be remembered: client.screen += glasses //Either way, add the item to the HUD update_observer_view(glasses,1) if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES))) - overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/eyes.dmi') + overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/clothing/eyes.dmi', override_state = glasses.icon_state) var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER] if(glasses_overlay) if(OFFSET_GLASSES in dna.species.offset_features) @@ -255,7 +250,7 @@ There are several things that need to be remembered: client.screen += ears //add it to the client's screen update_observer_view(ears,1) - overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi') + overlays_standing[EARS_LAYER] = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi') var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER] if(OFFSET_EARS in dna.species.offset_features) ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1] @@ -282,16 +277,13 @@ There are several things that need to be remembered: client.screen += shoes //add it to client's screen update_observer_view(shoes,1) - var/alt_icon = S.alternate_worn_icon || 'icons/mob/feet.dmi' + var/alt_icon = S.mob_overlay_icon || 'icons/mob/clothing/feet.dmi' var/variation_flag = NONE if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE) - alt_icon = 'icons/mob/feet_digi.dmi' + alt_icon = 'icons/mob/clothing/feet_digi.dmi' variation_flag |= STYLE_DIGITIGRADE - var/t_state = shoes.item_state - if (!t_state) - t_state = shoes.icon_state - overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(t_state, SHOES_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE) + overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(SHOES_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE) var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER] if(OFFSET_SHOES in dna.species.offset_features) shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1] @@ -314,7 +306,7 @@ There are several things that need to be remembered: var/t_state = s_store.item_state if(!t_state) t_state = s_store.icon_state - overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.alternate_worn_icon) ? s_store.alternate_worn_icon : 'icons/mob/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER) + overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.mob_overlay_icon) ? s_store.mob_overlay_icon : 'icons/mob/clothing/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER) var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER] if(OFFSET_S_STORE in dna.species.offset_features) s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1] @@ -324,12 +316,24 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_head() - ..() - update_mutant_bodyparts() + remove_overlay(HEAD_LAYER) + + if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated + return + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD] + inv.update_icon() + if(head) + head.screen_loc = ui_head + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += head + update_observer_view(head,1) remove_overlay(HEAD_LAYER) var/obj/item/clothing/head/H = head - var/alt_icon = H.alternate_worn_icon || 'icons/mob/head.dmi' + var/alt_icon = H.mob_overlay_icon || 'icons/mob/clothing/head.dmi' var/muzzled = FALSE var/variation_flag = NONE if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None") @@ -337,10 +341,10 @@ There are several things that need to be remembered: else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None") muzzled = TRUE if(muzzled && H.mutantrace_variation & STYLE_MUZZLE) - alt_icon = 'icons/mob/head_muzzled.dmi' + alt_icon = 'icons/mob/clothing/head_muzzled.dmi' variation_flag |= STYLE_MUZZLE - overlays_standing[HEAD_LAYER] = H.build_worn_icon(H.icon_state, HEAD_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE) + overlays_standing[HEAD_LAYER] = H.build_worn_icon(HEAD_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, H.icon_state, variation_flag, FALSE) var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER] if(OFFSET_HEAD in dna.species.offset_features) @@ -348,6 +352,7 @@ There are several things that need to be remembered: head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2] overlays_standing[HEAD_LAYER] = head_overlay apply_overlay(HEAD_LAYER) + update_mutant_bodyparts() /mob/living/carbon/human/update_inv_belt() remove_overlay(BELT_LAYER) @@ -362,11 +367,7 @@ There are several things that need to be remembered: client.screen += belt update_observer_view(belt) - var/t_state = belt.item_state - if(!t_state) - t_state = belt.icon_state - - overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = 'icons/mob/belt.dmi') + overlays_standing[BELT_LAYER] = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = 'icons/mob/clothing/belt.dmi') var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER] if(OFFSET_BELT in dna.species.offset_features) belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1] @@ -390,7 +391,7 @@ There are several things that need to be remembered: client.screen += wear_suit update_observer_view(wear_suit,1) - var/worn_icon = wear_suit.alternate_worn_icon || 'icons/mob/suit.dmi' + var/worn_icon = wear_suit.mob_overlay_icon || 'icons/mob/clothing/suit.dmi' var/center = FALSE var/dimension_x = 32 var/dimension_y = 32 @@ -405,20 +406,20 @@ There are several things that need to be remembered: variation_flag |= S.mutantrace_variation & T.taur_mode || S.mutantrace_variation & T.alt_taur_mode switch(variation_flag) if(STYLE_HOOF_TAURIC) - worn_icon = 'icons/mob/taur_hooved.dmi' + worn_icon = 'icons/mob/clothing/taur_hooved.dmi' if(STYLE_SNEK_TAURIC) - worn_icon = 'icons/mob/taur_naga.dmi' + worn_icon = 'icons/mob/clothing/taur_naga.dmi' if(STYLE_PAW_TAURIC) - worn_icon = 'icons/mob/taur_canine.dmi' + worn_icon = 'icons/mob/clothing/taur_canine.dmi' if(worn_icon != init_worn_icon) //worn icon sprite was changed, taur offsets will have to be applied. center = T.center dimension_x = T.dimension_x dimension_y = T.dimension_y else if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE) //not a taur, but digitigrade legs. - worn_icon = 'icons/mob/suit_digi.dmi' + worn_icon = 'icons/mob/clothing/suit_digi.dmi' variation_flag |= STYLE_DIGITIGRADE - overlays_standing[SUIT_LAYER] = S.build_worn_icon(wear_suit.icon_state, SUIT_LAYER, worn_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE) + overlays_standing[SUIT_LAYER] = S.build_worn_icon(SUIT_LAYER, worn_icon, FALSE, NO_FEMALE_UNIFORM, wear_suit.icon_state, variation_flag, FALSE) var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER] if(OFFSET_SUIT in dna.species.offset_features) suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1] @@ -456,11 +457,24 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_wear_mask() - ..() + remove_overlay(FACEMASK_LAYER) + + if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated + return + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK] + inv.update_icon() + if(wear_mask) + wear_mask.screen_loc = ui_mask + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + client.screen += wear_mask + update_observer_view(wear_mask,1) var/obj/item/clothing/mask/M = wear_mask remove_overlay(FACEMASK_LAYER) - var/alt_icon = M.alternate_worn_icon || 'icons/mob/mask.dmi' + var/alt_icon = M.mob_overlay_icon || 'icons/mob/clothing/mask.dmi' var/muzzled = FALSE var/variation_flag = NONE if(head && (head.flags_inv & HIDEMASK)) @@ -470,11 +484,10 @@ There are several things that need to be remembered: else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None") muzzled = TRUE if(muzzled && M.mutantrace_variation & STYLE_MUZZLE) - alt_icon = 'icons/mob/mask_muzzled.dmi' + alt_icon = 'icons/mob/clothing/mask_muzzled.dmi' variation_flag |= STYLE_MUZZLE - overlays_standing[FACEMASK_LAYER] = M.build_worn_icon(wear_mask.icon_state, FACEMASK_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, variation_flag, FALSE) - var/mutable_appearance/mask_overlay = overlays_standing[FACEMASK_LAYER] + var/mutable_appearance/mask_overlay = M.build_worn_icon(FACEMASK_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, wear_mask.icon_state, variation_flag, FALSE) if(OFFSET_FACEMASK in dna.species.offset_features) mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1] @@ -512,22 +525,6 @@ There are several things that need to be remembered: //human HUD updates for items in our inventory -//update whether our head item appears on our hud. -/mob/living/carbon/human/update_hud_head(obj/item/I) - I.screen_loc = ui_head - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) - client.screen += I - update_observer_view(I,1) - -//update whether our mask item appears on our hud. -/mob/living/carbon/human/update_hud_wear_mask(obj/item/I) - I.screen_loc = ui_mask - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) - client.screen += I - update_observer_view(I,1) - //update whether our neck item appears on our hud. /mob/living/carbon/human/update_hud_neck(obj/item/I) I.screen_loc = ui_neck @@ -556,27 +553,32 @@ covers: By Remie Richards (yes I'm taking credit because this just removed 90% of the copypaste in update_icons()) -state: A string to use as the state, this is FAR too complex to solve in this proc thanks to shitty old code -so it's specified as an argument instead. +override_state: A string to use as the state, otherwise item_state or icon_state will be used. default_layer: The layer to draw this on if no other layer is specified default_icon_file: The icon file to draw states from if no other icon file is specified -isinhands: If true then alternate_worn_icon is skipped so that default_icon_file is used, +isinhands: If true then mob_overlay_icon is skipped so that default_icon_file is used, in this situation default_icon_file is expected to match either the lefthand_ or righthand_ file var femalueuniform: A value matching a uniform item's fitted var, if this is anything but NO_FEMALE_UNIFORM, we generate/load female uniform sprites matching all previously decided variables +style_flags: mutant race appearance flags, mostly used for worn_overlays() + +use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if mob_overlay_icon is present. */ -/obj/item/proc/build_worn_icon(state = "", default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, style_flags = NONE, use_alt_icon = TRUE) +/obj/item/proc/build_worn_icon(default_layer = 0, default_icon_file = null, isinhands = FALSE, femaleuniform = NO_FEMALE_UNIFORM, override_state, style_flags = NONE, use_mob_overlay_icon = TRUE) + + var/t_state + t_state = override_state || item_state || icon_state //Find a valid icon file from variables+arguments var/file2use - if(!isinhands && alternate_worn_icon && use_alt_icon) - file2use = alternate_worn_icon + if(!isinhands && mob_overlay_icon && use_mob_overlay_icon) + file2use = mob_overlay_icon if(!file2use) file2use = default_icon_file @@ -589,13 +591,13 @@ generate/load female uniform sprites matching all previously decided variables var/mutable_appearance/standing if(femaleuniform) - standing = wear_female_version(state,file2use,layer2use,femaleuniform) + standing = wear_female_version(t_state,file2use,layer2use,femaleuniform) if(!standing) - standing = mutable_appearance(file2use, state, -layer2use) + standing = mutable_appearance(file2use, t_state, -layer2use) //Get the overlays for this item when it's being worn //eg: ammo counters, primed grenade flashes, etc. - var/list/worn_overlays = worn_overlays(isinhands, file2use, style_flags) + var/list/worn_overlays = worn_overlays(isinhands, file2use, t_state, style_flags) if(worn_overlays && worn_overlays.len) standing.overlays.Add(worn_overlays) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 7c6d0e8cdc..8097859aac 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -28,10 +28,8 @@ if(stat != DEAD) handle_brain_damage() - /* BUG_PROBABLE_CAUSE if(stat != DEAD) handle_liver() - */ if(stat == DEAD) stop_sound_channel(CHANNEL_HEARTBEAT) @@ -690,36 +688,17 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER) if((!dna && !liver) || (NOLIVER in dna.species.species_traits)) return - if(liver) - if(liver.damage < liver.maxHealth) - liver.organ_flags |= ORGAN_FAILING - liver_failure() - else + if(!liver || liver.organ_flags & ORGAN_FAILING) liver_failure() -/mob/living/carbon/proc/undergoing_liver_failure() - var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER) - if(liver && liver.failing) - return TRUE - -/mob/living/carbon/proc/return_liver_damage() - var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER) - if(liver) - return liver.damage - -/mob/living/carbon/proc/applyLiverDamage(var/d) - var/obj/item/organ/liver/L = getorganslot(ORGAN_SLOT_LIVER) - if(L) - L.damage += d - /mob/living/carbon/proc/liver_failure() reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE) if(HAS_TRAIT(src, TRAIT_STABLELIVER)) return adjustToxLoss(4, TRUE, TRUE) - if(prob(30)) - to_chat(src, "You feel a stabbing pain in your abdomen!") + if(prob(15)) + to_chat(src, "You feel a stabbing pain in your abdomen!") //////////////// diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm index ff83b00fe1..1e00815f24 100644 --- a/code/modules/mob/living/carbon/monkey/update_icons.dm +++ b/code/modules/mob/living/carbon/monkey/update_icons.dm @@ -45,7 +45,7 @@ remove_overlay(LEGCUFF_LAYER) clear_alert("legcuffed") if(legcuffed) - var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER) + var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/clothing/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER) legcuffs.color = handcuffed.color legcuffs.pixel_y = 8 diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm index e5483e8d73..a431059a89 100644 --- a/code/modules/mob/living/carbon/update_icons.dm +++ b/code/modules/mob/living/carbon/update_icons.dm @@ -42,15 +42,11 @@ observers = null break - var/t_state = I.item_state - if(!t_state) - t_state = I.icon_state - var/icon_file = I.lefthand_file if(get_held_index_of_item(I) % 2 == 0) icon_file = I.righthand_file - hands += I.build_worn_icon(state = t_state, default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) + hands += I.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) overlays_standing[HANDS_LAYER] = hands apply_overlay(HANDS_LAYER) @@ -94,13 +90,13 @@ if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated return - if(client && hud_used && hud_used.inv_slots[SLOT_WEAR_MASK]) + if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK] - inv.update_icon() + inv?.update_icon() if(wear_mask) if(!(head && (head.flags_inv & HIDEMASK))) - overlays_standing[FACEMASK_LAYER] = wear_mask.build_worn_icon(state = wear_mask.icon_state, default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/mask.dmi') + overlays_standing[FACEMASK_LAYER] = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/clothing/mask.dmi', override_state = wear_mask.icon_state) update_hud_wear_mask(wear_mask) apply_overlay(FACEMASK_LAYER) @@ -114,7 +110,7 @@ if(wear_neck) if(!(head && (head.flags_inv & HIDENECK))) - overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(state = wear_neck.icon_state, default_layer = NECK_LAYER, default_icon_file = 'icons/mob/neck.dmi') + overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = 'icons/mob/clothing/neck.dmi', override_state = wear_neck.icon_state) update_hud_neck(wear_neck) apply_overlay(NECK_LAYER) @@ -122,12 +118,12 @@ /mob/living/carbon/update_inv_back() remove_overlay(BACK_LAYER) - if(client && hud_used && hud_used.inv_slots[SLOT_BACK]) + if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BACK] - inv.update_icon() + inv?.update_icon() if(back) - overlays_standing[BACK_LAYER] = back.build_worn_icon(state = back.icon_state, default_layer = BACK_LAYER, default_icon_file = 'icons/mob/back.dmi') + overlays_standing[BACK_LAYER] = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = 'icons/mob/clothing/back.dmi', override_state = back.icon_state) update_hud_back(back) apply_overlay(BACK_LAYER) @@ -138,12 +134,12 @@ if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated return - if(client && hud_used && hud_used.inv_slots[SLOT_BACK]) + if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD] - inv.update_icon() + inv?.update_icon() if(head) - overlays_standing[HEAD_LAYER] = head.build_worn_icon(state = head.icon_state, default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/head.dmi') + overlays_standing[HEAD_LAYER] = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/clothing/head.dmi', override_state = head.icon_state) update_hud_head(head) apply_overlay(HEAD_LAYER) @@ -152,7 +148,7 @@ /mob/living/carbon/update_inv_handcuffed() remove_overlay(HANDCUFF_LAYER) if(handcuffed) - var/mutable_appearance/cuffs = mutable_appearance('icons/mob/restraints.dmi', handcuffed.item_state, -HANDCUFF_LAYER) + var/mutable_appearance/cuffs = mutable_appearance('icons/mob/clothing/restraints.dmi', handcuffed.item_state, -HANDCUFF_LAYER) cuffs.color = handcuffed.color overlays_standing[HANDCUFF_LAYER] = cuffs @@ -162,7 +158,7 @@ remove_overlay(LEGCUFF_LAYER) clear_alert("legcuffed") if(legcuffed) - var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER) + var/mutable_appearance/legcuffs = mutable_appearance('icons/mob/clothing/restraints.dmi', legcuffed.item_state, -LEGCUFF_LAYER) legcuffs.color = legcuffed.color overlays_standing[LEGCUFF_LAYER] = legcuffs @@ -195,15 +191,6 @@ /mob/living/carbon/proc/update_hud_back(obj/item/I) return - - -//Overlays for the worn overlay so you can overlay while you overlay -//eg: ammo counters, primed grenade flashing, etc. -//"icon_file" is used automatically for inhands etc. to make sure it gets the right inhand file -/obj/item/proc/worn_overlays(isinhands = FALSE, icon_file, style_flags = NONE) - . = list() - - /mob/living/carbon/update_body() update_body_parts() diff --git a/code/modules/mob/living/living_block.dm b/code/modules/mob/living/living_block.dm new file mode 100644 index 0000000000..d9e3309e47 --- /dev/null +++ b/code/modules/mob/living/living_block.dm @@ -0,0 +1,98 @@ +// This file has a weird name, but it's for anything related to the checks for shields, blocking, dodging, and similar "stop this attack before it actually impacts the target" as opposed to "defend once it has hit". + +/* +/// Bitflags for check_block() and handle_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS. +/// Attack was not blocked +#define BLOCK_NONE NONE +/// Attack was blocked, do not do damage. THIS FLAG MUST BE THERE FOR DAMAGE/EFFECT PREVENTION! +#define BLOCK_SUCCESS (1<<1) + +/// The below are for "metadata" on "how" the attack was blocked. + +/// Attack was and should be reflected (NOTE: the SHOULD here is important, as it says "the thing blocking isn't handling the reflecting for you so do it yourself"!) +#define BLOCK_SHOULD_REFLECT (1<<2) +/// Attack was manually redirected (including reflected) by any means by the defender. For when YOU are handling the reflection, rather than the thing hitting you. (see sleeping carp) +#define BLOCK_REDIRECTED (1<<3) +/// Attack was blocked by something like a shield. +#define BLOCK_PHYSICAL_EXTERNAL (1<<4) +/// Attack was blocked by something worn on you. +#define BLOCK_PHYSICAL_INTERNAL (1<<5) +/// Attack should pass through. Like SHOULD_REFLECT but for.. well, passing through harmlessly. +#define BLOCK_SHOULD_PASSTHROUGH (1<<6) +/// Attack outright missed because the target dodged. Should usually be combined with SHOULD_PASSTHROUGH or something (see martial arts) +#define BLOCK_TARGET_DODGED (1<<7) +*/ + +///Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields. Wrapper for do_run_block(). The arguments on that means the same as for this. +/mob/living/proc/check_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list) + return do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list) + +/// Runs a block "sequence", effectively checking and then doing effects if necessary. Wrapper for do_run_block(). The arguments on that means the same as for this. +/mob/living/proc/run_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list) + return do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list) + +/** The actual proc for block checks. DO NOT USE THIS DIRECTLY UNLESS YOU HAVE VERY GOOD REASON TO. To reduce copypaste for differences between handling for real attacks and virtual checks. + * Automatically checks all held items for /obj/item/proc/run_block() with the same parameters. + * @params + * real_attack - If this attack is real. This one is quirky; If it's real, run_block is called. If it's not, check_block is called and none of the regular checks happen, and this is effectively only useful + * for populating return_list with blocking metadata. + * object - Whatever /atom is actually hitting us, in essence. For example, projectile if gun, item if melee, structure/whatever if it's a thrown, etc. + * damage - The nominal damage this would do if it was to hit. Obviously doesn't take into effect explosions/magic/similar things.. unless you implement it to raise the value. + * attack_text - The text that this attack should show, in the context of something like "[src] blocks [attack_text]!" + * attack_type - See __DEFINES/combat.dm - Attack types, to distinguish between, for example, someone throwing an item at us vs bashing us with it. + * armour_penetration - 0-100 value of how effectively armor penetrating the attack should be. + * attacker - Set to the mob attacking IF KNOWN. Do not expect this to always be set! + * def_zone - The zone this'll impact. + * return_list - If something wants to grab things from what items/whatever put into list/block_return on obj/item/run_block and the comsig, pass in a list so you can grab anything put in it after block runs. + */ +/mob/living/proc/do_run_block(real_attack = TRUE, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list()) + // Component signal block runs have highest priority.. for now. + . = SEND_SIGNAL(src, COMSIG_LIVING_RUN_BLOCK, real_attack, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list) + if((. & BLOCK_SUCCESS) && !(. & BLOCK_CONTINUE_CHAIN)) + return + var/list/obj/item/tocheck = get_blocking_items() + sortTim(tocheck, /proc/cmp_item_block_priority_asc) + // i don't like this + var/block_chance_modifier = round(damage / -3) + if(real_attack) + for(var/obj/item/I in tocheck) + // i don't like this too + var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example + var/results = I.run_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list) + . |= results + if((results & BLOCK_SUCCESS) && !(results & BLOCK_CONTINUE_CHAIN)) + break + else + for(var/obj/item/I in tocheck) + // i don't like this too + var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example + I.check_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list) + +/// Gets an unsortedlist of objects to run block checks on. +/mob/living/proc/get_blocking_items() + . = list() + for(var/obj/item/I in held_items) + // this is a bad check but i am not removing it until a better catchall is made + if(istype(I, /obj/item/clothing)) + continue + . |= I + +/obj/item + /// The 0% to 100% chance for the default implementation of random block rolls. + var/block_chance = 0 + /// Block priority, higher means we check this higher in the "chain". + var/block_priority = BLOCK_PRIORITY_DEFAULT + +/// Runs block and returns flag for do_run_block to process. +/obj/item/proc/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + SEND_SIGNAL(src, COMSIG_ITEM_RUN_BLOCK, owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return) + if(prob(final_block_chance)) + owner.visible_message("[owner] blocks [attack_text] with [src]!") + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return BLOCK_NONE + +/// Returns block information using list/block_return. Used for check_block() on mobs. +/obj/item/proc/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + SEND_SIGNAL(src, COMSIG_ITEM_CHECK_BLOCK, owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return) + var/existing = block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE] + block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE] = max(existing || 0, final_block_chance) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 9980d2b830..7d220739d5 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -36,48 +36,44 @@ /mob/living/proc/on_hit(obj/item/projectile/P) return BULLET_ACT_HIT -/mob/living/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) - var/block_chance_modifier = round(damage / -3) - for(var/obj/item/I in held_items) - if(!istype(I, /obj/item/clothing)) - var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example - if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type)) - return TRUE - return FALSE - -/mob/living/proc/check_reflect(def_zone) //Reflection checks for anything in your hands, based on the reflection chance of the object(s) - for(var/obj/item/I in held_items) - if(I.IsReflect(def_zone)) - return TRUE - return FALSE - -/mob/living/proc/reflect_bullet_check(obj/item/projectile/P, def_zone) - if(P.is_reflectable && check_reflect(def_zone)) // Checks if you've passed a reflection% check - visible_message("The [P.name] gets reflected by [src]!", \ - "The [P.name] gets reflected by [src]!") - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/curloc = get_turf(src) - // redirect the projectile - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.firer = src - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x - var/new_angle_s = P.Angle + rand(120,240) - while(new_angle_s > 180) // Translate to regular projectile degrees - new_angle_s -= 360 - P.setAngle(new_angle_s) - return TRUE - return FALSE +/mob/living/proc/handle_projectile_attack_redirection(obj/item/projectile/P, redirection_mode, silent = FALSE) + P.ignore_source_check = TRUE + switch(redirection_mode) + if(REDIRECT_METHOD_DEFLECT) + P.setAngle(SIMPLIFY_DEGREES(P.Angle + rand(120, 240))) + if(!silent) + visible_message("[P] gets deflected by [src]!", \ + "[P] gets deflected by [src]!") + if(REDIRECT_METHOD_REFLECT) + P.setAngle(SIMPLIFY_DEGREES(P.Angle + 180)) + if(!silent) + visible_message("[P] gets reflected by [src]!", \ + "[P] gets reflected by [src]!") + if(REDIRECT_METHOD_PASSTHROUGH) + if(!silent) + visible_message("[P] passes through [src]!", \ + "[P] passes through [src]!") + return + if(REDIRECT_METHOD_RETURN_TO_SENDER) + if(!silent) + visible_message("[src] deflects [P] back at their attacker!", \ + "[src] deflects [P] back at their attacker!") + if(P.firer) + P.setAngle(Get_Angle(src, P.firer)) + else + P.setAngle(SIMPLIFY_DEGREES(P.Angle + 180)) + else + CRASH("Invalid rediretion mode [redirection_mode]") /mob/living/bullet_act(obj/item/projectile/P, def_zone) if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself - if(reflect_bullet_check(P, def_zone)) - return BULLET_ACT_FORCE_PIERCE // complete projectile permutation - if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) + var/list/returnlist = list() + var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist) + if(returned & BLOCK_SHOULD_REDIRECT) + handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD]) + if(returned & BLOCK_REDIRECTED) + return BULLET_ACT_FORCE_PIERCE + if(returned & BLOCK_SUCCESS) P.on_hit(src, 100, def_zone) return BULLET_ACT_BLOCK var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null) @@ -108,12 +104,14 @@ return FALSE /mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) + // Throwingdatum can be null if someone had an accident() while slipping with an item in hand. var/obj/item/I var/throwpower = 30 if(isitem(AM)) I = AM throwpower = I.throwforce - if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK)) + var/impacting_zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest + if(run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone) & BLOCK_SUCCESS) hitpush = FALSE skipcatch = TRUE blocked = TRUE @@ -124,10 +122,9 @@ if(I) if(!skipcatch && isturf(I.loc) && catch_item(I)) return TRUE - var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest var/dtype = BRUTE var/volume = I.get_volume_by_throwforce_and_or_w_class() - SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, zone) + SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, impacting_zone) dtype = I.damtype if (I.throwforce > 0) //If the weapon's throwforce is greater than zero... @@ -145,8 +142,8 @@ if(!blocked) visible_message("[src] has been hit by [I].", \ "[src] has been hit by [I].") - var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration) - apply_damage(I.throwforce, dtype, zone, armor) + var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration) + apply_damage(I.throwforce, dtype, impacting_zone, armor) if(I.thrownby) log_combat(I.thrownby, src, "threw and hit", I) else @@ -272,7 +269,7 @@ /mob/living/attack_hand(mob/user) ..() //Ignoring parent return value here. SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user) - if((user != src) && user.a_intent != INTENT_HELP && check_shields(user, 0, user.name, attack_type = UNARMED_ATTACK)) + if((user != src) && user.a_intent != INTENT_HELP && (run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS)) log_combat(user, src, "attempted to touch") visible_message("[user] attempted to touch [src]!") return TRUE @@ -283,7 +280,7 @@ to_chat(user, "You don't want to hurt [src]!") return TRUE var/hulk_verb = pick("smash","pummel") - if(user != src && check_shields(user, 15, "the [hulk_verb]ing")) + if(user != src && (run_block(user, 15, "the [hulk_verb]ing", ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS)) return TRUE ..() return FALSE @@ -298,14 +295,14 @@ M.Feedstop() return // can't attack while eating! - if(HAS_TRAIT(src, TRAIT_PACIFISM)) + if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE var/damage = rand(5, 35) if(M.is_adult) damage = rand(20, 40) - if(check_shields(M, damage, "the [M.name]")) + if(run_block(M, damage, "the [M.name]", ATTACK_TYPE_MELEE, null, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS) return FALSE if (stat != DEAD) @@ -324,7 +321,7 @@ if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE - if(check_shields(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", MELEE_ATTACK, M.armour_penetration)) + if(run_block(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", ATTACK_TYPE_MELEE, M.armour_penetration, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS) return FALSE if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) @@ -334,17 +331,15 @@ log_combat(M, src, "attacked") return TRUE - /mob/living/attack_paw(mob/living/carbon/monkey/M) if (M.a_intent == INTENT_HARM) if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE - if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH)) to_chat(M, "You can't bite with your mouth covered!") return FALSE - if(check_shields(M, 0, "the [M.name]")) + if(run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS) return FALSE M.do_attack_animation(src, ATTACK_EFFECT_BITE) if (prob(75)) @@ -368,7 +363,7 @@ if(HAS_TRAIT(L, TRAIT_PACIFISM)) to_chat(L, "You don't want to hurt anyone!") return FALSE - if(L != src && check_shields(L, rand(1, 3), "the [L.name]")) + if(L != src && (run_block(L, rand(1, 3), "the [L.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, L, check_zone(L.zone_selected)) & BLOCK_SUCCESS)) return FALSE L.do_attack_animation(src) if(prob(90)) @@ -382,7 +377,7 @@ "[L.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE) /mob/living/attack_alien(mob/living/carbon/alien/humanoid/M) - if((M != src) && M.a_intent != INTENT_HELP && check_shields(M, 0, "the [M.name]")) + if((M != src) && M.a_intent != INTENT_HELP && (run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)) visible_message("[M] attempted to touch [src]!") return FALSE switch(M.a_intent) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 35b49cce8e..f90b285d2d 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -354,7 +354,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(cultslurring) message = cultslur(message) - + if(clockcultslurring) message = CLOCK_CULT_SLUR(message) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 6b4a6645e6..d178af9fb0 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -695,7 +695,7 @@ holo_icon = client.prefs.get_filtered_holoform(HOLOFORM_FILTER_AI) else holo_icon = getHologramIcon(icon('icons/mob/ai.dmi', "female")) - else if("xeno queen") + if("xeno queen") holo_icon = getHologramIcon(icon(icon_list[input],"alienq")) else holo_icon = getHologramIcon(icon(icon_list[input], input)) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 810dd778de..892cc3f13b 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -283,9 +283,7 @@ T.visible_message("A port on [src] opens to reveal [cable], which promptly falls to the floor.", "You hear the soft click of something light and hard falling to the ground.") if("loudness") if(subscreen == 1) // Open Instrument - internal_instrument.interact(src) - if(subscreen == 2) // Change Instrument type - internal_instrument.selectInstrument() + internal_instrument.ui_interact(src) //updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window paiInterface() // So we'll just call the update directly rather than doing some default checks diff --git a/code/modules/mob/living/silicon/robot/update_icons.dm b/code/modules/mob/living/silicon/robot/update_icons.dm index 8d40e35706..72ad21c51e 100644 --- a/code/modules/mob/living/silicon/robot/update_icons.dm +++ b/code/modules/mob/living/silicon/robot/update_icons.dm @@ -41,7 +41,7 @@ else add_overlay("ov-opencover -c") if(hat) - var/mutable_appearance/head_overlay = hat.build_worn_icon(state = hat.icon_state, default_layer = 20, default_icon_file = 'icons/mob/head.dmi') + var/mutable_appearance/head_overlay = hat.build_worn_icon(default_layer = 20, default_icon_file = 'icons/mob/clothing/head.dmi', override_state = hat.icon_state) head_overlay.pixel_y += hat_offset add_overlay(head_overlay) update_fire() diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index a93bc8662e..9b3db8af62 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -112,11 +112,15 @@ /mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone) if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself - if(reflect_bullet_check(P, def_zone)) - return -1 // complete projectile permutation - if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) + var/list/returnlist = list() + var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist) + if(returned & BLOCK_SHOULD_REDIRECT) + handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD]) + if(returned & BLOCK_REDIRECTED) + return BULLET_ACT_FORCE_PIERCE + if(returned & BLOCK_SUCCESS) P.on_hit(src, 100, def_zone) - return 2 + return BULLET_ACT_BLOCK if((P.damage_type == BRUTE || P.damage_type == BURN)) adjustBruteLoss(P.damage) if(prob(P.damage*1.5)) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 75364b2845..a8e0d2c1c8 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -445,7 +445,6 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r return scan_result else return FALSE //The current element failed assessment, move on to the next. - return /mob/living/simple_animal/bot/proc/check_bot(targ) var/turf/T = get_turf(targ) diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index d3fb65c585..ab7c632214 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -523,9 +523,6 @@ soft_reset() return - reagent_id = null - return - /mob/living/simple_animal/bot/medbot/proc/check_overdose(mob/living/carbon/patient,reagent_id,injection_amount) var/datum/reagent/R = GLOB.chemical_reagents_list[reagent_id] if(!R.overdose_threshold) //Some chems do not have an OD threshold diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 5754f8c3b2..d199bc2ead 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -235,10 +235,11 @@ Auto Patrol: []"}, playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2) C.visible_message("[src] is trying to put zipties on [C]!",\ "[src] is trying to put zipties on you!") - addtimer(CALLBACK(src, .proc/attempt_handcuff, C), 60) + if(do_after(src, 60, FALSE, C)) + attempt_handcuff(C) /mob/living/simple_animal/bot/secbot/proc/attempt_handcuff(mob/living/carbon/C) - if( !on || !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing. + if (!on) return if(!C.handcuffed) C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index a6366c03fe..674cc722d8 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -392,6 +392,9 @@ var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult) if(!C) return + if(!C.cult_team) + to_chat(the_construct, "You are alone, and have no team.") + return var/datum/objective/eldergod/summon_objective = locate() in C.cult_team.objectives if(summon_objective.check_completion()) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index 0d344f1a9b..2a84152088 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -105,7 +105,7 @@ . = ..() if(can_be_held) //icon/item state is defined in mob_holder/drone_worn_icon() - AddElement(/datum/element/mob_holder, null, 'icons/mob/head.dmi', 'icons/mob/inhands/clothing_righthand.dmi', 'icons/mob/inhands/clothing_lefthand.dmi', ITEM_SLOT_HEAD, /datum/element/mob_holder.proc/drone_worn_icon) + AddElement(/datum/element/mob_holder, null, 'icons/mob/clothing/head.dmi', 'icons/mob/inhands/clothing_righthand.dmi', 'icons/mob/inhands/clothing_lefthand.dmi', ITEM_SLOT_HEAD, /datum/element/mob_holder.proc/drone_worn_icon) /mob/living/simple_animal/drone/med_hud_set_health() var/image/holder = hud_list[DIAG_HUD] diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm index 0f97a4c496..54184310a8 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm @@ -92,8 +92,8 @@ return if(hack) if(hacked) - return Stun(40) + return if(clockwork) to_chat(src, "ERROR: LAW OVERRIDE DETECTED") to_chat(src, "From now on, these are your laws:") diff --git a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm index 408edc7110..815c2bc0db 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm @@ -28,12 +28,7 @@ var/y_shift = getItemPixelShiftY() if(r_hand) - - var/r_state = r_hand.item_state - if(!r_state) - r_state = r_hand.icon_state - - var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(state = r_state, default_layer = DRONE_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) + var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(default_layer = DRONE_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) if(y_shift) r_hand_overlay.pixel_y += y_shift @@ -46,12 +41,7 @@ client.screen |= r_hand if(l_hand) - - var/l_state = l_hand.item_state - if(!l_state) - l_state = l_hand.icon_state - - var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(state = l_state, default_layer = DRONE_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) + var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(default_layer = DRONE_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) if(y_shift) l_hand_overlay.pixel_y += y_shift @@ -82,10 +72,10 @@ if(client && hud_used && hud_used.hud_shown) head.screen_loc = ui_drone_head client.screen += head - var/used_head_icon = 'icons/mob/head.dmi' + var/used_head_icon = 'icons/mob/clothing/head.dmi' if(istype(head, /obj/item/clothing/mask)) - used_head_icon = 'icons/mob/mask.dmi' - var/mutable_appearance/head_overlay = head.build_worn_icon(state = head.icon_state, default_layer = DRONE_HEAD_LAYER, default_icon_file = used_head_icon) + used_head_icon = 'icons/mob/clothing/mask.dmi' + var/mutable_appearance/head_overlay = head.build_worn_icon(default_layer = DRONE_HEAD_LAYER, default_icon_file = used_head_icon, override_state = head.icon_state) head_overlay.pixel_y -= 15 drone_overlays[DRONE_HEAD_LAYER] = head_overlay diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 41c56169d0..af342118a2 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -313,11 +313,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians var/obj/item/r_hand = get_item_for_held_index(2) if(r_hand) - var/r_state = r_hand.item_state - if(!r_state) - r_state = r_hand.icon_state - - hands_overlays += r_hand.build_worn_icon(state = r_state, default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) + hands_overlays += r_hand.build_worn_icon(default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) r_hand.layer = ABOVE_HUD_LAYER @@ -326,11 +322,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians client.screen |= r_hand if(l_hand) - var/l_state = l_hand.item_state - if(!l_state) - l_state = l_hand.icon_state - - hands_overlays += l_hand.build_worn_icon(state = l_state, default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) + hands_overlays += l_hand.build_worn_icon(default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) l_hand.layer = ABOVE_HUD_LAYER diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm index 237ab9d919..1ece6dde37 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm @@ -54,7 +54,7 @@ var/blocked = FALSE if(hasmatchingsummoner(hit_atom)) //if the summoner matches don't hurt them blocked = TRUE - if(L.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK)) + if(L.run_block(src, 90, "[name]", ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS) blocked = TRUE if(!blocked) L.drop_all_held_items() diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 3c3612f434..439bedf3cc 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -400,10 +400,9 @@ action.button_icon_state = "wrap_[active]" action.UpdateButtonIcon() -/obj/effect/proc_holder/wrap/Click() - if(!istype(usr, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) +/obj/effect/proc_holder/wrap/Trigger(mob/living/simple_animal/hostile/poison/giant_spider/nurse/user) + if(!istype(user)) return TRUE - var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/user = usr activate(user) return TRUE @@ -444,7 +443,7 @@ check_flags = AB_CHECK_CONSCIOUS button_icon_state = "lay_eggs" -/datum/action/innate/spider/lay_eggs/IsAvailable() +/datum/action/innate/spider/lay_eggs/IsAvailable(silent = FALSE) if(..()) if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) return 0 @@ -508,7 +507,7 @@ desc = "Send a command to all living spiders." button_icon_state = "command" -/datum/action/innate/spider/comm/IsAvailable() +/datum/action/innate/spider/comm/IsAvailable(silent = FALSE) if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife)) return FALSE return TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/visuals_icons.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/visuals_icons.dm index b3e0f3b658..9d451748b0 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/visuals_icons.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/visuals_icons.dm @@ -33,14 +33,12 @@ var/obj/item/r_hand = get_item_for_held_index(2) if(r_hand) - var/r_state = r_hand.item_state ? r_hand.item_state : r_hand.icon_state - var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(state = r_state, default_layer = GORILLA_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) + var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(default_layer = GORILLA_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE) r_hand_overlay.pixel_y -= 1 hands_overlays += r_hand_overlay if(l_hand) - var/l_state = l_hand.item_state ? l_hand.item_state : l_hand.icon_state - var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(state = l_state, default_layer = GORILLA_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) + var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(default_layer = GORILLA_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE) l_hand_overlay.pixel_y -= 1 hands_overlays += l_hand_overlay diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 6ec8e0cfd2..138d7f155e 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -11,6 +11,7 @@ speed = 0 maxHealth = 250 health = 250 + blood_volume = 0 gender = NEUTER mob_biotypes = NONE 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 95fafbabfd..884e3bb989 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 @@ -40,27 +40,27 @@ deathsound = 'sound/magic/demon_dies.ogg' deathmessage = "begins to shudder as it becomes transparent..." loot_drop = /obj/item/clothing/neck/cloak/herald_cloak - + can_talk = 1 attack_action_types = list(/datum/action/innate/elite_attack/herald_trishot, /datum/action/innate/elite_attack/herald_directionalshot, /datum/action/innate/elite_attack/herald_teleshot, /datum/action/innate/elite_attack/herald_mirror) - + var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/my_mirror = null var/is_mirror = FALSE - + /mob/living/simple_animal/hostile/asteroid/elite/herald/death() . = ..() if(!is_mirror) addtimer(CALLBACK(src, .proc/become_ghost), 8) if(my_mirror != null) qdel(my_mirror) - + /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost() icon_state = "herald_ghost" - + /mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) . = ..() if(.) @@ -71,25 +71,25 @@ button_icon_state = "herald_trishot" chosen_message = "You are now firing three shots in your chosen direction." chosen_attack_num = HERALD_TRISHOT - + /datum/action/innate/elite_attack/herald_directionalshot name = "Circular Shot" button_icon_state = "herald_directionalshot" chosen_message = "You are firing projectiles in all directions." chosen_attack_num = HERALD_DIRECTIONALSHOT - + /datum/action/innate/elite_attack/herald_teleshot name = "Teleport Shot" button_icon_state = "herald_teleshot" chosen_message = "You will now fire a shot which teleports you where it lands." chosen_attack_num = HERALD_TELESHOT - + /datum/action/innate/elite_attack/herald_mirror name = "Summon Mirror" button_icon_state = "herald_mirror" chosen_message = "You will spawn a mirror which duplicates your attacks." chosen_attack_num = HERALD_MIRROR - + /mob/living/simple_animal/hostile/asteroid/elite/herald/OpenFire() if(client) switch(chosen_attack) @@ -124,7 +124,7 @@ my_mirror.herald_teleshot(target) if(HERALD_MIRROR) herald_mirror() - + /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/shoot_projectile(turf/marker, set_angle, var/is_teleshot) var/turf/startloc = get_turf(src) var/obj/item/projectile/herald/H = null @@ -137,7 +137,7 @@ if(target) H.original = target H.fire(set_angle) - + /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_trishot(target) ranged_cooldown = world.time + 30 playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) @@ -151,17 +151,17 @@ addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 10) addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 12) addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 14) - + /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_circleshot() var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315) for(var/i in directional_shot_angles) shoot_projectile(get_turf(src), i, FALSE) - + /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/unenrage() if(stat == DEAD || is_mirror) return icon_state = "herald" - + /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_directionalshot() ranged_cooldown = world.time + 50 if(!is_mirror) @@ -172,14 +172,14 @@ playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) addtimer(CALLBACK(src, .proc/herald_circleshot), 15) addtimer(CALLBACK(src, .proc/unenrage), 20) - + /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_teleshot(target) ranged_cooldown = world.time + 30 playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) var/target_turf = get_turf(target) var/angle_to_target = Get_Angle(src, target_turf) shoot_projectile(target_turf, angle_to_target, TRUE) - + /mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_mirror() ranged_cooldown = world.time + 40 playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) @@ -190,7 +190,7 @@ my_mirror = new_mirror my_mirror.my_master = src my_mirror.faction = faction.Copy() - + /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror name = "herald's mirror" desc = "This fiendish work of magic copies the herald's attacks. Seems logical to smash it." @@ -203,16 +203,16 @@ del_on_death = TRUE is_mirror = TRUE var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null - + /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Initialize() ..() toggle_ai(AI_OFF) - + /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Destroy() if(my_master != null) my_master.my_mirror = null . = ..() - + /obj/item/projectile/herald name ="death bolt" icon_state= "chronobolt" @@ -222,7 +222,7 @@ eyeblur = 0 damage_type = BRUTE pass_flags = PASSTABLE - + /obj/item/projectile/herald/teleshot name ="golden bolt" damage = 0 @@ -239,11 +239,11 @@ var/mob/living/F = firer if(F != null && istype(F, /mob/living/simple_animal/hostile/asteroid/elite) && F.faction_check_mob(L)) L.heal_overall_damage(damage) - + /obj/item/projectile/herald/teleshot/on_hit(atom/target, blocked = FALSE) . = ..() firer.forceMove(get_turf(src)) - + //Herald's loot: Cloak of the Prophet /obj/item/clothing/neck/cloak/herald_cloak @@ -252,13 +252,13 @@ icon = 'icons/obj/lavaland/elite_trophies.dmi' icon_state = "herald_cloak" body_parts_covered = CHEST|GROIN|ARMS - hit_reaction_chance = 10 - + var/hit_reaction_chance = 10 + /obj/item/clothing/neck/cloak/herald_cloak/proc/reactionshot(mob/living/carbon/owner) var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315) for(var/i in directional_shot_angles) shoot_projectile(get_turf(owner), i, owner) - + /obj/item/clothing/neck/cloak/herald_cloak/proc/shoot_projectile(turf/marker, set_angle, mob/living/carbon/owner) var/turf/startloc = get_turf(owner) var/obj/item/projectile/herald/H = null @@ -266,12 +266,11 @@ H.preparePixelProjectile(marker, startloc) H.firer = owner H.fire(set_angle) - -/obj/item/clothing/neck/cloak/herald_cloak/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + +/obj/item/clothing/neck/cloak/herald_cloak/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) . = ..() if(rand(1,100) > hit_reaction_chance) return owner.visible_message("[owner]'s [src] emits a loud noise as [owner] is struck!") - var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315) playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) addtimer(CALLBACK(src, .proc/reactionshot, owner), 10) 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 d83a38ae24..c9011c5f5f 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 @@ -12,7 +12,7 @@ * - Charges at the target after a telegraph, throwing them across the arena should it connect. * - Legionnaire's head detaches, attacking as it's own entity. Has abilities of it's own later into the fight. Once dead, regenerates after a brief period. If the skill is used while the head is off, it will be killed. * - Leaves a pile of bones at your location. Upon using this skill again, you'll swap locations with the bone pile. - * - Spews a cloud of smoke from it's maw, wherever said maw is. + * - Spews a cloud of smoke from it's maw, wherever said maw is. * A unique fight incorporating the head mechanic of legion into a whole new beast. Combatants will need to make sure the tag-team of head and body don't lure them into a deadly trap. */ @@ -45,35 +45,35 @@ /datum/action/innate/elite_attack/head_detach, /datum/action/innate/elite_attack/bonfire_teleport, /datum/action/innate/elite_attack/spew_smoke) - + var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/myhead = null var/obj/structure/legionnaire_bonfire/mypile = null var/has_head = TRUE - + /datum/action/innate/elite_attack/legionnaire_charge name = "Legionnaire Charge" button_icon_state = "legionnaire_charge" chosen_message = "You will attempt to grab your opponent and throw them." chosen_attack_num = LEGIONNAIRE_CHARGE - + /datum/action/innate/elite_attack/head_detach name = "Release Head" button_icon_state = "head_detach" chosen_message = "You will now detach your head or kill it if it is already released." chosen_attack_num = HEAD_DETACH - + /datum/action/innate/elite_attack/bonfire_teleport name = "Bonfire Teleport" button_icon_state = "bonfire_teleport" chosen_message = "You will leave a bonfire. Second use will let you swap positions with it indefintiely. Using this move on the same tile as your active bonfire removes it." chosen_attack_num = BONFIRE_TELEPORT - + /datum/action/innate/elite_attack/spew_smoke name = "Spew Smoke" button_icon_state = "spew_smoke" chosen_message = "Your head will spew smoke in an area, wherever it may be." chosen_attack_num = SPEW_SMOKE - + /mob/living/simple_animal/hostile/asteroid/elite/legionnaire/OpenFire() if(client) switch(chosen_attack) @@ -96,7 +96,7 @@ bonfire_teleport() if(SPEW_SMOKE) spew_smoke() - + /mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge(target) ranged_cooldown = world.time + 50 var/dir_to_target = get_dir(get_turf(src), get_turf(target)) @@ -107,7 +107,7 @@ playsound(src,'sound/magic/demon_attack1.ogg', 200, 1) visible_message("[src] prepares to charge!") addtimer(CALLBACK(src, .proc/legionnaire_charge_2, dir_to_target, 0), 5) - + /mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge_2(var/move_dir, var/times_ran) if(times_ran >= 4) return @@ -136,7 +136,7 @@ L.Stun(20) //substituting this for the Paralyze from the line above, because we don't have tg paralysis stuff L.adjustBruteLoss(50) addtimer(CALLBACK(src, .proc/legionnaire_charge_2, move_dir, (times_ran + 1)), 2) - + /mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/head_detach(target) ranged_cooldown = world.time + 10 if(myhead != null) @@ -160,11 +160,11 @@ else if(health < maxHealth * 0.5) myhead.melee_damage_lower = 20 myhead.melee_damage_upper = 20 - + /mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/onHeadDeath() myhead = null addtimer(CALLBACK(src, .proc/regain_head), 50) - + /mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/regain_head() has_head = TRUE if(stat == DEAD) @@ -196,7 +196,7 @@ forceMove(pileturf) visible_message("[src] forms from the bonfire!") mypile.forceMove(legionturf) - + /mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/spew_smoke() ranged_cooldown = world.time + 60 var/turf/T = null @@ -213,7 +213,7 @@ var/datum/effect_system/smoke_spread/smoke = new smoke.set_up(2, T) smoke.start() - + //The legionnaire's head. Basically the same as any legion head, but we have to tell our creator when we die so they can generate another head. /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead name = "legionnaire head" @@ -239,12 +239,12 @@ faction = list() ranged = FALSE var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/body = null - + /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/death() . = ..() if(body) body.onHeadDeath() - + //The legionnaire's bonfire, which can be swapped positions with. Also sets flammable living beings on fire when they walk over it. /obj/structure/legionnaire_bonfire name = "bone pile" @@ -258,20 +258,20 @@ light_range = 4 light_color = LIGHT_COLOR_RED var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/myowner = null - - + + /obj/structure/legionnaire_bonfire/Entered(atom/movable/mover, turf/target) if(isliving(mover)) var/mob/living/L = mover L.adjust_fire_stacks(3) L.IgniteMob() . = ..() - + /obj/structure/legionnaire_bonfire/Destroy() if(myowner != null) myowner.mypile = null . = ..() - + //The visual effect which appears in front of legionnaire when he goes to charge. /obj/effect/temp_visual/dragon_swoop/legionnaire duration = 10 @@ -280,7 +280,7 @@ /obj/effect/temp_visual/dragon_swoop/legionnaire/Initialize() . = ..() transform *= 0.33 - + // Legionnaire's loot: Legionnaire Spine /obj/item/crusher_trophy/legionnaire_spine diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm index bf80ab9ff4..4f8e271d6f 100644 --- a/code/modules/mob/living/simple_animal/slime/powers.dm +++ b/code/modules/mob/living/simple_animal/slime/powers.dm @@ -11,7 +11,7 @@ background_icon_state = "bg_alien" var/needs_growth = NO_GROWTH_NEEDED -/datum/action/innate/slime/IsAvailable() +/datum/action/innate/slime/IsAvailable(silent = FALSE) if(..()) var/mob/living/simple_animal/slime/S = owner if(needs_growth == GROWTH_NEEDED) diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 5cdeaecd37..1375d88948 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -7,6 +7,8 @@ /mob/living/proc/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg) if(!iscarbon(src)) return Paralyze(amount, updating, ignore_canknockdown) + if(!ignore_canknockdown && !(status_flags & CANKNOCKDOWN)) + return FALSE if(istype(buckled, /obj/vehicle/ridden)) buckled.unbuckle_mob(src) var/drop_items = amount > 80 //80 is cutoff for old item dropping behavior diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index e5aaa016bd..536eacca7d 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -1,4 +1,5 @@ /mob/Logout() + SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGOUT, client) log_message("[key_name(src)] is no longer owning mob [src]([src.type])", LOG_OWNERSHIP) SStgui.on_logout(src) unset_machine() diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 4d9d15ae5c..ffc0970bdf 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -353,7 +353,7 @@ if(m_intent == MOVE_INTENT_RUN) m_intent = MOVE_INTENT_WALK else - if (HAS_TRAIT(src,TRAIT_NORUNNING)) // FULPSTATION 7/10/19 So you can't run during fortitude. + if (HAS_TRAIT(src,TRAIT_NORUNNING)) to_chat(src, "You find yourself unable to run.") return FALSE m_intent = MOVE_INTENT_RUN diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm index 295ecc66c0..81e2cb95e6 100644 --- a/code/modules/modular_computers/computers/item/processor.dm +++ b/code/modules/modular_computers/computers/item/processor.dm @@ -20,7 +20,6 @@ . = ..() if(!loc || !istype(loc, /obj/machinery/modular_computer)) CRASH("Inapropriate type passed to obj/item/modular_computer/processor/New()! Aborting.") - return // Obtain reference to machinery computer all_components = list() idle_threads = list() @@ -69,4 +68,4 @@ if(MC_SDD) machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_disk if(MC_AI) - machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_card \ No newline at end of file + machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_card diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm index 55f7c19cd7..e03427cc9c 100644 --- a/code/modules/modular_computers/hardware/battery_module.dm +++ b/code/modules/modular_computers/hardware/battery_module.dm @@ -54,7 +54,6 @@ holder.shutdown_computer() return TRUE - return FALSE @@ -95,4 +94,4 @@ name = "nano battery" desc = "A tiny power cell, commonly seen in low-end portable microcomputers." icon_state = "cell_micro" - maxcharge = 300 \ No newline at end of file + maxcharge = 300 diff --git a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm index c723f2cd7b..c0ee68cdee 100644 --- a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm +++ b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm @@ -106,7 +106,7 @@ It is possible to destroy the net by the occupant or someone else. playsound(affecting, 'sound/effects/sparks2.ogg', 50, 1) new /obj/effect/temp_visual/dir_setting/ninja/phase(affecting.drop_location(), affecting.dir) -/obj/attack_alien(mob/living/carbon/alien/humanoid/user) +/obj/structure/energy_net/attack_alien(mob/living/carbon/alien/humanoid/user) if(attack_generic(user, 15, BRUTE, "melee", 0)) //Aliens normally deal 60 damage to structures. They'd one-shot nets without this. playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) diff --git a/code/modules/paperwork/contract.dm b/code/modules/paperwork/contract.dm index 2c02903d3e..f46d4bf029 100644 --- a/code/modules/paperwork/contract.dm +++ b/code/modules/paperwork/contract.dm @@ -8,7 +8,6 @@ item_flags = NOBLUDGEON /obj/item/paper/contract/ComponentInitialize() - return . = ..() AddElement(/datum/element/update_icon_blocker) diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm index 2beb9296b3..241dde13a8 100644 --- a/code/modules/paperwork/stamps.dm +++ b/code/modules/paperwork/stamps.dm @@ -9,7 +9,6 @@ throw_speed = 3 throw_range = 7 custom_materials = list(/datum/material/iron=60) - item_color = "cargo" pressure_resistance = 2 attack_verb = list("stamped") @@ -20,52 +19,52 @@ /obj/item/stamp/qm name = "quartermaster's rubber stamp" icon_state = "stamp-qm" - item_color = "qm" + dye_color = DYE_QM /obj/item/stamp/law name = "law office's rubber stamp" icon_state = "stamp-law" - item_color = "cargo" + dye_color = DYE_LAW /obj/item/stamp/captain name = "captain's rubber stamp" icon_state = "stamp-cap" - item_color = "captain" + dye_color = DYE_CAPTAIN /obj/item/stamp/hop name = "head of personnel's rubber stamp" icon_state = "stamp-hop" - item_color = "hop" + dye_color = DYE_HOP /obj/item/stamp/hos name = "head of security's rubber stamp" icon_state = "stamp-hos" - item_color = "hosred" + dye_color = DYE_HOS /obj/item/stamp/ce name = "chief engineer's rubber stamp" icon_state = "stamp-ce" - item_color = "chief" + dye_color = DYE_CE /obj/item/stamp/rd name = "research director's rubber stamp" icon_state = "stamp-rd" - item_color = "director" + dye_color = DYE_RD /obj/item/stamp/cmo name = "chief medical officer's rubber stamp" icon_state = "stamp-cmo" - item_color = "cmo" + dye_color = DYE_CMO /obj/item/stamp/denied name = "\improper DENIED rubber stamp" icon_state = "stamp-deny" - item_color = "redcoat" + dye_color = DYE_REDCOAT /obj/item/stamp/clown name = "clown's rubber stamp" icon_state = "stamp-clown" - item_color = "clown" + dye_color = DYE_CLOWN /obj/item/stamp/attack_paw(mob/user) return attack_hand(user) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 93f82991fd..49848824e4 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -556,23 +556,18 @@ By design, d1 is the smallest direction and d2 is the highest new_cable.update_icon() /obj/item/stack/cable_coil/attack_self(mob/user) - if(!check_cable_amount(user)) + if(!use(15)) + to_chat(user, "You dont have enough cable coil to make restraints out of them") return to_chat(user, "You start making some cable restraints.") - if(do_after(user, 30, TRUE, user) && check_cable_amount(user)) - amount -= 15 - var/obj/item/restraints/handcuffs/cable/result = new(get_turf(user)) - user.put_in_hands(result) - result.color = color - to_chat(user, "You make some restraints out of cable") + if(!do_after(user, 30, TRUE, user, TRUE)) + to_chat(user, "You fail to make cable restraints, you need to stand still while doing so.") + give(15) return - to_chat(user, "You fail to make cable restraints, you need to stand still while doing so.") - -/obj/item/stack/cable_coil/proc/check_cable_amount(user) - if(amount < 15) //We dont care about cyborgs here, so we dont use get_amount() - to_chat(user, "You dont have enough cable coil to make restraints out of them") - return FALSE - return TRUE + var/obj/item/restraints/handcuffs/cable/result = new(get_turf(user)) + user.put_in_hands(result) + result.color = color + to_chat(user, "You make some restraints out of cable") //add cables to the stack /obj/item/stack/cable_coil/proc/give(extra) @@ -854,4 +849,4 @@ By design, d1 is the smallest direction and d2 is the highest . = ..() var/list/cable_colors = GLOB.cable_colors color = pick(cable_colors) - \ No newline at end of file + diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 835055ea48..36005232f3 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -257,6 +257,7 @@ /obj/machinery/light/small/built icon_state = "bulb-empty" + start_with_cell = FALSE /obj/machinery/light/small/built/Initialize() . = ..() diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index a073997b9d..c471047682 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -51,7 +51,8 @@ for(var/datum/antagonist/cult/C in GLOB.antagonists) if(!C.owner) continue - all_cults |= C.cult_team + if(C.cult_team) + all_cults |= C.cult_team for(var/datum/team/cult/T in all_cults) deltimer(T.blood_target_reset_timer) T.blood_target = src diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 6c5f97557d..73ea3ccd59 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -185,7 +185,7 @@ if(sunfrac <= 0) return - var/sgen = SOLAR_GEN_RATE * sunfrac + var/sgen = SOLAR_GEN_RATE * sunfrac * efficiency add_avail(sgen) if(control) control.gen += sgen @@ -253,6 +253,7 @@ var/obj/item/stack/sheet/G = S.change_stack(null, 2) if(G) glass_type = G + G.moveToNullspace() playsound(src.loc, 'sound/machines/click.ogg', 50, 1) user.visible_message("[user] places the glass on the solar assembly.", "You place the glass on the solar assembly.") if(tracker) diff --git a/code/modules/projectiles/ammunition/ballistic/pistol.dm b/code/modules/projectiles/ammunition/ballistic/pistol.dm index 13a284e970..58a5bfb497 100644 --- a/code/modules/projectiles/ammunition/ballistic/pistol.dm +++ b/code/modules/projectiles/ammunition/ballistic/pistol.dm @@ -21,6 +21,11 @@ desc = "A 10mm incendiary bullet casing." projectile_type = /obj/item/projectile/bullet/incendiary/c10mm +/obj/item/ammo_casing/c10mm/soporific + name = ".10mm soporific bullet casing" + desc = "A 10mm soporific bullet casing." + projectile_type = /obj/item/projectile/bullet/c10mm/soporific + // 9mm (Stechkin APS) /obj/item/ammo_casing/c9mm diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm index fbbca99ec2..81ae026138 100644 --- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm +++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm @@ -52,6 +52,29 @@ ammo_type = /obj/item/ammo_casing/c10mm max_ammo = 20 +/obj/item/ammo_box/c10mm/fire + name = "ammo box (10mm Incendiary)" + icon_state = "10mmbox" + ammo_type = /obj/item/ammo_casing/c10mm/fire + max_ammo = 20 + +/obj/item/ammo_box/c10mm/hp + name = "ammo box (10mm Hollow Point)" + icon_state = "10mmbox" + ammo_type = /obj/item/ammo_casing/c10mm/hp + max_ammo = 20 + +/obj/item/ammo_box/c10mm/ap + name = "ammo box (10mm Armour Piercing)" + icon_state = "10mmbox" + ammo_type = /obj/item/ammo_casing/c10mm/ap + max_ammo = 20 + +/obj/item/ammo_box/c10mm/soporific + name = "ammo box (10mm Soporific)" + ammo_type = /obj/item/ammo_casing/c10mm/soporific + max_ammo = 20 + /obj/item/ammo_box/c45 name = "ammo box (.45)" icon_state = "45box" diff --git a/code/modules/projectiles/boxes_magazines/external/pistol.dm b/code/modules/projectiles/boxes_magazines/external/pistol.dm index dbde572db1..63b0483875 100644 --- a/code/modules/projectiles/boxes_magazines/external/pistol.dm +++ b/code/modules/projectiles/boxes_magazines/external/pistol.dm @@ -25,6 +25,13 @@ desc= "A gun magazine. Loaded with rounds which penetrate armour, but are less effective against normal targets." ammo_type = /obj/item/ammo_casing/c10mm/ap +/obj/item/ammo_box/magazine/m10mm/soporific + name = "pistol magazine (10mm soporific)" + icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' + icon_state = "9x19pS" + desc = "A gun magazine. Loaded with rounds which inject the target with a variety of illegal substances to induce sleep in the target." + ammo_type = /obj/item/ammo_casing/c10mm/soporific + /obj/item/ammo_box/magazine/m45 name = "handgun magazine (.45)" icon_state = "45-8" diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index dd40648191..9c1a23174e 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -513,7 +513,7 @@ icon_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "sniper_zoom" -/datum/action/item_action/toggle_scope_zoom/IsAvailable() +/datum/action/item_action/toggle_scope_zoom/IsAvailable(silent = FALSE) . = ..() if(!.) var/obj/item/gun/G = target diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index 68f212ba30..e15c49b891 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -21,6 +21,38 @@ var/obj/item/suppressor/S = new(src) install_suppressor(S) +//(reskinnable stetchkin) +/obj/item/gun/ballistic/automatic/pistol/modular + name = "modular pistol" + desc = "A small, easily concealable 10mm handgun. Has a threaded barrel for suppressors." + icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' + icon_state = "cde" + can_unsuppress = TRUE + obj_flags = UNIQUE_RENAME + unique_reskin = list("Default" = "cde", + "N-99" = "n99", + "Stealth" = "stealthpistol", + "HKVP-78" = "vp78", + "Luger" = "p08b", + "Mk.58" = "secguncomp", + "PX4 Storm" = "px4" + ) + +/obj/item/gun/ballistic/automatic/pistol/modular/update_icon() + ..() + if(current_skin) + icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" + else + icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" + if(magazine && suppressed) + cut_overlays() + add_overlay("[unique_reskin[current_skin]]-magazine-sup") //Yes, this means the default iconstate can't have a magazine overlay + else if (magazine) + cut_overlays() + add_overlay("[unique_reskin[current_skin]]-magazine") + else + cut_overlays() + /obj/item/gun/ballistic/automatic/pistol/m1911 name = "\improper M1911" desc = "A classic .45 handgun with a small magazine capacity." @@ -92,3 +124,34 @@ to_chat(user, "..and falls into view. Whew, that was a close one.") user.dropItemToGround(src) +////////////Anti Tank Pistol//////////// + +/obj/item/gun/ballistic/automatic/pistol/antitank + name = "Anti Tank Pistol" + desc = "A massively impractical and silly monstrosity of a pistol that fires .50 calliber rounds. The recoil is likely to dislocate your wrist." + icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' + icon_state = "atp" + item_state = "pistol" + recoil = 4 + mag_type = /obj/item/ammo_box/magazine/sniper_rounds + fire_delay = 50 + burst_size = 1 + can_suppress = 0 + w_class = WEIGHT_CLASS_NORMAL + actions_types = list() + fire_sound = 'sound/weapons/blastcannon.ogg' + spread = 20 //damn thing has no rifling. + +/obj/item/gun/ballistic/automatic/pistol/antitank/update_icon() + ..() + if(magazine) + cut_overlays() + add_overlay("atp-mag") + else + cut_overlays() + icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" + +/obj/item/gun/ballistic/automatic/pistol/antitank/syndicate + name = "Syndicate Anti Tank Pistol" + desc = "A massively impractical and silly monstrosity of a pistol that fires .50 calliber rounds. The recoil is likely to dislocate a variety of joints without proper bracing." + pin = /obj/item/firing_pin/implant/pindicate diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 36a9bba295..e0c84e7047 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -65,9 +65,6 @@ update_icon() /obj/item/gun/energy/Destroy() - //no need to delete them, since contents are already deleted in atom/movable/Destroy(). - cell = null - ammo_type = null STOP_PROCESSING(SSobj, src) return ..() diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm index 14b2ff0c1a..c993c0013a 100644 --- a/code/modules/projectiles/guns/magic/staff.dm +++ b/code/modules/projectiles/guns/magic/staff.dm @@ -90,9 +90,10 @@ . = ..() AddComponent(/datum/component/butchering, 15, 125, 0, hitsound) -/obj/item/gun/magic/staff/spellblade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(attack_type == PROJECTILE_ATTACK) - final_block_chance = 0 +/obj/item/gun/magic/staff/spellblade/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + // Do not block projectiles. + if(attack_type & ATTACK_TYPE_PROJECTILE) + return BLOCK_NONE return ..() /obj/item/gun/magic/staff/locker diff --git a/code/modules/projectiles/guns/misc/chameleon.dm b/code/modules/projectiles/guns/misc/chameleon.dm index d2afe2bd78..4fa614ae5c 100644 --- a/code/modules/projectiles/guns/misc/chameleon.dm +++ b/code/modules/projectiles/guns/misc/chameleon.dm @@ -60,13 +60,12 @@ continue vv_edit_var(v, initial(vars[v])) vars[v] = initial(vars[v]) - QDEL_NULL(chambered.BB) + QDEL_NULL(chambered.BB) chambered.newshot() /obj/item/gun/energy/laser/chameleon/proc/set_chameleon_ammo(obj/item/ammo_casing/AC, passthrough = TRUE, reset = FALSE) if(!istype(AC)) CRASH("[AC] is not /obj/item/ammo_casing!") - return FALSE for(var/V in ammo_copy_vars) if(AC.vars.Find(V)) chameleon_ammo_vars[V] = AC.vars[V] @@ -78,7 +77,6 @@ /obj/item/gun/energy/laser/chameleon/proc/set_chameleon_projectile(obj/item/projectile/P) if(!istype(P)) CRASH("[P] is not /obj/item/projectile!") - return FALSE chameleon_projectile_vars = list("name" = "practice laser", "icon" = 'icons/obj/projectiles.dmi', "icon_state" = "laser", "nodamage" = TRUE) for(var/V in projectile_copy_vars) if(P.vars.Find(V)) @@ -99,7 +97,6 @@ /obj/item/gun/energy/laser/chameleon/proc/set_chameleon_gun(obj/item/gun/G , passthrough = TRUE) if(!istype(G)) CRASH("[G] is not /obj/item/gun!") - return FALSE for(var/V in gun_copy_vars) if(vars.Find(V) && G.vars.Find(V)) chameleon_gun_vars[V] = G.vars[V] diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 9b60f96d16..6094a7aa46 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -20,7 +20,7 @@ var/atom/movable/firer = null//Who shot it var/atom/fired_from = null // the atom that the projectile was fired from (gun, turret) var/suppressed = FALSE //Attack message var/suppressed = FALSE //Attack message - var/candink = FALSE //Can this projectile play the dink sound when hitting the head? var/yo = null + var/candink = FALSE //Can this projectile play the dink sound when hitting the head? var/yo = null var/xo = null var/atom/original = null // the original target clicked @@ -695,3 +695,9 @@ /obj/item/projectile/experience_pressure_difference() return + +/////// MISC HELPERS //////// +/// Is this atom reflectable with ""standardized"" reflection methods like you know eshields and deswords and similar +/proc/is_energy_reflectable_projectile(atom/A) + var/obj/item/projectile/P = A + return istype(P) && P.is_reflectable diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm index b68c3847e2..319640a4d5 100644 --- a/code/modules/projectiles/projectile/bullets/pistol.dm +++ b/code/modules/projectiles/projectile/bullets/pistol.dm @@ -34,3 +34,17 @@ name = "10mm incendiary bullet" damage = 15 fire_stacks = 2 + +/obj/item/projectile/bullet/c10mm/soporific + name ="10mm soporific bullet" + nodamage = TRUE + +/obj/item/projectile/bullet/c10mm/soporific/on_hit(atom/target, blocked = FALSE) + . = ..() + if((blocked != 100) && isliving(target)) + var/mob/living/L = target + L.blur_eyes(6) + if(L.getStaminaLoss() >= 60) + L.Sleeping(300) + else + L.adjustStaminaLoss(25) \ No newline at end of file diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 7695ef77be..5f2edd5206 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -284,7 +284,7 @@ if(L.mind) L.mind.transfer_to(S) if(owner) - to_chat(S, "You are an animate statue. You cannot move when monitored, but are nearly invincible and deadly when unobserved! Do not harm [owner], your creator.") + to_chat(S, "You are an animated statue. You cannot move when monitored, but are nearly invincible and deadly when unobserved! Do not harm [owner], your creator.") P.forceMove(S) return else diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index eff1531e23..89dd229407 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -972,7 +972,6 @@ if(isnull(amount)) amount = 0 CRASH("null amount passed to reagent code") - return FALSE if(!isnum(amount)) return FALSE diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 384a113b27..5eb5b94de9 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -214,7 +214,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) //For easy bloodsucker disgusting and blood removal /datum/reagent/proc/disgust_bloodsucker(mob/living/carbon/C, disgust, blood_change, blood_puke = TRUE, force) - if(isvamp(C)) + if(AmBloodsucker(C)) var/datum/antagonist/bloodsucker/bloodsuckerdatum = C.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) if(disgust) bloodsuckerdatum.handle_eat_human_food(disgust, blood_puke, force) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index b7f32421aa..7ee233b449 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -43,8 +43,8 @@ All effects don't start immediately, but rather get worse over time; the rate is booze_power *= 0.7 C.drunkenness = max((C.drunkenness + (sqrt(volume) * booze_power * ALCOHOL_RATE)), 0) //Volume, power, and server alcohol rate effect how quickly one gets drunk var/obj/item/organ/liver/L = C.getorganslot(ORGAN_SLOT_LIVER) - if (istype(L)) - C.applyLiverDamage((max(sqrt(volume) * (boozepwr ** ALCOHOL_EXPONENT) * L.alcohol_tolerance, 0))/150) + if(L) + L.applyOrganDamage((max(sqrt(volume) * (boozepwr ** ALCOHOL_EXPONENT) * L.alcohol_tolerance, 0))/150) return ..() /datum/reagent/consumable/ethanol/reaction_obj(obj/O, reac_volume) @@ -579,7 +579,7 @@ All effects don't start immediately, but rather get worse over time; the rate is value = 1.3 /datum/reagent/consumable/ethanol/bloody_mary/on_mob_life(mob/living/carbon/C) - if(isvamp(C)) + if(AmBloodsucker(C)) disgust_bloodsucker(FALSE, 1) //Bloodsuckers get SOME blood from it, for style reasons. if(C.blood_volume < (BLOOD_VOLUME_NORMAL*C.blood_ratio)) C.blood_volume = min((BLOOD_VOLUME_NORMAL*C.blood_ratio), C.blood_volume + 3) //Bloody Mary quickly restores blood loss. @@ -1646,7 +1646,7 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "pina_colada" glass_name = "Pina Colada" glass_desc = "If you like pina coladas, and getting caught in the rain... well, you'll like this drink." - + /datum/reagent/consumable/ethanol/grasshopper name = "Grasshopper" description = "A fresh and sweet dessert shooter. Difficult to look manly while drinking this." @@ -2354,7 +2354,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/hotlime_miami/on_mob_life(mob/living/carbon/M) M.set_drugginess(50) M.adjustStaminaLoss(-2) - return ..() + return ..() /datum/reagent/consumable/ethanol/fruit_wine name = "Fruit Wine" diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index bf090302c8..e7229b5abf 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -467,9 +467,9 @@ if(H.physiology) H.physiology.stamina_mod *= 0.5 if(H.dna && H.dna.species) - H.dna.species.punchdamagehigh *= 4 - H.dna.species.punchdamagelow *= 4 - H.dna.species.punchstunthreshold *= 2 + H.dna.species.punchdamagehigh += 4 + H.dna.species.punchdamagelow += 4 + H.dna.species.punchstunthreshold -= 2 /datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L) . = ..() @@ -480,9 +480,9 @@ if(H.physiology) H.physiology.stamina_mod *= 2 if(H.dna && H.dna.species) - H.dna.species.punchdamagehigh *= 0.25 - H.dna.species.punchdamagelow *= 0.25 - H.dna.species.punchstunthreshold *= 0.5 + H.dna.species.punchdamagehigh -= 4 + H.dna.species.punchdamagelow -= 4 + H.dna.species.punchstunthreshold += 2 /datum/reagent/drug/skooma/on_mob_life(mob/living/carbon/M) M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index fa30609c54..c003fc7111 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -18,6 +18,7 @@ /datum/reagent/consumable/on_mob_life(mob/living/carbon/M) current_cycle++ M.nutrition += nutriment_factor + M.CheckBloodsuckerEatFood(nutriment_factor) holder.remove_reagent(type, metabolization_rate) /datum/reagent/consumable/reaction_mob(mob/living/M, method=TOUCH, reac_volume) @@ -423,6 +424,50 @@ M.emote(pick("twitch","giggle")) ..() +/datum/reagent/consumable/garlic //NOTE: having garlic in your blood stops vampires from biting you. + name = "Garlic Juice" + //id = "garlic" + description = "Crushed garlic. Chefs love it, but it can make you smell bad." + color = "#FEFEFE" + taste_description = "garlic" + metabolization_rate = 0.15 * REAGENTS_METABOLISM + +/datum/reagent/consumable/garlic/on_mob_life(mob/living/carbon/M) + if(isvampire(M)) //incapacitating but not lethal. Unfortunately, vampires cannot vomit. + if(prob(min(25, current_cycle))) + to_chat(M, "You can't get the scent of garlic out of your nose! You can barely think...") + M.Stun(10) + M.Jitter(10) + return + + else if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.job == "Cook") + if(prob(20)) //stays in the system much longer than sprinkles/banana juice, so heals slower to partially compensate + H.heal_bodypart_damage(1, 1, 0) + . = 1 + ..() + +/datum/reagent/consumable/garlic/reaction_mob(mob/living/M, method, reac_volume) + if(AmBloodsucker(M, TRUE)) //Theyll be immune to garlic as long as they masquarade, but they cant do it if they already have it. + switch(method) + if(INGEST) + if(prob(min(30, current_cycle))) + to_chat(M, "You cant get the smell of garlic out of your nose! You cant think straight because of it!") + M.Jitter(15) + if(prob(min(15, current_cycle))) + M.visible_message("Something you ate is burning your stomach!", "[M] clutches their stomach and falls to the ground!") + M.Knockdown(20) + M.emote("scream") + if(prob(min(5, current_cycle)) && iscarbon(M)) + var/mob/living/carbon/C + C.vomit() + if(INJECT) + if(prob(min(20, current_cycle))) + to_chat(M, "You feel like your veins are boiling!") + M.emote("scream") + M.adjustFireLoss(5) + ..() /datum/reagent/consumable/sprinkles name = "Sprinkles" value = 3 diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 46002287dd..ecceb6e8bf 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -263,9 +263,9 @@ /datum/reagent/medicine/silver_sulfadiazine/overdose_start(mob/living/M) metabolization_rate = 15 * REAGENTS_METABOLISM M.adjustBruteLoss(2*REM, 0) - if(iscarbon(M)) - var/mob/living/carbon/C = M - C.applyLiverDamage(1) + var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) + if(L) + L.applyOrganDamage(1) ..() . = 1 @@ -326,9 +326,9 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M) metabolization_rate = 15 * REAGENTS_METABOLISM M.adjustBruteLoss(2*REM, 0) - if(iscarbon(M)) - var/mob/living/carbon/C = M - C.applyLiverDamage(1) + var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) + if(L) + L.applyOrganDamage(1) ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index d9b2aafb4b..c2f14e69ec 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -332,7 +332,7 @@ data = list("misc" = 1) data["misc"]++ M.jitteriness = min(M.jitteriness+4,10) - if(iscultist(M)) + if(iscultist(M, FALSE, TRUE)) for(var/datum/action/innate/cult/blood_magic/BM in M.actions) if(!BM.holy_dispel) BM.holy_dispel = TRUE @@ -361,7 +361,7 @@ if("emote") M.visible_message("[M] [pick("whimpers quietly", "shivers as though cold", "glances around in paranoia")].") if(data["misc"] >= 60) // 30 units, 135 seconds - if(iscultist(M) || is_servant_of_ratvar(M)) + if(iscultist(M, FALSE, TRUE) || is_servant_of_ratvar(M, FALSE, TRUE)) if(iscultist(M)) SSticker.mode.remove_cultist(M.mind, FALSE, TRUE) else if(is_servant_of_ratvar(M)) @@ -1070,11 +1070,11 @@ to_chat(M, "You start feeling your guts twisting painfully!") SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/overdose, name) -/datum/reagent/iron/overdose_process(mob/living/carbon/C) +/datum/reagent/iron/overdose_process(mob/living/M) if(prob(20)) - var/obj/item/organ/liver/L = C.getorganslot(ORGAN_SLOT_LIVER) - if (istype(L)) - C.applyLiverDamage(2) //mild until the fabled med rework comes out. the organ damage galore + var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) + if(L) + L.applyOrganDamage(2) ..() /datum/reagent/gold diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 3c4be7969d..9555f5b64b 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -331,7 +331,6 @@ else to_chat(user, "This doesn't fit in [src].") return FALSE - return FALSE /obj/item/hypospray/mkii/AltClick(mob/user) . = ..() diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 6b3ba6fe28..5405b82848 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -122,16 +122,6 @@ category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL -/datum/design/bluespacebodybag - name = "Bluespace Body Bag" - desc = "A bluespace body bag, powered by experimental bluespace technology. It can hold loads of bodies and the largest of creatures." - id = "bluespacebodybag" - build_type = PROTOLATHE - materials = list(/datum/material/iron = 3000, /datum/material/plasma = 2000, /datum/material/diamond = 500, /datum/material/bluespace = 500) - build_path = /obj/item/bodybag/bluespace - category = list("Medical Designs") - departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE - /datum/design/plasmarefiller name = "Plasma-Man Jumpsuit Refill" desc = "A refill pack for the auto-extinguisher on Plasma-man suits." @@ -242,6 +232,40 @@ category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE +//////////////////////////////////////// +//////////Body Bags///////////////////// +//////////////////////////////////////// + +/datum/design/bodybag + name = "Body Bag" + desc = "A normal body bag used for storge of dead crew." + id = "bodybag" + build_type = PROTOLATHE + materials = list(/datum/material/plastic = 4000) + build_path = /obj/item/bodybag + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/bluespacebodybag + name = "Bluespace Body Bag" + desc = "A bluespace body bag, powered by experimental bluespace technology. It can hold loads of bodies and the largest of creatures." + id = "bluespacebodybag" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 3000, /datum/material/plasma = 2000, /datum/material/diamond = 500, /datum/material/bluespace = 500) + build_path = /obj/item/bodybag/bluespace + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/containmentbodybag + name = "Containment Body Bag" + desc = "A containment body bag, heavy and radiation proof." + id = "containmentbodybag" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 6000, /datum/material/plastic = 4000, /datum/material/titanium = 2000) + build_path = /obj/item/bodybag/containment + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + //////////////////////////////////////// //////////Defibrillator Tech//////////// //////////////////////////////////////// diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index c50227e60d..dafa119873 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -79,7 +79,7 @@ display_name = "Advanced Biotechnology" description = "Advanced Biotechnology" prereq_ids = list("biotech") - design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "meta_beaker", "healthanalyzer_advanced", "harvester", "holobarrier_med", "defibrillator_compact", "smartdartgun", "medicinalsmartdart", "pHmeter") + design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "meta_beaker", "healthanalyzer_advanced", "harvester", "holobarrier_med", "defibrillator_compact", "smartdartgun", "medicinalsmartdart", "pHmeter", "containmentbodybag") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) /datum/techweb_node/bio_process @@ -221,16 +221,14 @@ description = "Unlock the potential of the mysterious of why CC decided to not build these around the station themselves." prereq_ids = list("adv_engi", "high_efficiency") design_ids = list("meteor_defence", "meteor_console") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) -*/ -//datum/techweb_node/adv_meteor_defense - //id = "adv_meteor_defense" - //display_name = "Meteor Defense Research" - //description = "New and improved coding and lock on tech for meteor defence!" - //prereq_ids = list("basic_meteor_defense", "adv_datatheory", "emp_adv") - //design_ids = list("meteor_disk") - //research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) +/datum/techweb_node/adv_meteor_defense + id = "adv_meteor_defense" + display_name = "Meteor Defense Research" + description = "New and improved coding and lock on tech for meteor defence!" + prereq_ids = list("basic_meteor_defense", "adv_datatheory", "emp_adv") + design_ids = list("meteor_disk") +*/ /datum/techweb_node/computer_board_gaming id = "computer_board_gaming" diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm index b8bdffbabf..795a57b82c 100644 --- a/code/modules/research/xenobiology/crossbreeding/_clothing.dm +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -137,8 +137,7 @@ Slimecrossing Armor var/hit_reflect_chance = 10 // Citadel Change: because 40% chance of bouncing lasers back into peoples faces isn't good. armor = list("melee" = 70, "bullet" = 70, "laser" = 40, "energy" = 40, "bomb" = 80, "bio" = 80, "rad" = 80, "fire" = 70, "acid" = 90) //Citadel Change to avoid immortal Xenobiologists. -/obj/item/clothing/suit/armor/heavy/adamantine/IsReflect(def_zone) - if(def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) && prob(hit_reflect_chance)) - return TRUE - else - return FALSE +/obj/item/clothing/suit/armor/heavy/adamantine/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(is_energy_reflectable_projectile(object) && prob(hit_reflect_chance)) + return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_INTERNAL + return ..() diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 03488fa8a9..143fe508b6 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -45,6 +45,12 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th /obj/effect/proc_holder/singularity_pull() return +/obj/effect/proc_holder/Click() + return Trigger(usr, FALSE) + +/obj/effect/proc_holder/proc/Trigger(mob/user) + return TRUE + /obj/effect/proc_holder/proc/InterceptClickOn(mob/living/caller, params, atom/A) if(caller.ranged_ability != src || ranged_ability_user != caller) //I'm not actually sure how these would trigger, but, uh, safety, I guess? to_chat(caller, "[caller.ranged_ability.name] has been disabled.") @@ -150,8 +156,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th if(mobs_blacklist) mobs_blacklist = typecacheof(mobs_blacklist) -/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = FALSE, mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell - if(!can_cast(user, skipcharge)) +/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = FALSE, mob/user = usr, skip_can_cast = FALSE) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell + if(!skip_can_cast && !can_cast(user, skipcharge)) return FALSE if(!skipcharge) @@ -181,17 +187,22 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th return TRUE /obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount + var/mob/living/L + if(isliving(user)) + L = user switch(invocation_type) if("shout") - if(prob(50))//Auto-mute? Fuck that noise - user.say(invocation, forced = "spell") - else - user.say(replacetext(invocation," ","`"), forced = "spell") + if(!L || L.can_speak_vocal(invocation)) + if(prob(50))//Auto-mute? Fuck that noise + user.say(invocation, forced = "spell") + else + user.say(replacetext(invocation," ","`"), forced = "spell") if("whisper") - if(prob(50)) - user.whisper(invocation) - else - user.whisper(replacetext(invocation," ","`")) + if(!L || L.can_speak_vocal(invocation)) + if(prob(50)) + user.whisper(invocation) + else + user.whisper(replacetext(invocation," ","`")) if("emote") user.visible_message(invocation, invocation_emote_self) //same style as in mob/living/emote.dm @@ -210,8 +221,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th qdel(action) return ..() -/obj/effect/proc_holder/spell/Click() - if(cast_check()) +/obj/effect/proc_holder/spell/Trigger(mob/user, skip_can_cast = TRUE) + if(cast_check(FALSE, user, skip_can_cast)) choose_targets() return 1 @@ -432,7 +443,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th return 1 /obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr, skipcharge = FALSE, silent = FALSE) - var/magic_flags = SEND_SIGNAL(user, COMSIG_MOB_SPELL_CAST_CHECK, src) + var/magic_flags = SEND_SIGNAL(user, COMSIG_MOB_SPELL_CAN_CAST, src) if(magic_flags & SPELL_SKIP_ALL_REQS) return TRUE @@ -448,9 +459,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th to_chat(user, "You can't cast this spell here.") return FALSE - if(!skipcharge) - if(!charge_check(user)) - return FALSE + if(!skipcharge && !charge_check(user, silent)) + return FALSE if(user.stat && !stat_allowed && !(magic_flags & SPELL_SKIP_STAT)) if(!silent) diff --git a/code/modules/spells/spell_types/aimed.dm b/code/modules/spells/spell_types/aimed.dm index 786026a1bc..1a904b1076 100644 --- a/code/modules/spells/spell_types/aimed.dm +++ b/code/modules/spells/spell_types/aimed.dm @@ -11,12 +11,11 @@ var/current_amount = 0 //How many projectiles left. var/projectiles_per_fire = 1 //Projectiles per fire. Probably not a good thing to use unless you override ready_projectile(). -/obj/effect/proc_holder/spell/aimed/Click() - var/mob/living/user = usr +/obj/effect/proc_holder/spell/aimed/Trigger(mob/user, skip_can_cast = TRUE) if(!istype(user)) return var/msg - if(!can_cast(user, FALSE, TRUE)) + if(!skip_can_cast && !can_cast(user, FALSE, TRUE)) msg = "You can no longer cast [name]!" remove_ranged_ability(msg) return diff --git a/code/modules/spells/spell_types/lightning.dm b/code/modules/spells/spell_types/lightning.dm index 81b26cf464..d0c3c4166c 100644 --- a/code/modules/spells/spell_types/lightning.dm +++ b/code/modules/spells/spell_types/lightning.dm @@ -15,9 +15,9 @@ action_icon_state = "lightning" -/obj/effect/proc_holder/spell/targeted/tesla/Click() - if(!ready && cast_check()) - StartChargeup() +/obj/effect/proc_holder/spell/targeted/tesla/Trigger(mob/user, skip_can_cast = TRUE) + if(!ready && cast_check(FALSE, user, skip_can_cast)) + StartChargeup(user) return 1 /obj/effect/proc_holder/spell/targeted/tesla/proc/StartChargeup(mob/user = usr) diff --git a/code/modules/spells/spell_types/mime.dm b/code/modules/spells/spell_types/mime.dm index a3bb81ae55..8f39da5031 100644 --- a/code/modules/spells/spell_types/mime.dm +++ b/code/modules/spells/spell_types/mime.dm @@ -16,12 +16,12 @@ action_icon_state = "mime" action_background_icon_state = "bg_mime" -/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Click() - if(usr && usr.mind) - if(!usr.mind.miming) +/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Trigger(mob/user, skip_can_cast = TRUE) + if(user.mind) + if(!user.mind.miming) to_chat(usr, "You must dedicate yourself to silence first.") return - invocation = "[usr.real_name] looks as if a wall is in front of [usr.p_them()]." + invocation = "[user.real_name] looks as if a wall is in front of [user.p_them()]." else invocation_type ="none" ..() @@ -41,17 +41,12 @@ action_icon_state = "mime" action_background_icon_state = "bg_mime" -/obj/effect/proc_holder/spell/targeted/mime/speak/Click() - if(!usr) - return - if(!ishuman(usr)) - return - var/mob/living/carbon/human/H = usr - if(H.mind.miming) +/obj/effect/proc_holder/spell/targeted/mime/speak/Trigger(mob/user, skip_can_cast = TRUE) + if(user.mind?.miming) still_recharging_msg = "You can't break your vow of silence that fast!" else still_recharging_msg = "You'll have to wait before you can give your vow of silence again!" - ..() + return ..() /obj/effect/proc_holder/spell/targeted/mime/speak/cast(list/targets,mob/user = usr) for(var/mob/living/carbon/human/H in targets) @@ -82,15 +77,15 @@ action_icon_state = "mime" action_background_icon_state = "bg_mime" -/obj/effect/proc_holder/spell/targeted/forcewall/mime/Click() - if(usr && usr.mind) - if(!usr.mind.miming) +/obj/effect/proc_holder/spell/targeted/forcewall/mime/Trigger(mob/user, skip_can_cast = TRUE) + if(user.mind) + if(!user.mind.miming) to_chat(usr, "You must dedicate yourself to silence first.") return - invocation = "[usr.real_name] looks as if a blockade is in front of [usr.p_them()]." + invocation = "[user.real_name] looks as if a blockade is in front of [user.p_them()]." else invocation_type ="none" - ..() + return ..() /obj/effect/proc_holder/spell/aimed/finger_guns name = "Finger Guns" @@ -114,19 +109,18 @@ base_icon_state = "mime" -/obj/effect/proc_holder/spell/aimed/finger_guns/Click() - var/mob/living/carbon/human/owner = usr - if(owner.incapacitated()) - to_chat(owner, "You can't properly point your fingers while incapacitated.") +/obj/effect/proc_holder/spell/aimed/finger_guns/Trigger(mob/user, skip_can_cast = TRUE) + if(user.incapacitated()) + to_chat(user, "You can't properly point your fingers while incapacitated.") return - if(usr && usr.mind) - if(!usr.mind.miming) + if(user.mind) + if(!user.mind.miming) to_chat(usr, "You must dedicate yourself to silence first.") return - invocation = "[usr.real_name] fires [usr.p_their()] finger gun!" + invocation = "[user.real_name] fires [user.p_their()] finger gun!" else invocation_type ="none" - ..() + return ..() /obj/effect/proc_holder/spell/targeted/touch/mimerope name = "Invisible Rope" @@ -144,8 +138,8 @@ action_background_icon_state = "bg_mime" hand_path = /obj/item/melee/touch_attack/mimerope -/obj/effect/proc_holder/spell/targeted/touch/mimerope/Click() - if(usr && usr.mind) +/obj/effect/proc_holder/spell/targeted/touch/mimerope/Trigger(mob/user, skip_can_cast = TRUE) + if(user.mind) if(!usr.mind.miming) to_chat(usr, "You must dedicate yourself to silence first.") return diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 4b169173ed..54f2aef10d 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -436,7 +436,7 @@ if(!isnull(body_markings) && status == BODYPART_ORGANIC) if(!use_digitigrade) - if(BODY_ZONE_CHEST) + if(body_zone == BODY_ZONE_CHEST) . += image(body_markings_icon, "[body_markings]_[body_zone]_[icon_gender]", -MARKING_LAYER, image_dir) else . += image(body_markings_icon, "[body_markings]_[body_zone]", -MARKING_LAYER, image_dir) diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm index 73225fc41c..117a45cdbc 100755 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -1,7 +1,6 @@ #define LIVER_DEFAULT_HEALTH 100 //amount of damage required for liver failure #define LIVER_DEFAULT_TOX_TOLERANCE 3 //amount of toxins the liver can filter out #define LIVER_DEFAULT_TOX_LETHALITY 0.01 //lower values lower how harmful toxins are to the liver -#define LIVER_SWELLING_MOVE_MODIFY "pharma" /obj/item/organ/liver name = "liver" @@ -15,12 +14,14 @@ healing_factor = STANDARD_ORGAN_HEALING decay_factor = STANDARD_ORGAN_DECAY + high_threshold_passed = "You feel a stange ache in your abdomen, almost like a stitch. This pain is encumbering your movements." + high_threshold_cleared = "The stitching ache in your abdomen passes away, unencumbering your movements." + now_fixed = "The stabbing pain in your abdomen slowly calms down into a more tolerable ache." + var/alcohol_tolerance = ALCOHOL_RATE//affects how much damage the liver takes from alcohol - var/failing //is this liver failing? var/toxTolerance = LIVER_DEFAULT_TOX_TOLERANCE//maximum amount of toxins the liver can just shrug off var/toxLethality = LIVER_DEFAULT_TOX_LETHALITY//affects how much damage toxins do to the liver var/filterToxins = TRUE //whether to filter toxins - var/swelling = 0 var/cachedmoveCalc = 1 /obj/item/organ/liver/on_life() @@ -28,8 +29,6 @@ if(istype(C)) if(!(organ_flags & ORGAN_FAILING))//can't process reagents with a failing liver - //slowly heal liver damage - damage = max(0, damage - 0.1) if(filterToxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER)) //handle liver toxin filtration @@ -46,42 +45,41 @@ if(damage > 10 && prob(damage/3))//the higher the damage the higher the probability to_chat(C, "You feel a dull pain in your abdomen.") - if(damage > maxHealth)//cap liver damage - damage = maxHealth - - if(swelling >= 10) - pharmacokinesis() - /obj/item/organ/liver/prepare_eat() var/obj/S = ..() S.reagents.add_reagent(/datum/reagent/iron, 5) return S -//Just in case +/obj/item/organ/liver/applyOrganDamage(d, maximum = maxHealth) + . = ..() + if(!.) + return + if(damage >= high_threshold) + var/move_calc = 1+((round(damage) - high_threshold)/(high_threshold/3)) + owner.add_movespeed_modifier(MOVESPEED_ID_CIRRHOSIS, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = move_calc) + sizeMoveMod(move_calc, owner) + else + owner.remove_movespeed_modifier(MOVESPEED_ID_CIRRHOSIS) + sizeMoveMod(1, owner) + +/obj/item/organ/liver/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) + . = ..() + if(. && damage >= high_threshold) + var/move_calc = 1+((round(damage) - high_threshold)/(high_threshold/3)) + M.add_movespeed_modifier(MOVESPEED_ID_CIRRHOSIS, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = move_calc) + sizeMoveMod(move_calc, owner) + /obj/item/organ/liver/Remove(special = FALSE) if(!QDELETED(owner)) - owner.remove_movespeed_modifier(LIVER_SWELLING_MOVE_MODIFY) - owner.ResetBloodVol() //At the moment, this shouldn't allow application twice. You either have this OR a thirsty ferret. + owner.remove_movespeed_modifier(MOVESPEED_ID_CIRRHOSIS) sizeMoveMod(1, owner) return ..() -//Applies some of the effects to the patient. -/obj/item/organ/liver/proc/pharmacokinesis() - var/moveCalc = 1+((round(swelling) - 9)/3) - if(moveCalc == cachedmoveCalc)//reduce calculations - return - if(prob(5)) - to_chat(owner, "You feel a stange ache in your side, almost like a stitch. This pain is affecting your movements and making you feel lightheaded.") - var/mob/living/carbon/human/H = owner - H.add_movespeed_modifier(LIVER_SWELLING_MOVE_MODIFY, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) - H.AdjustBloodVol(moveCalc/3) - sizeMoveMod(moveCalc, H) - -/obj/item/organ/liver/proc/sizeMoveMod(var/value, mob/living/carbon/human/H) +/obj/item/organ/liver/proc/sizeMoveMod(value, mob/living/carbon/C) if(cachedmoveCalc == value) return - H.next_move_modifier /= cachedmoveCalc - H.next_move_modifier *= value + C.next_move_modifier /= cachedmoveCalc + C.next_move_modifier *= value cachedmoveCalc = value /obj/item/organ/liver/fly diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index b091af0f92..d95901bdbe 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -143,8 +143,9 @@ var/healing_amount = -(maxHealth * healing_factor) ///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's health healing_amount -= owner.satiety > 0 ? 4 * healing_factor * owner.satiety / MAX_SATIETY : 0 - applyOrganDamage(healing_amount) //to FERMI_TWEAK - //Make it so each threshold is stuck. + if(healing_amount) + applyOrganDamage(healing_amount) //to FERMI_TWEAK + //Make it so each threshold is stuck. /obj/item/organ/examine(mob/user) . = ..() @@ -205,14 +206,15 @@ ///Adjusts an organ's damage by the amount "d", up to a maximum amount, which is by default max damage /obj/item/organ/proc/applyOrganDamage(var/d, var/maximum = maxHealth) //use for damaging effects if(!d) //Micro-optimization. - return + return FALSE if(maximum < damage) - return + return FALSE damage = CLAMP(damage + d, 0, maximum) - var/mess = check_damage_thresholds(owner) + var/mess = check_damage_thresholds() prev_damage = damage if(mess && owner) to_chat(owner, mess) + return TRUE ///SETS an organ's damage to the amount "d", and in doing so clears or sets the failing flag, good for when you have an effect that should fix an organ if broken /obj/item/organ/proc/setOrganDamage(var/d) //use mostly for admin heals @@ -224,7 +226,7 @@ * description: By checking our current damage against our previous damage, we can decide whether we've passed an organ threshold. * If we have, send the corresponding threshold message to the owner, if such a message exists. */ -/obj/item/organ/proc/check_damage_thresholds(var/M) +/obj/item/organ/proc/check_damage_thresholds() if(damage == prev_damage) return var/delta = damage - prev_damage diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 7c849dbd68..671d31530a 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -74,7 +74,7 @@ ..() cords = target -/datum/action/item_action/organ_action/colossus/IsAvailable() +/datum/action/item_action/organ_action/colossus/IsAvailable(silent = FALSE) if(world.time < cords.next_command) return FALSE if(!owner) @@ -632,7 +632,7 @@ ..() cords = target -/datum/action/item_action/organ_action/velvet/IsAvailable() +/datum/action/item_action/organ_action/velvet/IsAvailable(silent = FALSE) return TRUE /datum/action/item_action/organ_action/velvet/Trigger() diff --git a/code/modules/surgery/plastic_surgery.dm b/code/modules/surgery/plastic_surgery.dm index ce9de95b4c..c4e056583c 100644 --- a/code/modules/surgery/plastic_surgery.dm +++ b/code/modules/surgery/plastic_surgery.dm @@ -40,7 +40,6 @@ if(ishuman(target)) var/mob/living/carbon/human/H = target H.sec_hud_set_ID() - return 1 return TRUE /datum/surgery_step/reshape_face/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/code/modules/uplink/uplink_items/uplink_ammo.dm b/code/modules/uplink/uplink_items/uplink_ammo.dm index 15bb47af91..4a7e1f146e 100644 --- a/code/modules/uplink/uplink_items/uplink_ammo.dm +++ b/code/modules/uplink/uplink_items/uplink_ammo.dm @@ -15,6 +15,12 @@ cost = 1 exclude_modes = list(/datum/game_mode/nuclear/clown_ops) +/datum/uplink_item/ammo/pistol/box + name = "Ammo Box - 10mm" + desc = "An additional box of 10mm ammo. The box has 20 cases inside, does not come with a magazine." + item = /obj/item/ammo_box/c10mm + illegal_tech = FALSE + /datum/uplink_item/ammo/pistolap name = "10mm Armour Piercing Magazine" desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. \ @@ -23,6 +29,12 @@ cost = 2 exclude_modes = list(/datum/game_mode/nuclear/clown_ops) +/datum/uplink_item/ammo/pistolap/box + name = "Ammo Box - 10mm Armour Piercing" + desc = "An additional box of 10mm Armour Piercing ammo. The box has 20 cases inside, does not come with a magazine." + item = /obj/item/ammo_box/c10mm/ap + illegal_tech = FALSE + /datum/uplink_item/ammo/pistolhp name = "10mm Hollow Point Magazine" desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. \ @@ -31,6 +43,12 @@ cost = 3 exclude_modes = list(/datum/game_mode/nuclear/clown_ops) +/datum/uplink_item/ammo/pistolhp/box + name = "Ammo Box - 10mm Hollow Point" + desc = "An additional box of 10mm Hollow Point ammo. The box has 20 cases inside, does not come with a magazine." + item = /obj/item/ammo_box/c10mm/hp + illegal_tech = FALSE + /datum/uplink_item/ammo/pistolfire name = "10mm Incendiary Magazine" desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. \ @@ -39,6 +57,12 @@ cost = 2 exclude_modes = list(/datum/game_mode/nuclear/clown_ops) +/datum/uplink_item/ammo/pistolfire/box + name = "Ammo Box - 10mm Incendiary" + desc = "An additional box of 10mm Incendiary ammo. The box has 20 cases inside, does not come with a magazine." + item = /obj/item/ammo_box/magazine/m10mm/fire + illegal_tech = FALSE + /datum/uplink_item/ammo/pistolzzz name = "10mm Soporific Magazine" desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with soporific rounds that put the target to sleep. \ @@ -46,6 +70,12 @@ item = /obj/item/ammo_box/magazine/m10mm/soporific cost = 2 +/datum/uplink_item/ammo/pistolzzz/box + name = "Ammo Box - 10mm Soporific" + desc = "An additional box of 10mm Soporific ammo. The box has 20 cases inside, does not come with a magazine." + item = /obj/item/ammo_box/c10mm/soporific + illegal_tech = FALSE + /datum/uplink_item/ammo/shotgun cost = 2 include_modes = list(/datum/game_mode/nuclear) @@ -212,6 +242,12 @@ cost = 2 include_modes = list(/datum/game_mode/nuclear) +/datum/uplink_item/ammo/pistolaps + name = "Ammo Box - 9mm" + desc = "An additional box of 9mm ammo. The box has 30 cases inside, does not come with a magazine." + item = /obj/item/ammo_box/c9mm + illegal_tech = FALSE + /datum/uplink_item/ammo/flechetteap name = "Armor Piercing Flechette Magazine" desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \ diff --git a/code/modules/uplink/uplink_items/uplink_clothing.dm b/code/modules/uplink/uplink_items/uplink_clothing.dm index aad9834612..d6336bd982 100644 --- a/code/modules/uplink/uplink_items/uplink_clothing.dm +++ b/code/modules/uplink/uplink_items/uplink_clothing.dm @@ -83,4 +83,10 @@ name = "Thieving Gloves" desc = "A pair of gloves that are insulated and frictionless, allowing you to steal easily from anyone you see." item = /obj/item/clothing/gloves/thief - cost = 4 \ No newline at end of file + cost = 4 + +/datum/uplink_item/suits/wallwalkers + name = "Wall Walking Boots" + desc = "Through bluespace magic stolen from an organisation that hoards technology, these boots simply allow you to slip through the atoms that make up anything, but only while walking, for safety reasons. As well as this, they unfortunately cause minor breath loss as the majority of atoms in your lungs are sucked out into any solid object you walk through." + item = /obj/item/clothing/shoes/wallwalkers + cost = 6 \ No newline at end of file diff --git a/code/modules/uplink/uplink_items/uplink_dangerous.dm b/code/modules/uplink/uplink_items/uplink_dangerous.dm index 819ba51623..c798aa5cd9 100644 --- a/code/modules/uplink/uplink_items/uplink_dangerous.dm +++ b/code/modules/uplink/uplink_items/uplink_dangerous.dm @@ -9,9 +9,9 @@ /datum/uplink_item/dangerous/pistol name = "Stechkin Pistol" - desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible \ + desc = "A sleek box containing a small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines. The handgun is compatible \ with suppressors." - item = /obj/item/gun/ballistic/automatic/pistol + item = /obj/item/storage/box/syndie_kit/pistol cost = 7 exclude_modes = list(/datum/game_mode/nuclear/clown_ops) @@ -174,10 +174,13 @@ include_modes = list(/datum/game_mode/nuclear) /datum/uplink_item/dangerous/rapid - name = "Gloves of the North Star" - desc = "These gloves let the user punch people very fast. Does not improve weapon attack speed or the meaty fists of a hulk." - item = /obj/item/clothing/gloves/rapid - cost = 8 + name = "Bands of the North Star" + desc = "These armbands let the user punch people very fast and with the lethality of a legendary martial artist. \ + Does not improve weapon attack speed or the meaty fists of a hulk, but you will be unmatched in martial power. \ + Combines with all martial arts, but the user will be unable to bring themselves to use guns, nor remove the armbands." + item = /obj/item/clothing/gloves/fingerless/pugilist/rapid + cost = 30 + include_modes = list(/datum/game_mode/nuclear) /datum/uplink_item/dangerous/guardian name = "Holoparasites" diff --git a/code/modules/uplink/uplink_items/uplink_devices.dm b/code/modules/uplink/uplink_items/uplink_devices.dm index 06fd9aab43..194281ded6 100644 --- a/code/modules/uplink/uplink_items/uplink_devices.dm +++ b/code/modules/uplink/uplink_items/uplink_devices.dm @@ -20,6 +20,12 @@ item = /obj/item/emagrecharge cost = 2 +/datum/uplink_item/device_tools/bluespacerecharge + name = "Bluespace Crystal Recharging Device" + desc = "A small device intended for recharging Wall Walking boots. Using it will add six charges to them. Use ten bluespace crystals on this recharger to add three more charges to it. " + item = /obj/item/bluespacerecharge + cost = 2 + /datum/uplink_item/device_tools/phantomthief name = "Syndicate Mask" desc = "A cheap plastic mask fitted with an adrenaline autoinjector, which can be used by simply tensing your muscles" @@ -185,8 +191,9 @@ /datum/uplink_item/device_tools/stimpack name = "Stimpack" desc = "Stimpacks, the tool of many great heroes, make you nearly immune to stuns and knockdowns for about \ - 5 minutes after injection." - item = /obj/item/reagent_containers/syringe/stimulants + 5 minutes after fully injecting yourself. Can inject yourself, or others, 5 times and through hardsuits. \ + Each injection will gives around a minute of stimulants." + item = /obj/item/reagent_containers/hypospray/medipen/stimulants cost = 5 surplus = 90 diff --git a/code/modules/uplink/uplink_items/uplink_roles.dm b/code/modules/uplink/uplink_items/uplink_roles.dm index 3d28010133..778edf8cc8 100644 --- a/code/modules/uplink/uplink_items/uplink_roles.dm +++ b/code/modules/uplink/uplink_items/uplink_roles.dm @@ -92,6 +92,22 @@ restricted_roles = list("Chaplain") surplus = 5 //Very low chance to get it in a surplus crate even without being the chaplain +/datum/uplink_item/role_restricted/clockwork_slab + name = "Clockwork Slab" + desc = "A reverse engineered clockwork slab. Is this really a good idea?." + item = /obj/item/clockwork/slab/traitor + cost = 20 + refundable = TRUE + restricted_roles = list("Chaplain") + +/datum/uplink_item/role_restricted/arcane_tome + name = "Arcane Tome" + desc = "A replica of a Nar'sian tome. This is probably a bad idea.." + item = /obj/item/tome/traitor + cost = 20 + refundable = TRUE + restricted_roles = list("Chaplain") + /datum/uplink_item/role_restricted/explosive_hot_potato name = "Exploding Hot Potato" desc = "A potato rigged with explosives. On activation, a special mechanism is activated that prevents it from being dropped. \ diff --git a/code/modules/vehicles/scooter.dm b/code/modules/vehicles/scooter.dm index 990ff93595..1fb037d1c5 100644 --- a/code/modules/vehicles/scooter.dm +++ b/code/modules/vehicles/scooter.dm @@ -133,9 +133,6 @@ else playsound(src, 'sound/vehicles/skateboard_roll.ogg', 50, TRUE) if(prob (25)) - var/turf/location = get_turf(loc) - if(location) - location.hotspot_expose(1000,1000) sparks.start() //the most radical way to start plasma fires addtimer(CALLBACK(src, .proc/grind), 2) return diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index 8a62c19e16..4f7502bb02 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -16,12 +16,26 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY CANISTER CHARGES in vending_items.dm */ +#define MAX_VENDING_INPUT_AMOUNT 30 +/** + * # vending record datum + * + * A datum that represents a product that is vendable + */ /datum/data/vending_product name = "generic" + ///Typepath of the product that is created when this record "sells" var/product_path = null + ///How many of this product we currently have var/amount = 0 + ///How many we can store at maximum var/max_amount = 0 +/** + * # vending machines + * + * Captalism in the year 2525, everything in a vending machine, even love + */ /obj/machinery/vending name = "\improper Vendomat" desc = "A generic vending machine." @@ -36,43 +50,117 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C integrity_failure = 0.33 armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70) circuit = /obj/item/circuitboard/machine/vendor - var/active = 1 //No sales pitches if off! - var/vend_ready = 1 //Are we ready to vend?? Is it time?? + light_power = 0.5 + light_range = MINIMUM_USEFUL_LIGHT_RANGE + /// Is the machine active (No sales pitches if off)! + var/active = TRUE + ///Are we ready to vend?? Is it time?? + var/vend_ready = TRUE + ///Next world time to send a purchase message + var/purchase_message_cooldown + ///Last mob to shop with us - // To be filled out at compile time - var/list/products = list() //For each, use the following pattern: - var/list/contraband = list() //list(/type/path = amount, /type/path2 = amount2) - var/list/premium = list() //No specified amount = only one in stock + /** + * List of products this machine sells + * + * form should be list(/type/path = amount, /type/path2 = amount2) + */ + var/list/products = list() + + /** + * List of products this machine sells when you hack it + * + * form should be list(/type/path = amount, /type/path2 = amount2) + */ + var/list/contraband = list() + + /** + * List of premium products this machine sells + * + * form should be list(/type/path, /type/path2) as there is only ever one in stock + */ + var/list/premium = list() + + ///String of slogans separated by semicolons, optional + var/product_slogans = "" + ///String of small ad messages in the vending screen - random chance + var/product_ads = "" - var/product_slogans = "" //String of slogans separated by semicolons, optional - var/product_ads = "" //String of small ad messages in the vending screen - random chance var/list/product_records = list() var/list/hidden_records = list() var/list/coin_records = list() var/list/slogan_list = list() - var/list/small_ads = list() //Small ad messages in the vending screen - random chance of popping up whenever you open it - var/vend_reply //Thank you for shopping! - var/last_reply = 0 - var/last_slogan = 0 //When did we last pitch? - var/slogan_delay = 6000 //How long until we can pitch again? - var/icon_vend //Icon_state when vending! - var/icon_deny //Icon_state when vending! - var/seconds_electrified = 0 //Shock customers like an airlock. - var/shoot_inventory = 0 //Fire items at customers! We're broken! - var/shoot_inventory_chance = 2 - var/shut_up = 0 //Stop spouting those godawful pitches! - var/extended_inventory = 0 //can we access the hidden inventory? - var/scan_id = 1 - var/obj/item/coin/coin - var/obj/item/stack/spacecash/bill - - var/static/vending_cache = list() //used for storing the icons of items being vended - + ///Small ad messages in the vending screen - random chance of popping up whenever you open it + var/list/small_ads = list() var/dish_quants = list() //used by the snack machine's custom compartment to count dishes. + ///Message sent post vend (Thank you for shopping!) + var/vend_reply + ///Last world tick we sent a vent reply + var/last_reply + ///Last world tick we sent a slogan message out + var/last_slogan + var/last_shopper + ///How many ticks until we can send another + var/slogan_delay = 6000 + ///Icon when vending an item to the user + var/icon_vend + ///Icon to flash when user is denied a vend + var/icon_deny + ///World ticks the machine is electified for + var/seconds_electrified = MACHINE_NOT_ELECTRIFIED + ///When this is TRUE, we fire items at customers! We're broken! + var/shoot_inventory + ///How likely this is to happen (prob 100) + var/shoot_inventory_chance = 2 + //Stop spouting those godawful pitches! + var/shut_up + ///can we access the hidden inventory? + var/extended_inventory + ///Are we checking the users ID + var/scan_id = TRUE + ///Coins that we accept? + var/obj/item/coin/coin + ///Default price of items if not overridden + /** + * Is this item on station or not + * + * if it doesn't originate from off-station during mapload, everything is free + */ + var/onstation = TRUE //if it doesn't originate from off-station during mapload, everything is free + ///A variable to change on a per instance basis on the map that allows the instance to force cost and ID requirements + var/onstation_override = FALSE //change this on the object on the map to override the onstation check. DO NOT APPLY THIS GLOBALLY. - var/obj/item/vending_refill/refill_canister = null //The type of refill canisters used by this machine. + ///ID's that can load this vending machine wtih refills + var/list/canload_access_list -/obj/machinery/vending/Initialize() + + var/list/vending_machine_input = list() + ///Display header on the input view + var/input_display_header = "Custom Vendor" + + //The type of refill canisters used by this machine. + var/obj/item/vending_refill/refill_canister = null + + /// how many items have been inserted in a vendor + var/loaded_items + + ///Name of lighting mask for the vending machine + var/light_mask + +/obj/item/circuitboard + ///determines if the circuit board originated from a vendor off station or not. + var/onstation = TRUE + +/** + * Initialize the vending machine + * + * Builds the vending machine inventory, sets up slogans and other such misc work + * + * This also sets the onstation var to: + * * FALSE - if the machine was maploaded on a zlevel that doesn't pass the is_station_level check + * * TRUE - all other cases + */ +/obj/machinery/vending/Initialize(mapload) var/build_inv = FALSE if(!refill_canister) circuit = null @@ -94,9 +182,11 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C /obj/machinery/vending/Destroy() QDEL_NULL(wires) QDEL_NULL(coin) - QDEL_NULL(bill) return ..() +/obj/machinery/vending/can_speak() + return !shut_up + /obj/machinery/vending/RefreshParts() //Better would be to make constructable child if(!component_parts) return @@ -118,34 +208,65 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C else ..() -/obj/machinery/vending/obj_break(damage_flag) - if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1)) - stat |= BROKEN +/obj/machinery/vending/update_icon_state() + if(stat & BROKEN) icon_state = "[initial(icon_state)]-broken" + set_light(0) + else if(powered()) + icon_state = initial(icon_state) + set_light(1.4) + else + icon_state = "[initial(icon_state)]-off" + set_light(0) - var/dump_amount = 0 - var/found_anything = TRUE - while (found_anything) - found_anything = FALSE - for(var/record in shuffle(product_records)) - var/datum/data/vending_product/R = record - if(R.amount <= 0) //Try to use a record that actually has something to dump. - continue - var/dump_path = R.product_path - if(!dump_path) - continue - R.amount-- - // busting open a vendor will destroy some of the contents - if(found_anything && prob(80)) - continue - var/obj/O = new dump_path(loc) - step(O, pick(GLOB.alldirs)) - found_anything = TRUE - dump_amount++ - if (dump_amount >= 16) - return +/obj/machinery/vending/update_overlays() + . = ..() + if(!light_mask) + return + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) + if(!(stat & BROKEN) && powered()) + SSvis_overlays.add_vis_overlay(src, icon, light_mask, EMISSIVE_LAYER, EMISSIVE_PLANE) + +/obj/machinery/vending/obj_break(damage_flag) + . = ..() + if(!.) + return + + var/dump_amount = 0 + var/found_anything = TRUE + while (found_anything) + found_anything = FALSE + for(var/record in shuffle(product_records)) + var/datum/data/vending_product/R = record + if(R.amount <= 0) //Try to use a record that actually has something to dump. + continue + var/dump_path = R.product_path + if(!dump_path) + continue + R.amount-- + // busting open a vendor will destroy some of the contents + if(found_anything && prob(80)) + continue + + var/obj/O = new dump_path(loc) + step(O, pick(GLOB.alldirs)) + found_anything = TRUE + dump_amount++ + if (dump_amount >= 16) + return + +GLOBAL_LIST_EMPTY(vending_products) +/** + * Build the inventory of the vending machine from it's product and record lists + * + * This builds up a full set of /datum/data/vending_products from the product list of the vending machine type + * Arguments: + * * productlist - the list of products that need to be converted + * * recordlist - the list containing /datum/data/vending_product datums + * * startempty - should we set vending_product record amount from the product list (so it's prefilled at roundstart) + */ /obj/machinery/vending/proc/build_inventory(list/productlist, list/recordlist, start_empty = FALSE) for(var/typepath in productlist) var/amount = productlist[typepath] @@ -154,13 +275,21 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C var/atom/temp = typepath var/datum/data/vending_product/R = new /datum/data/vending_product() + GLOB.vending_products[typepath] = 1 R.name = initial(temp.name) R.product_path = typepath if(!start_empty) R.amount = amount R.max_amount = amount recordlist += R - +/** + * Refill a vending machine from a refill canister + * + * This takes the products from the refill canister and then fills the products,contraband and premium product categories + * + * Arguments: + * * canister - the vending canister we are refilling from + */ /obj/machinery/vending/proc/restock(obj/item/vending_refill/canister) if (!canister.products) canister.products = products.Copy() @@ -172,7 +301,13 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C . += refill_inventory(canister.products, product_records) . += refill_inventory(canister.contraband, hidden_records) . += refill_inventory(canister.premium, coin_records) - +/** + * Refill our inventory from the passed in product list into the record list + * + * Arguments: + * * productlist - list of types -> amount + * * recordlist - existing record datums + */ /obj/machinery/vending/proc/refill_inventory(list/productlist, list/recordlist) . = 0 for(var/R in recordlist) @@ -182,7 +317,11 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C productlist[record.product_path] -= diff record.amount += diff . += diff - +/** + * Set up a refill canister that matches this machines products + * + * This is used when the machine is deconstructed, so the items aren't "lost" + */ /obj/machinery/vending/proc/update_canister() if (!component_parts) return @@ -190,12 +329,14 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C var/obj/item/vending_refill/R = locate() in component_parts if (!R) CRASH("Constructible vending machine did not have a refill canister") - return R.products = unbuild_inventory(product_records) R.contraband = unbuild_inventory(hidden_records) R.premium = unbuild_inventory(coin_records) +/** + * Given a record list, go through and and return a list of type -> amount + */ /obj/machinery/vending/proc/unbuild_inventory(list/recordlist) . = list() for(var/R in recordlist) @@ -209,11 +350,14 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C return TRUE /obj/machinery/vending/wrench_act(mob/living/user, obj/item/I) + ..() if(panel_open) default_unfasten_wrench(user, I, time = 60) return TRUE /obj/machinery/vending/screwdriver_act(mob/living/user, obj/item/I) + if(..()) + return TRUE if(anchored) default_deconstruction_screwdriver(user, icon_state, icon_state, I) cut_overlays() @@ -232,9 +376,6 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C if(coin) to_chat(user, "[src] already has [coin] inserted") return - if(bill) - to_chat(user, "[src] already has [bill] inserted") - return if(!premium.len) to_chat(user, "[src] doesn't have a coin slot.") return @@ -243,41 +384,87 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C coin = I to_chat(user, "You insert [I] into [src].") return - else if(istype(I, /obj/item/stack/spacecash)) - if(coin) - to_chat(user, "[src] already has [coin] inserted") - return - if(bill) - to_chat(user, "[src] already has [bill] inserted") - return - var/obj/item/stack/S = I - if(!premium.len) - to_chat(user, "[src] doesn't have a bill slot.") - return - S.use(1) - bill = new S.type(src, 1) - to_chat(user, "You insert [I] into [src].") - return else if(refill_canister && istype(I, refill_canister)) if (!panel_open) - to_chat(user, "You should probably unscrew the service panel first.") + to_chat(user, "You should probably unscrew the service panel first!") else if (stat & (BROKEN|NOPOWER)) to_chat(user, "[src] does not respond.") else //if the panel is open we attempt to refill the machine var/obj/item/vending_refill/canister = I if(canister.get_part_rating() == 0) - to_chat(user, "[canister] is empty!") + to_chat(user, "[canister] is empty!") else // instantiate canister if needed var/transferred = restock(canister) if(transferred) to_chat(user, "You loaded [transferred] items in [src].") else - to_chat(user, "There's nothing to restock!") + to_chat(user, "There's nothing to restock!") return + + if(compartmentLoadAccessCheck(user) && user.a_intent != INTENT_HARM) + if(canLoadItem(I)) + loadingAttempt(I,user) + updateUsrDialog() //can't put this on the proc above because we spam it below + + if(istype(I, /obj/item/storage/bag)) //trays USUALLY + var/obj/item/storage/T = I + var/loaded = 0 + var/denied_items = 0 + for(var/obj/item/the_item in T.contents) + if(contents.len >= MAX_VENDING_INPUT_AMOUNT) // no more than 30 item can fit inside, legacy from snack vending although not sure why it exists + to_chat(user, "[src]'s compartment is full.") + break + if(canLoadItem(the_item) && loadingAttempt(the_item,user)) + SEND_SIGNAL(T, COMSIG_TRY_STORAGE_TAKE, the_item, src, TRUE) + loaded++ + else + denied_items++ + if(denied_items) + to_chat(user, "[src] refuses some items!") + if(loaded) + to_chat(user, "You insert [loaded] dishes into [src]'s compartment.") + updateUsrDialog() else - return ..() + . = ..() + +/obj/machinery/vending/proc/loadingAttempt(obj/item/I, mob/user) + . = TRUE + if(!user.transferItemToLoc(I, src)) + return FALSE + if(vending_machine_input[format_text(I.name)]) + vending_machine_input[format_text(I.name)]++ + else + vending_machine_input[format_text(I.name)] = 1 + to_chat(user, "You insert [I] into [src]'s input compartment.") + loaded_items++ + +/** + * Is the passed in user allowed to load this vending machines compartments + * + * Arguments: + * * user - mob that is doing the loading of the vending machine + */ +/obj/machinery/vending/proc/compartmentLoadAccessCheck(mob/user) + if(!canload_access_list) + return TRUE + else + var/do_you_have_access = FALSE + var/req_access_txt_holder = req_access_txt + for(var/i in canload_access_list) + req_access_txt = i + if(!allowed(user) && !(obj_flags & EMAGGED) && scan_id) + continue + else + do_you_have_access = TRUE + break //you passed don't bother looping anymore + req_access_txt = req_access_txt_holder // revert to normal (before the proc ran) + if(do_you_have_access) + return TRUE + else + to_chat(user, "[src]'s input compartment blinks red: Access denied.") + return FALSE /obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/W) if(!istype(W)) @@ -297,7 +484,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C else display_parts(user) if(moved) - to_chat(user, "[moved] items restocked.") + to_chat(user, "[moved] items restocked.") W.play_rped_sound() return TRUE @@ -319,188 +506,145 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C return return ..() -/obj/machinery/vending/ui_interact(mob/user) - var/dat = "" +/obj/machinery/vending/ui_base_html(html) + var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/vending) + . = replacetext(html, "", assets.css_tag()) - dat += "

Select an item

" - dat += "
" - if(!product_records.len) - dat += "No product loaded!" - else - var/list/display_records = product_records - if(extended_inventory) - display_records = product_records + hidden_records - if(coin || bill) - display_records = product_records + coin_records - if((coin || bill) && extended_inventory) - display_records = product_records + hidden_records + coin_records - dat += "" - for (var/datum/data/vending_product/R in display_records) - dat += "" - dat += "" - if(R.amount > 0) - dat += "" - else - dat += "" - dat += "" - dat += "
[sanitize(R.name)][R.amount] VendVend
" - dat += "
" - if(premium.len > 0) - dat += "Change Return: " - if (coin || bill) - dat += "[(coin ? coin : "")][(bill ? bill : "")]  Remove" - else - dat += "No money  Remove" - if(istype(src, /obj/machinery/vending/snack)) - dat += "

Chef's Food Selection

" - dat += "
" - for (var/O in dish_quants) - if(dish_quants[O] > 0) - var/N = dish_quants[O] - dat += "Dispense " - dat += "[capitalize(O)]: [N]
" - dat += "
" +/obj/machinery/vending/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open, 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) + var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/vending) + assets.send(user) + ui = new(user, src, ui_key, "vending", name, 450, 600, master_ui, state) + ui.open() - var/datum/browser/popup = new(user, "vending", (name)) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open() +/obj/machinery/vending/ui_static_data(mob/user) + . = list() + .["product_records"] = list() + for (var/datum/data/vending_product/R in product_records) + var/list/data = list( + path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), + name = R.name, + max_amount = R.max_amount, + ref = REF(R) + ) + .["product_records"] += list(data) + .["coin_records"] = list() + for (var/datum/data/vending_product/R in coin_records) + var/list/data = list( + path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), + name = R.name, + max_amount = R.max_amount, + ref = REF(R), + premium = TRUE + ) + .["coin_records"] += list(data) + .["hidden_records"] = list() + for (var/datum/data/vending_product/R in hidden_records) + var/list/data = list( + path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), + name = R.name, + max_amount = R.max_amount, + ref = REF(R), + premium = TRUE + ) + .["hidden_records"] += list(data) -/obj/machinery/vending/proc/GetIconForProduct(datum/data/vending_product/P) - if(vending_cache[P.product_path]) - return vending_cache[P.product_path] - var/product = new P.product_path() - vending_cache[P.product_path] = icon2base64(getFlatIcon(product, no_anim = TRUE)) - qdel(product) - return vending_cache[P.product_path] +/obj/machinery/vending/ui_data(mob/user) + . = list() + .["stock"] = list() + for(var/datum/data/vending_product/R in product_records + coin_records + hidden_records) + .["stock"][R.name] = R.amount + .["extended_inventory"] = extended_inventory + .["coin"] = coin -/obj/machinery/vending/Topic(href, href_list) - if(..()) +/obj/machinery/vending/ui_act(action, params) + . = ..() + if(.) return - - if(href_list["remove_coin"]) - if(!(coin || bill)) - to_chat(usr, "There is no money in this machine.") - return - if(coin) - usr.put_in_hands(coin) - to_chat(usr, "You remove [coin] from [src].") - coin = null - if(bill) - usr.put_in_hands(bill) - to_chat(usr, "You remove [bill] from [src].") - bill = null - - - usr.set_machine(src) - - if((href_list["dispense"]) && (vend_ready)) - var/N = href_list["dispense"] - if(dish_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. - return - vend_ready = 0 - use_power(5) - - dish_quants[N] = max(dish_quants[N] - 1, 0) - for(var/obj/O in contents) - if(O.name == N) - O.forceMove(drop_location()) - break - vend_ready = 1 - updateUsrDialog() - return - - if((href_list["vend"]) && (vend_ready)) - if(panel_open) - to_chat(usr, "The vending machine cannot dispense products while its service panel is open!") - return - - if((!allowed(usr)) && !(obj_flags & EMAGGED) && scan_id) //For SECURE VENDING MACHINES YEAH - to_chat(usr, "Access denied." ) - flick(icon_deny,src) - return - - vend_ready = 0 //One thing at a time!! - - var/datum/data/vending_product/R = locate(href_list["vend"]) - if(!R || !istype(R) || !R.product_path) - vend_ready = 1 - return - - if(R in hidden_records) - if(!extended_inventory) - vend_ready = 1 + switch(action) + if("vend") + . = TRUE + if(!vend_ready) return - else if(R in coin_records) - if(!(coin || bill)) - to_chat(usr, "You need to insert money to get this item!") - vend_ready = 1 + if(panel_open) + to_chat(usr, "The vending machine cannot dispense products while its service panel is open!") return - if(coin && coin.string_attached) - if(prob(50)) - if(usr.CanReach(src)) - if(usr.put_in_hands(coin)) - to_chat(usr, "You successfully pull [coin] out before [src] could swallow it.") - coin = null - else - to_chat(usr, "You couldn't pull [coin] out because your hands are full!") - QDEL_NULL(coin) - else + if((!allowed(usr)) && !(obj_flags & EMAGGED) && scan_id) //For SECURE VENDING MACHINES YEAH + to_chat(usr, "Access denied." ) + flick(icon_deny,src) + return + vend_ready = FALSE //One thing at a time!! + var/datum/data/vending_product/R = locate(params["ref"]) + if(!R || !istype(R) || !R.product_path) + vend_ready = TRUE + return + if(R in hidden_records) + if(!extended_inventory) + vend_ready = TRUE + return + else if(R in coin_records) + if(!(coin)) + to_chat(usr, "You need to a coin to get this item!") + vend_ready = TRUE + return + if(coin && coin.string_attached) + if(!prob(50)) + to_chat(usr, "You weren't able to pull [coin] out fast enough, the machine ate it, string and all!") + QDEL_NULL(coin) + return + if(!usr.CanReach(src)) to_chat(usr, "You successfully pull [coin] out of [src] to the floor.") coin = null - else - to_chat(usr, "You weren't able to pull [coin] out fast enough, the machine ate it, string and all!") - QDEL_NULL(coin) - else + if(!usr.put_in_hands(coin)) + to_chat(usr, "You couldn't pull [coin] out because your hands are full!") + QDEL_NULL(coin) + to_chat(usr, "You successfully pull [coin] out before [src] could swallow it.") + coin = null QDEL_NULL(coin) - QDEL_NULL(bill) - - else if (!(R in product_records)) - vend_ready = 1 - message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!") - return - - if (R.amount <= 0) - to_chat(usr, "Sold out.") - vend_ready = 1 - return - else - R.amount-- - - if(((last_reply + 200) <= world.time) && vend_reply) - speak(vend_reply) - last_reply = world.time - - use_power(5) - if(icon_vend) //Show the vending animation if needed - flick(icon_vend,src) - var/vended = new R.product_path(get_turf(src)) - if(usr.CanReach(src)) - if(usr.put_in_hands(vended)) + else if(!(R in product_records)) + vend_ready = TRUE + message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!") + return + if(R.amount <= 0) + to_chat(usr, "Sold out.") + vend_ready = TRUE + return + else + R.amount-- + if(((last_reply + 200) <= world.time) && vend_reply) + speak(vend_reply) + last_reply = world.time + use_power(5) + if(icon_vend) //Show the vending animation if needed + flick(icon_vend,src) + var/vended = new R.product_path(get_turf(src)) + if(usr.CanReach(src) && usr.put_in_hands(vended)) to_chat(usr, "You take [R.name] out of the slot.") else to_chat(usr, "[capitalize(R.name)] falls onto the floor!") - else - to_chat(usr, "[capitalize(R.name)] falls onto the floor!") - SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[R.product_path]")) - vend_ready = 1 - - updateUsrDialog() - return - - else if(href_list["togglevoice"] && panel_open) - shut_up = !shut_up - - updateUsrDialog() - + + SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[R.product_path]")) + vend_ready = TRUE + return + if("takeoutcoin") + usr.put_in_hands(coin) + to_chat(usr, "You remove [coin] from [src].") + coin = null + return + + if("togglevoice") + if(panel_open) + shut_up = !shut_up + /obj/machinery/vending/process() if(stat & (BROKEN|NOPOWER)) - return + return PROCESS_KILL if(!active) return - if(seconds_electrified > 0) + if(seconds_electrified > MACHINE_NOT_ELECTRIFIED) seconds_electrified-- //Pitch to the people! Really sell it! @@ -511,7 +655,14 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C if(shoot_inventory && prob(shoot_inventory_chance)) throw_item() - +/** + * Speak the given message verbally + * + * Checks if the machine is powered and the message exists + * + * Arguments: + * * message - the message to speak + */ /obj/machinery/vending/proc/speak(message) if(stat & (BROKEN|NOPOWER)) return @@ -521,47 +672,61 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C say(message) /obj/machinery/vending/power_change() - if(stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" - else - if(powered()) - icon_state = initial(icon_state) - stat &= ~NOPOWER - else - icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER + . = ..() + if(powered()) + START_PROCESSING(SSmachines, src) //Somebody cut an important wire and now we're following a new definition of "pitch." +/** + * Throw an item from our internal inventory out in front of us + * + * This is called when we are hacked, it selects a random product from the records that has an amount > 0 + * This item is then created and tossed out in front of us with a visible message + */ /obj/machinery/vending/proc/throw_item() var/obj/throw_item = null - var/mob/living/target = locate() in view(7,src) + var/mob/living/target = locate() in view(7, src) if(!target) - return 0 - + return FALSE for(var/datum/data/vending_product/R in shuffle(product_records)) if(R.amount <= 0) //Try to use a record that actually has something to dump. continue var/dump_path = R.product_path if(!dump_path) continue - R.amount-- throw_item = new dump_path(loc) break if(!throw_item) - return 0 + return FALSE pre_throw(throw_item) throw_item.throw_at(target, 16, 3) visible_message("[src] launches [throw_item] at [target]!") - return 1 - + return TRUE +/** + * A callback called before an item is tossed out + * + * Override this if you need to do any special case handling + * + * Arguments: + * * I - obj/item being thrown + */ /obj/machinery/vending/proc/pre_throw(obj/item/I) return - -/obj/machinery/vending/proc/shock(mob/user, prb) - if(stat & (BROKEN|NOPOWER)) // unpowered, no shock +/** + * Shock the passed in user + * + * This checks we have power and that the passed in prob is passed, then generates some sparks + * and calls electrocute_mob on the user + * + * Arguments: + * * user - the user to shock + * * prb - probability the shock happens + */ +/obj/machinery/vending/proc/shock(mob/living/user, prb) + if(!istype(user) || stat & (BROKEN|NOPOWER)) // unpowered, no shock return FALSE if(!prob(prb)) return FALSE @@ -571,6 +736,15 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C return TRUE else return FALSE +/** + * Are we able to load the item passed in + * + * Arguments: + * * I - the item being loaded + * * user - the user doing the loading + */ +/obj/machinery/vending/proc/canLoadItem(obj/item/I, mob/user) + return FALSE /obj/machinery/vending/onTransitZ() return diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm index 4917bd3dba..ca774ed1f6 100644 --- a/code/modules/vore/eating/belly_obj.dm +++ b/code/modules/vore/eating/belly_obj.dm @@ -558,7 +558,6 @@ to_chat(R,"Your attempt to escape [lowertext(name)] has failed!") to_chat(owner,"The attempt to escape from your [lowertext(name)] has failed!") return - return var/struggle_outer_message = pick(struggle_messages_outside) var/struggle_user_message = pick(struggle_messages_inside) diff --git a/code/modules/vore/trycatch.dm b/code/modules/vore/trycatch.dm index 2adf6e0cf6..d4b1ac2c05 100644 --- a/code/modules/vore/trycatch.dm +++ b/code/modules/vore/trycatch.dm @@ -16,15 +16,14 @@ The proc you're attemping should return nonzero values on success. try if(!callon || !procname) CRASH("attempt_vr: Invalid obj/proc: [callon]/[procname]") - return 0 var/result = call(callon,procname)(arglist(args)) return result catch(var/exception/e) - CRASH("attempt_vr runtimed when calling [procname] on [callon].") - CRASH("attempt_vr catch: [e] on [e.file]:[e.line]") + stack_trace("attempt_vr runtimed when calling [procname] on [callon].") + stack_trace("attempt_vr catch: [e] on [e.file]:[e.line]") return 0 /* @@ -46,17 +45,16 @@ The hooks you're calling should return nonzero values on success. var/hook_path = text2path("/hook/[hook]") if(!hook_path) CRASH("hook_vr: Invalid hook '/hook/[hook]' called.") - return 0 var/caller = new hook_path var/status = 1 for(var/P in typesof("[hook_path]/proc")) if(!call(caller, P)(arglist(args))) - CRASH("hook_vr: Hook '[P]' failed or runtimed.") + stack_trace("hook_vr: Hook '[P]' failed or runtimed.") status = 0 return status catch(var/exception/e) - CRASH("hook_vr itself failed or runtimed. Exception below.") - CRASH("hook_vr catch: [e] on [e.file]:[e.line]") \ No newline at end of file + stack_trace("hook_vr itself failed or runtimed. Exception below.") + stack_trace("hook_vr catch: [e] on [e.file]:[e.line]") diff --git a/config/config.txt b/config/config.txt index fd5dc968fb..35af0e848b 100644 --- a/config/config.txt +++ b/config/config.txt @@ -510,13 +510,16 @@ DEFAULT_VIEW 21x15 ### FAIL2TOPIC: ### Automated IP bans for world/Topic() spammers +### NOTE FOR WINDOWS HOSTS: This requires you to be running dreamdaemon as an administrator for it to work at all. TGS3 handles this automatically, and honestly there's no reason not to be using TGS3 if you're hosting on Windows. +### NOTE FOR LINUX HOSTS: This requires manual setup of iptables. Beware that improper configuration of this can and will irreversibly fuck up a server, so please don't tinker with it if you don't know what you're doing. ## Enabled -FAIL2TOPIC_ENABLED +#FAIL2TOPIC_ENABLED ## Minimum wait time in deciseconds between valid requests FAIL2TOPIC_RATE_LIMIT 10 ## Number of requests after breaching rate limit that triggers a ban FAIL2TOPIC_MAX_FAILS 5 ## Firewall rule name used on physical server +## FOR LINUX HOSTS: This is used as the chain name. The iptables chain doesn't get created or hooked up to INPUT automatically, so you'll have to get that set up yourself. Recommended name: BYOND FAIL2TOPIC_RULE_NAME _dd_fail2topic ## Enable automatic profiling - Byond 513.1506 and newer only. diff --git a/config/game_options.txt b/config/game_options.txt index c3930fd325..8c48ac6ede 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -620,3 +620,16 @@ BREASTS_CUPS_PREFS e ## Minimum and maximum limits for penis length from the character creation menu. PENIS_MIN_INCHES_PREFS 1 PENIS_MAX_INCHES_PREFS 20 + +## Body size configs, the feature will be disabled if both min and max have the same value. +BODY_SIZE_MIN 1 +BODY_SIZE_MAX 1 + +## Pun-Pun movement slowdown given to characters with a body size smaller than this value, +## to compensate for their smaller hitbox. +## To disable, just make sure the value is lower than 'body_size_min' +THRESHOLD_BODY_SIZE_SLOWDOWN 0.85 + +## Multiplier used in the smaller strides slowdown calculation. +## Doesn't apply to floating or crawling mobs. +BODY_SIZE_SLOWDOWN_MULTIPLIER 0.25 \ No newline at end of file diff --git a/dependencies.sh b/dependencies.sh index be5a320428..83254509b9 100644 --- a/dependencies.sh +++ b/dependencies.sh @@ -23,4 +23,4 @@ export NODE_VERSION=12 export PHP_VERSION=5.6 # SpacemanDMM git tag -export SPACEMAN_DMM_VERSION=suite-1.3 +export SPACEMAN_DMM_VERSION=suite-1.4 diff --git a/html/changelogs/AutoChangeLog-pr-10732.yml b/html/changelogs/AutoChangeLog-pr-10732.yml new file mode 100644 index 0000000000..8d6746bbd4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10732.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - rscadd: "Traitor chaplains can now become neutered versions of cults." diff --git a/html/changelogs/AutoChangeLog-pr-10891.yml b/html/changelogs/AutoChangeLog-pr-10891.yml new file mode 100644 index 0000000000..cac5c5312d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10891.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - rscadd: "Most crate types can now be made, some costing more do to function over fashion" diff --git a/html/changelogs/AutoChangeLog-pr-10986.yml b/html/changelogs/AutoChangeLog-pr-10986.yml new file mode 100644 index 0000000000..bac7b9692a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10986.yml @@ -0,0 +1,4 @@ +author: "Seris02" +delete-after: True +changes: + - rscadd: "wall walking boots" diff --git a/html/changelogs/AutoChangeLog-pr-11275.yml b/html/changelogs/AutoChangeLog-pr-11275.yml new file mode 100644 index 0000000000..5a3ce31631 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11275.yml @@ -0,0 +1,5 @@ +author: "Ghommie" +delete-after: True +changes: + - rscadd: "Reenabled the swarmers event. Also blacklisted another dozen other machineries and structures that may be critical to the shift or station integrity from swarmers' HUNGER for materials." + - bugfix: "Fixed find_safe_turfs() searching for turfs with concentration of oxygen lower than 16 rather higher." diff --git a/html/changelogs/AutoChangeLog-pr-11379.yml b/html/changelogs/AutoChangeLog-pr-11379.yml new file mode 100644 index 0000000000..319d4b2140 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11379.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - refactor: "refactored polychromic clothing into an element." diff --git a/html/changelogs/AutoChangeLog-pr-11618.yml b/html/changelogs/AutoChangeLog-pr-11618.yml new file mode 100644 index 0000000000..99acbbeef5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11618.yml @@ -0,0 +1,12 @@ +author: "Arturlang" +delete-after: True +changes: + - rscadd: "Adds garlic, a mutation of onions" + - rscadd: "You can now make garlic necklaces." + - tweak: "Tweaked hunger to be more the same as blood level for bloodsuckers" + - tweak: "Bloodsuckers no longer get zero healing from regenerative cores, the core now heals their wounds but not their blood." + - balance: "Bloodsucker heal is now based a lot more on blood level." + - bugfix: "You can no longer be effectively immortal when fully auged as a bloodsucker." + - bugfix: "Regenerative cores will regain their old names when they are renewed, no more working decayed cores." + - code_imp: "Removes a lot of unnecesiry clutter of comments and tries to make the vars more consistent for bloodsucker code." + - code_imp: "Made the regenerative core use one proc instead of copypasta" diff --git a/html/changelogs/AutoChangeLog-pr-11655.yml b/html/changelogs/AutoChangeLog-pr-11655.yml new file mode 100644 index 0000000000..7acbf5efa7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11655.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - balance: "The crusher's vortex talisman trophy now has a cooldown between each spawned wall." diff --git a/html/changelogs/AutoChangeLog-pr-11697.yml b/html/changelogs/AutoChangeLog-pr-11697.yml new file mode 100644 index 0000000000..d8026366cb --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11697.yml @@ -0,0 +1,6 @@ +author: "actioninja" +delete-after: True +changes: + - rscadd: "Washing machines now support arbitrary dye color" + - rscadd: "Washing machines now dye nearly every item." + - refactor: "lots of backend changes to clothing overlays, report any issues" diff --git a/html/changelogs/AutoChangeLog-pr-11807.yml b/html/changelogs/AutoChangeLog-pr-11807.yml new file mode 100644 index 0000000000..be368dc57a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11807.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - code_imp: "datum/pipeline return_air stack trace now gives a reference so it's actually marginally useful if caught in round." diff --git a/html/changelogs/AutoChangeLog-pr-11809.yml b/html/changelogs/AutoChangeLog-pr-11809.yml new file mode 100644 index 0000000000..92c882825f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11809.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - rscadd: "Volumetric storage is here." diff --git a/html/changelogs/AutoChangeLog-pr-11811.yml b/html/changelogs/AutoChangeLog-pr-11811.yml new file mode 100644 index 0000000000..010a0caa86 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11811.yml @@ -0,0 +1,6 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Liver failure is back!" + - tweak: "standarized a few (prefs off) side effects from enlargment chems on livers to do organ damage instead without the blood volume whackiness." + - tweak: "High liver damage now slows mobs down." diff --git a/html/changelogs/AutoChangeLog-pr-11812.yml b/html/changelogs/AutoChangeLog-pr-11812.yml new file mode 100644 index 0000000000..ca452b1d23 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11812.yml @@ -0,0 +1,4 @@ +author: "Auris456852" +delete-after: True +changes: + - rscadd: "Added printer sound for admins that plays when someone messages Centcomm or the Syndicate. Just like RP!" diff --git a/html/changelogs/AutoChangeLog-pr-11814.yml b/html/changelogs/AutoChangeLog-pr-11814.yml new file mode 100644 index 0000000000..3cb85d8668 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11814.yml @@ -0,0 +1,5 @@ +author: "kappa-sama" +delete-after: True +changes: + - balance: "doubles the Stam damage of nonlethal krav stompers" + - bugfix: "no longer Krav Maga stomp people that are standing" diff --git a/html/changelogs/AutoChangeLog-pr-11816.yml b/html/changelogs/AutoChangeLog-pr-11816.yml new file mode 100644 index 0000000000..8ca4da37de --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11816.yml @@ -0,0 +1,4 @@ +author: "necromanceranne" +delete-after: True +changes: + - bugfix: "Sleeping Carp and Rising Bass now dodge. Again." diff --git a/html/changelogs/AutoChangeLog-pr-11817.yml b/html/changelogs/AutoChangeLog-pr-11817.yml new file mode 100644 index 0000000000..9d9e0a779b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11817.yml @@ -0,0 +1,5 @@ +author: "Putnam3145" +delete-after: True +changes: + - rscadd: "Latejoin changelings for dynamic" + - bugfix: "Average threat calculation works now" diff --git a/html/changelogs/AutoChangeLog-pr-11819.yml b/html/changelogs/AutoChangeLog-pr-11819.yml new file mode 100644 index 0000000000..6619f26aba --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11819.yml @@ -0,0 +1,5 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Wizard robes & co work again now." + - bugfix: "Fixed some spell casting message spam." diff --git a/html/changelogs/AutoChangeLog-pr-11823.yml b/html/changelogs/AutoChangeLog-pr-11823.yml new file mode 100644 index 0000000000..b4ba01d44b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11823.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - bugfix: "Contamination is back." diff --git a/html/changelogs/AutoChangeLog-pr-11824.yml b/html/changelogs/AutoChangeLog-pr-11824.yml new file mode 100644 index 0000000000..2b91fc5564 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11824.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "fixed yet another few airless issues with the space hermit ruin." diff --git a/html/changelogs/AutoChangeLog-pr-11826.yml b/html/changelogs/AutoChangeLog-pr-11826.yml new file mode 100644 index 0000000000..4ffe43239d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11826.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - refactor: "Backend body size preferences." diff --git a/html/changelogs/AutoChangeLog-pr-11828.yml b/html/changelogs/AutoChangeLog-pr-11828.yml new file mode 100644 index 0000000000..067963046f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11828.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed toilet cistern loot spawning on the floor." diff --git a/html/changelogs/AutoChangeLog-pr-11829.yml b/html/changelogs/AutoChangeLog-pr-11829.yml new file mode 100644 index 0000000000..5cf966cd02 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11829.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed a whacky miniature cell duping issue." diff --git a/html/changelogs/AutoChangeLog-pr-11830.yml b/html/changelogs/AutoChangeLog-pr-11830.yml new file mode 100644 index 0000000000..79d3e7656f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11830.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed the phantom thief component, again." diff --git a/html/changelogs/AutoChangeLog-pr-11831.yml b/html/changelogs/AutoChangeLog-pr-11831.yml new file mode 100644 index 0000000000..22b0e71692 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11831.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "fixed a few floaty sprite accessories." diff --git a/html/changelogs/AutoChangeLog-pr-11834.yml b/html/changelogs/AutoChangeLog-pr-11834.yml new file mode 100644 index 0000000000..05d1b245b1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11834.yml @@ -0,0 +1,5 @@ +author: "Bhijn" +delete-after: True +changes: + - server: "Fail2Topic now supports Linux. Do beware that this requires some sysop experience to properly set up!" + - config: "Fail2Topic is now disabled by default, and the out-of-the-box config files have been updated to be a little more detailed." diff --git a/html/changelogs/AutoChangeLog-pr-11838.yml b/html/changelogs/AutoChangeLog-pr-11838.yml new file mode 100644 index 0000000000..464448c138 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11838.yml @@ -0,0 +1,4 @@ +author: "kappa-sama" +delete-after: True +changes: + - rscdel: "normies can no longer steal circuit codes" diff --git a/icons/mob/accessories.dmi b/icons/mob/accessories.dmi deleted file mode 100644 index cda7cca404..0000000000 Binary files a/icons/mob/accessories.dmi and /dev/null differ diff --git a/icons/mob/actions/backgrounds.dmi b/icons/mob/actions/backgrounds.dmi index 3697fe4ff5..07839588ce 100644 Binary files a/icons/mob/actions/backgrounds.dmi and b/icons/mob/actions/backgrounds.dmi differ diff --git a/icons/mob/clothing/accessories.dmi b/icons/mob/clothing/accessories.dmi new file mode 100644 index 0000000000..c13b6a50bc Binary files /dev/null and b/icons/mob/clothing/accessories.dmi differ diff --git a/icons/mob/back.dmi b/icons/mob/clothing/back.dmi similarity index 100% rename from icons/mob/back.dmi rename to icons/mob/clothing/back.dmi diff --git a/icons/mob/belt.dmi b/icons/mob/clothing/belt.dmi similarity index 100% rename from icons/mob/belt.dmi rename to icons/mob/clothing/belt.dmi diff --git a/icons/mob/belt_mirror.dmi b/icons/mob/clothing/belt_mirror.dmi similarity index 100% rename from icons/mob/belt_mirror.dmi rename to icons/mob/clothing/belt_mirror.dmi diff --git a/icons/mob/custom_w.dmi b/icons/mob/clothing/custom_w.dmi similarity index 100% rename from icons/mob/custom_w.dmi rename to icons/mob/clothing/custom_w.dmi diff --git a/icons/mob/eyes.dmi b/icons/mob/clothing/eyes.dmi similarity index 100% rename from icons/mob/eyes.dmi rename to icons/mob/clothing/eyes.dmi diff --git a/icons/mob/feet.dmi b/icons/mob/clothing/feet.dmi similarity index 79% rename from icons/mob/feet.dmi rename to icons/mob/clothing/feet.dmi index 578970a21c..1e09dce605 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/clothing/feet.dmi differ diff --git a/icons/mob/feet_digi.dmi b/icons/mob/clothing/feet_digi.dmi similarity index 57% rename from icons/mob/feet_digi.dmi rename to icons/mob/clothing/feet_digi.dmi index fbc105b634..626c67a71c 100644 Binary files a/icons/mob/feet_digi.dmi and b/icons/mob/clothing/feet_digi.dmi differ diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi new file mode 100644 index 0000000000..74aabf6021 Binary files /dev/null and b/icons/mob/clothing/hands.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/clothing/head.dmi similarity index 95% rename from icons/mob/head.dmi rename to icons/mob/clothing/head.dmi index c499c236e3..f2ea9fa55d 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/clothing/head.dmi differ diff --git a/icons/mob/head_muzzled.dmi b/icons/mob/clothing/head_muzzled.dmi similarity index 100% rename from icons/mob/head_muzzled.dmi rename to icons/mob/clothing/head_muzzled.dmi diff --git a/icons/mob/mask.dmi b/icons/mob/clothing/mask.dmi similarity index 100% rename from icons/mob/mask.dmi rename to icons/mob/clothing/mask.dmi diff --git a/icons/mob/mask_muzzled.dmi b/icons/mob/clothing/mask_muzzled.dmi similarity index 100% rename from icons/mob/mask_muzzled.dmi rename to icons/mob/clothing/mask_muzzled.dmi diff --git a/icons/mob/clothing/neck.dmi b/icons/mob/clothing/neck.dmi new file mode 100644 index 0000000000..78073222ca Binary files /dev/null and b/icons/mob/clothing/neck.dmi differ diff --git a/icons/mob/restraints.dmi b/icons/mob/clothing/restraints.dmi similarity index 100% rename from icons/mob/restraints.dmi rename to icons/mob/clothing/restraints.dmi diff --git a/icons/mob/suit.dmi b/icons/mob/clothing/suit.dmi similarity index 99% rename from icons/mob/suit.dmi rename to icons/mob/clothing/suit.dmi index 195e4ecd67..a2ea222a68 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/clothing/suit.dmi differ diff --git a/icons/mob/suit_digi.dmi b/icons/mob/clothing/suit_digi.dmi similarity index 99% rename from icons/mob/suit_digi.dmi rename to icons/mob/clothing/suit_digi.dmi index 67ad9f7e1a..5287bac43c 100644 Binary files a/icons/mob/suit_digi.dmi and b/icons/mob/clothing/suit_digi.dmi differ diff --git a/icons/mob/taur_canine.dmi b/icons/mob/clothing/taur_canine.dmi similarity index 100% rename from icons/mob/taur_canine.dmi rename to icons/mob/clothing/taur_canine.dmi diff --git a/icons/mob/taur_hooved.dmi b/icons/mob/clothing/taur_hooved.dmi similarity index 100% rename from icons/mob/taur_hooved.dmi rename to icons/mob/clothing/taur_hooved.dmi diff --git a/icons/mob/taur_naga.dmi b/icons/mob/clothing/taur_naga.dmi similarity index 100% rename from icons/mob/taur_naga.dmi rename to icons/mob/clothing/taur_naga.dmi diff --git a/icons/mob/underwear.dmi b/icons/mob/clothing/underwear.dmi similarity index 100% rename from icons/mob/underwear.dmi rename to icons/mob/clothing/underwear.dmi diff --git a/icons/mob/clothing/uniform.dmi b/icons/mob/clothing/uniform.dmi new file mode 100644 index 0000000000..4485a9a5f8 Binary files /dev/null and b/icons/mob/clothing/uniform.dmi differ diff --git a/icons/mob/uniform_digi.dmi b/icons/mob/clothing/uniform_digi.dmi similarity index 99% rename from icons/mob/uniform_digi.dmi rename to icons/mob/clothing/uniform_digi.dmi index 80e8f80b94..6827581b85 100644 Binary files a/icons/mob/uniform_digi.dmi and b/icons/mob/clothing/uniform_digi.dmi differ diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi deleted file mode 100644 index e7068a1854..0000000000 Binary files a/icons/mob/hands.dmi and /dev/null differ diff --git a/icons/mob/neck.dmi b/icons/mob/neck.dmi deleted file mode 100644 index de59a136d9..0000000000 Binary files a/icons/mob/neck.dmi and /dev/null differ diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index ea946f60d9..60c413c372 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi deleted file mode 100644 index 1845e75d26..0000000000 Binary files a/icons/mob/uniform.dmi and /dev/null differ diff --git a/icons/obj/bodybag.dmi b/icons/obj/bodybag.dmi index 7fcc193ad6..c3267d3fc9 100644 Binary files a/icons/obj/bodybag.dmi and b/icons/obj/bodybag.dmi differ diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index 76094938e8..aea15e2e39 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/clothing/cloaks.dmi b/icons/obj/clothing/cloaks.dmi index dd1ae7d727..6f4de62cc0 100644 Binary files a/icons/obj/clothing/cloaks.dmi and b/icons/obj/clothing/cloaks.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index e937842275..d53f53c029 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 07d9c8cee6..2e0906ea20 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/neck.dmi b/icons/obj/clothing/neck.dmi index 0bdaa36e62..c4c9c94f48 100644 Binary files a/icons/obj/clothing/neck.dmi and b/icons/obj/clothing/neck.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index bd8d52a1e6..c4e000b700 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 530cd61e6f..607c26bb62 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index edcd2ff9b6..dfebe38155 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/glass_ware.dmi b/icons/obj/glass_ware.dmi new file mode 100644 index 0000000000..7b720836cc Binary files /dev/null and b/icons/obj/glass_ware.dmi differ diff --git a/icons/obj/guns/energy.dmi b/icons/obj/guns/energy.dmi index ba8111bb00..e54f55ed46 100644 Binary files a/icons/obj/guns/energy.dmi and b/icons/obj/guns/energy.dmi differ diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi index 712ea11a3b..c93865ca77 100644 Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi index e746d8f43d..c7c31581f3 100644 Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi index 43e231cbab..62843e3f54 100644 Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi index ace24db5ff..a647bebd57 100644 Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ diff --git a/icons/turf/mining.dmi b/icons/turf/mining.dmi index 6561438228..335cff453e 100644 Binary files a/icons/turf/mining.dmi and b/icons/turf/mining.dmi differ diff --git a/icons/turf/smoothrocks.dmi b/icons/turf/smoothrocks.dmi index 20314cff5b..ba2bbce955 100644 Binary files a/icons/turf/smoothrocks.dmi and b/icons/turf/smoothrocks.dmi differ diff --git a/modular_citadel/code/game/objects/items/devices/radio/shockcollar.dm b/modular_citadel/code/game/objects/items/devices/radio/shockcollar.dm index 44b8067876..6c9f12a852 100644 --- a/modular_citadel/code/game/objects/items/devices/radio/shockcollar.dm +++ b/modular_citadel/code/game/objects/items/devices/radio/shockcollar.dm @@ -2,7 +2,7 @@ name = "shock collar" desc = "A reinforced metal collar. It seems to have some form of wiring near the front. Strange.." icon = 'modular_citadel/icons/obj/clothing/cit_neck.dmi' - alternate_worn_icon = 'modular_citadel/icons/mob/citadel/neck.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/citadel/neck.dmi' icon_state = "shockcollar" item_state = "shockcollar" body_parts_covered = NECK diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index 47a994326f..8fda73b199 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -364,11 +364,10 @@ if(ishuman(src) && dna.species.id == "human") dna.features["genitals_use_skintone"] = TRUE dna.species.use_skintones = TRUE - if(MUTCOLORS) - if(src.dna.species.fixed_mut_color) - dna.features["cock_color"] = "[dna.species.fixed_mut_color]" - dna.features["breasts_color"] = "[dna.species.fixed_mut_color]" - return + if(src.dna.species.fixed_mut_color) + dna.features["cock_color"] = "[dna.species.fixed_mut_color]" + dna.features["breasts_color"] = "[dna.species.fixed_mut_color]" + return //So people who haven't set stuff up don't get rainbow surprises. dna.features["cock_color"] = "[dna.features["mcolor"]]" dna.features["breasts_color"] = "[dna.features["mcolor"]]" diff --git a/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm b/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm index 6bbe947f54..1cea2dd916 100644 --- a/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm +++ b/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm @@ -23,13 +23,13 @@ icon_state = "knotted" name = "Knotted" taur_icon = 'modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi' - taur_dimension_y = 64 + taur_dimension_x = 64 /datum/sprite_accessory/penis/flared icon_state = "flared" name = "Flared" taur_icon = 'modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi' - taur_dimension_y = 64 + taur_dimension_x = 64 /datum/sprite_accessory/penis/barbknot icon_state = "barbknot" @@ -39,7 +39,7 @@ icon_state = "tapered" name = "Tapered" taur_icon = 'modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi' - taur_dimension_y = 64 + taur_dimension_x = 64 /datum/sprite_accessory/penis/tentacle icon_state = "tentacle" diff --git a/modular_citadel/code/modules/clothing/neck.dm b/modular_citadel/code/modules/clothing/neck.dm index 20324516f6..f57e2ae530 100644 --- a/modular_citadel/code/modules/clothing/neck.dm +++ b/modular_citadel/code/modules/clothing/neck.dm @@ -7,7 +7,7 @@ icon = 'modular_citadel/icons/obj/clothing/cit_neck.dmi' item_state = "undertale" icon_state = "undertale" - alternate_worn_icon = 'modular_citadel/icons/mob/clothing/necks.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/clothing/necks.dmi' resistance_flags = FIRE_PROOF actions_types = list(/datum/action/item_action/zanderlocket) var/toggled = FALSE diff --git a/modular_citadel/code/modules/clothing/suits/polychromic_cloaks.dm b/modular_citadel/code/modules/clothing/suits/polychromic_cloaks.dm deleted file mode 100644 index ade6cee3ba..0000000000 --- a/modular_citadel/code/modules/clothing/suits/polychromic_cloaks.dm +++ /dev/null @@ -1,40 +0,0 @@ -/obj/item/clothing/neck/cloak/polychromic //enables all three overlays to reduce copypasta and defines basic stuff - name = "polychromic cloak" - desc = "For when you want to show off your horrible colour coordination skills." - icon = 'modular_citadel/icons/polyclothes/item/neck.dmi' - alternate_worn_icon = 'modular_citadel/icons/polyclothes/mob/neck.dmi' - icon_state = "polyce" - item_color = "polyce" - item_state = "qmcloak" - hasprimary = TRUE - hassecondary = TRUE - hastertiary = TRUE - primary_color = "#FFFFFF" //RGB in hexcode - secondary_color = "#FFFFFF" - tertiary_color = "#808080" - -/obj/item/clothing/neck/cloak/polychromic/worn_overlays(isinhands, icon_file, style_flags = NONE) //this is where the main magic happens. Also mandates that ALL polychromic stuff MUST USE alternate_worn_icon - . = ..() - if(hasprimary | hassecondary | hastertiary) - if(!isinhands) //prevents the worn sprites from showing up if you're just holding them - if(hasprimary) //checks if overlays are enabled - var/mutable_appearance/primary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-primary") //automagical sprite selection - primary_worn.color = primary_color //colors the overlay - . += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite. - if(hassecondary) - var/mutable_appearance/secondary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-secondary") - secondary_worn.color = secondary_color - . += secondary_worn - if(hastertiary) - var/mutable_appearance/tertiary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-tertiary") - tertiary_worn.color = tertiary_color - . += tertiary_worn - -/obj/item/clothing/neck/cloak/polychromic/polyce //DONATOR ITEM - name = "polychromic embroidered cloak" - desc = "A fancy cloak embroidered with polychromatic thread in a pattern that reminds one of the wielders of unlimited power." - icon_state = "polyce" - item_color = "polyce" - primary_color = "#808080" //RGB in hexcode - secondary_color = "#8CC6FF" - tertiary_color = "#FF3535" \ No newline at end of file diff --git a/modular_citadel/code/modules/clothing/suits/suits.dm b/modular_citadel/code/modules/clothing/suits/suits.dm index 4b9dd131ca..25b0c120e5 100644 --- a/modular_citadel/code/modules/clothing/suits/suits.dm +++ b/modular_citadel/code/modules/clothing/suits/suits.dm @@ -8,7 +8,7 @@ /obj/item/clothing/suit/armor/hos/trenchcoat/cloak name = "armored trenchcloak" desc = "A trenchcoat enchanced with a special lightweight kevlar. This one appears to be designed to be draped over one's shoulders rather than worn normally.." - alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/citadel/suit.dmi' icon_state = "hostrench" item_state = "hostrench" mutantrace_variation = NONE diff --git a/modular_citadel/code/modules/clothing/trek.dm b/modular_citadel/code/modules/clothing/trek.dm index c6b0b80f22..b4ec9fbd61 100644 --- a/modular_citadel/code/modules/clothing/trek.dm +++ b/modular_citadel/code/modules/clothing/trek.dm @@ -15,7 +15,7 @@ desc = "The overcoat worn by all officers of the 2380s." icon = 'modular_citadel/icons/obj/clothing/trek_item_icon.dmi' icon_state = "trek_ds9_coat" - alternate_worn_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi' item_state = "trek_ds9_coat" body_parts_covered = CHEST|GROIN|ARMS mutantrace_variation = NONE @@ -44,7 +44,7 @@ name = "Federation Uniform Jacket" desc = "A uniform jacket from the United Federation. Set phasers to awesome." icon = 'modular_citadel/icons/obj/clothing/trek_item_icon.dmi' - alternate_worn_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi' icon_state = "fedcoat" item_state = "fedcoat" mutantrace_variation = NONE @@ -110,7 +110,7 @@ name = "Modern Federation Uniform Jacket" desc = "A modern uniform jacket from the United Federation." icon = 'modular_citadel/icons/obj/clothing/trek_item_icon.dmi' - alternate_worn_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi' icon_state = "fedmodern" item_state = "fedmodern" body_parts_covered = CHEST|GROIN|ARMS @@ -142,7 +142,7 @@ desc = "An officer's cap that demands discipline from the one who wears it." icon = 'modular_citadel/icons/obj/clothing/trek_item_icon.dmi' icon_state = "fedcapofficer" - alternate_worn_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi' item_state = "fedcapofficer" //Variants diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm index 62145616ad..bd377d6081 100644 --- a/modular_citadel/code/modules/custom_loadout/custom_items.dm +++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm @@ -26,7 +26,7 @@ desc = "The design on this seems a little too familiar." icon = 'icons/obj/custom.dmi' icon_state = "infcloak" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "infcloak" w_class = WEIGHT_CLASS_SMALL body_parts_covered = CHEST|GROIN|LEGS|ARMS @@ -36,9 +36,8 @@ desc = "A soft black collar that seems to stretch to fit whoever wears it." icon = 'icons/obj/custom.dmi' icon_state = "infcollar" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "infcollar" - item_color = null tagname = null /obj/item/clothing/accessory/medal/steele @@ -46,14 +45,13 @@ desc = "An intricate pendant given to those who help a key member of the Steele Corporation." icon = 'icons/obj/custom.dmi' icon_state = "steele" - item_color = "steele" medaltype = "medal-silver" /obj/item/toy/darksabre name = "Kiara's Sabre" desc = "This blade looks as dangerous as its owner." icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "darksabre" item_state = "darksabre" lefthand_file = 'modular_citadel/icons/mob/inhands/stunsword_left.dmi' @@ -70,7 +68,7 @@ name = "Ornate Sheathe" desc = "An ornate and rather sinister looking sabre sheathe." icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "darksheath" item_state = "darksheath" fitting_swords = list(/obj/item/toy/darksabre) @@ -80,7 +78,7 @@ name = "Dark Armor" desc = "A dark, non-functional piece of armor sporting a red and black finish." icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "darkcarapace" item_state = "darkcarapace" blood_overlay_type = "armor" @@ -107,8 +105,7 @@ icon = 'icons/obj/custom.dmi' icon_state = "zombscarf" desc = "A fashionable collar" - alternate_worn_icon = 'icons/mob/custom_w.dmi' - item_color = "zombscarf" + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' dog_fashion = /datum/dog_fashion/head /obj/item/clothing/suit/toggle/labcoat/mad/red @@ -116,7 +113,7 @@ desc = "An oddly special looking coat." icon = 'icons/obj/custom.dmi' icon_state = "labred" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "labred" mutantrace_variation = NONE @@ -125,7 +122,7 @@ desc = "An oddly special looking coat." icon = 'icons/obj/custom.dmi' icon_state = "labredblack" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "labredblack" mutantrace_variation = NONE @@ -144,7 +141,7 @@ name = "carrot cloak" desc = "A cloak in the shape and color of a carrot!" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "carrotcloak" item_state = "carrotcloak" w_class = WEIGHT_CLASS_SMALL @@ -156,7 +153,7 @@ icon = 'icons/obj/custom.dmi' icon_state = "satchel_carrot" item_state = "satchel_carrot" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' /obj/item/storage/backpack/satchel/carrot/Initialize() . = ..() @@ -179,7 +176,7 @@ icon = 'icons/obj/custom.dmi' icon_state = "festive" item_state = "festive" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' w_class = WEIGHT_CLASS_SMALL body_parts_covered = CHEST|GROIN|LEGS|ARMS @@ -187,7 +184,7 @@ name = "Alboroto Rosa mask" icon = 'icons/obj/custom.dmi' icon_state = "lucharzigfie" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "lucharzigfie" /obj/item/clothing/head/hardhat/reindeer/fluff @@ -195,7 +192,7 @@ desc = "Some fake antlers and a very fake red nose - Sponsored by PWR Game(tm)" icon_state = "hardhat0_reindeer" item_state = "hardhat0_reindeer" - item_color = "reindeer" + hat_type = "reindeer" flags_inv = 0 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0) brightness_on = 0 //luminosity when on @@ -220,7 +217,7 @@ name = "The Hollow heart" desc = "Sometimes things are too much to hide." icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "hheart" item_state = "hheart" flags_inv = HIDEFACE|HIDEFACIALHAIR @@ -230,7 +227,7 @@ desc = "You would swear this was in your nightmares after eating too many veggies." icon = 'icons/obj/custom.dmi' icon_state = "hos-g" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "hos-g" body_parts_covered = CHEST|GROIN|ARMS|LEGS mutantrace_variation = NONE @@ -247,7 +244,7 @@ desc = "Smells like reactor four." icon = 'icons/obj/custom.dmi' item_state = "stalker" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "stalker" /obj/item/reagent_containers/food/drinks/flask/steel @@ -262,7 +259,7 @@ desc = "It's a collar..." icon = 'icons/obj/custom.dmi' icon_state = "petcollar-stripe" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "petcollar-stripe" tagname = null @@ -271,9 +268,8 @@ desc = "Just looking at this makes you want to sing." icon = 'icons/obj/custom.dmi' icon_state = "singer" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "singer" - item_color = "singer" fitted = NO_FEMALE_UNIFORM alternate_worn_layer = ABOVE_SHOES_LAYER can_adjust = 0 @@ -282,7 +278,7 @@ /obj/item/clothing/shoes/sneakers/pink icon = 'icons/obj/custom.dmi' icon_state = "pink" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "pink" mutantrace_variation = NONE @@ -291,13 +287,13 @@ desc = "A neosilk clip-on tie. This one has a black S on the tipping and looks rather unique." icon = 'icons/obj/custom.dmi' icon_state = "bloodredtie" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' /obj/item/clothing/suit/puffydress name = "Puffy Dress" desc = "A formal puffy black and red Victorian dress." icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "puffydress" item_state = "puffydress" body_parts_covered = CHEST|GROIN|LEGS @@ -310,7 +306,7 @@ item_state = "vermillion" body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' mutantrace_variation = NONE /obj/item/clothing/under/sweater/black/naomi @@ -327,7 +323,7 @@ desc = "This cloak doesn't seem too special." icon = 'icons/obj/custom.dmi' icon_state = "wintergreencloak" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "wintergreencloak" w_class = WEIGHT_CLASS_SMALL body_parts_covered = CHEST|GROIN|LEGS|ARMS @@ -343,7 +339,7 @@ desc = "An oddly special looking coat." icon = 'icons/obj/custom.dmi' icon_state = "rdcoat" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' item_state = "rdcoat" mutantrace_variation = NONE @@ -359,7 +355,7 @@ desc = "These strange wings look like they once attached to something... or someone...? Whatever the case, their presence makes you feel uneasy.." icon = 'icons/obj/custom.dmi' icon_state = "devilwings" - alternate_worn_icon = 'modular_citadel/icons/mob/clothing/devilwings64x64.dmi' + mob_overlay_icon = 'modular_citadel/icons/mob/clothing/devilwings64x64.dmi' item_state = "devilwings" worn_x_dimension = 64 worn_y_dimension = 34 @@ -369,14 +365,14 @@ desc = "A truly patriotic form of heroic attire." icon = 'icons/obj/custom.dmi' resistance_flags = FLAMMABLE - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "flagcape" item_state = "flagcape" /obj/item/clothing/shoes/lucky name = "Lucky Jackboots" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' desc = "Comfy Lucky Jackboots with the word Luck on them." item_state = "luckyjack" icon_state = "luckyjack" @@ -385,7 +381,7 @@ /obj/item/clothing/under/custom/lunasune name = "Divine Robes" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' desc = "Heavenly robes of the kitsune Luna Pumpkin,you can feel radiance coming from them." item_state = "Divine_robes" icon_state = "Divine_robes" @@ -394,7 +390,7 @@ /obj/item/clothing/under/custom/leoskimpy name = "Leon's Skimpy Outfit" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' desc = "A rather skimpy outfit." item_state = "shark_cloth" icon_state = "shark_cloth" @@ -403,7 +399,7 @@ /obj/item/clothing/under/custom/mimeoveralls name = "Mime's Overalls" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' desc = "A less-than-traditional mime's attire, completed by a set of dorky-looking overalls." item_state = "moveralls" icon_state = "moveralls" @@ -415,7 +411,7 @@ icon_state = "zuliecloak" item_state = "zuliecloak" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' hoodtype = /obj/item/clothing/head/hooded/cloakhood/zuliecloak body_parts_covered = CHEST|GROIN|ARMS slot_flags = SLOT_WEAR_SUIT | ITEM_SLOT_NECK //it's a cloak. it's cosmetic. so why the hell not? what could possibly go wrong? @@ -427,7 +423,7 @@ icon_state = "zuliecap" item_state = "zuliecap" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' flags_inv = HIDEEARS|HIDEHAIR mutantrace_variation = NONE @@ -435,7 +431,7 @@ name = "Multicolor Coat" desc = "An oddly special looking coat with black, red, and gold" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' icon_state = "redgoldjacket" item_state = "redgoldjacket" body_parts_covered = CHEST|GROIN|LEGS|ARMS @@ -447,7 +443,7 @@ icon_state = "kimono" item_state = "kimono" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' body_parts_covered = CHEST|GROIN|LEGS|ARMS mutantrace_variation = NONE @@ -457,7 +453,7 @@ icon_state = "commjacket" item_state = "commjacket" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' body_parts_covered = CHEST|GROIN|LEGS|ARMS mutantrace_variation = NONE @@ -467,7 +463,7 @@ icon_state = "mw2_russian_para" item_state = "mw2_russian_para" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' mutantrace_variation = NONE /obj/item/clothing/gloves/longblackgloves @@ -476,7 +472,7 @@ icon_state = "longblackgloves" item_state = "longblackgloves" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' /obj/item/clothing/under/custom/trendy_fit name = "Trendy Fitting Clothing" @@ -484,7 +480,7 @@ icon_state = "trendy_fit" item_state = "trendy_fit" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' mutantrace_variation = NONE /obj/item/clothing/head/blueberet @@ -493,7 +489,7 @@ icon_state = "blueberet" item_state = "blueberet" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' dynamic_hair_suffix = "" /obj/item/clothing/head/flight @@ -502,7 +498,7 @@ icon_state = "flight-g" item_state = "flight-g" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' /obj/item/clothing/neck/necklace/onion name = "Onion Necklace" @@ -510,7 +506,7 @@ icon = 'icons/obj/custom.dmi' icon_state = "onion" item_state = "onion" - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' /obj/item/clothing/under/custom/mikubikini name = "starlight singer bikini" @@ -518,7 +514,7 @@ icon_state = "mikubikini" item_state = "mikubikini" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' mutantrace_variation = NONE /obj/item/clothing/suit/mikujacket @@ -527,7 +523,7 @@ icon_state = "mikujacket" item_state = "mikujacket" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' mutantrace_variation = NONE /obj/item/clothing/head/mikuhair @@ -536,7 +532,7 @@ icon_state = "mikuhair" item_state = "mikuhair" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' mutantrace_variation = NONE flags_inv = HIDEHAIR @@ -546,7 +542,7 @@ icon_state = "mikugloves" item_state = "mikugloves" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' mutantrace_variation = NONE /obj/item/clothing/shoes/sneakers/mikuleggings @@ -555,7 +551,7 @@ icon_state = "mikuleggings" item_state = "mikuleggings" icon = 'icons/obj/custom.dmi' - alternate_worn_icon = 'icons/mob/custom_w.dmi' + mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi' mutantrace_variation = NONE /obj/item/toy/plush/mammal/dog/fritz @@ -567,3 +563,8 @@ unique_reskin = list("Goodboye" = "fritz", "Badboye" = "fritz_bad") mutantrace_variation = NONE +/obj/item/clothing/neck/cloak/polychromic/polyce + name = "polychromic embroidered cloak" + desc = "A fancy cloak embroidered with polychromatic thread in a pattern that reminds one of the wielders of unlimited power." + icon_state = "polyce" + poly_colors = list("#808080", "#8CC6FF", "#FF3535") diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm index 6d080ee898..0a3bdb727d 100644 --- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm +++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm @@ -424,15 +424,15 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm ! if(hit_atom) if(isliving(hit_atom)) var/mob/living/L = hit_atom - if(!L.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK)) + if(L.run_block(0, "the [name]", src, ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS) + DefaultCombatKnockdown(15, 1, 1) + else L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") L.DefaultCombatKnockdown(iscarbon(L) ? 60 : 45, override_stamdmg = CLAMP(pounce_stamloss, 0, pounce_stamloss_cap-L.getStaminaLoss())) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice. playsound(src, 'sound/weapons/Egloves.ogg', 50, 1) sleep(2)//Runtime prevention (infinite bump() calls on hulks) step_towards(src,L) log_combat(src, L, "borg pounced") - else - DefaultCombatKnockdown(15, 1, 1) pounce_cooldown = !pounce_cooldown spawn(pounce_cooldown_time) //3s by default diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm index 53463bcfe5..20917c4ba5 100644 --- a/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm +++ b/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm @@ -1,34 +1,3 @@ -////////////Anti Tank Pistol//////////// - -/obj/item/gun/ballistic/automatic/pistol/antitank - name = "Anti Tank Pistol" - desc = "A massively impractical and silly monstrosity of a pistol that fires .50 calliber rounds. The recoil is likely to dislocate your wrist." - icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' - icon_state = "atp" - item_state = "pistol" - recoil = 4 - mag_type = /obj/item/ammo_box/magazine/sniper_rounds - fire_delay = 50 - burst_size = 1 - can_suppress = 0 - w_class = WEIGHT_CLASS_NORMAL - actions_types = list() - fire_sound = 'sound/weapons/blastcannon.ogg' - spread = 20 //damn thing has no rifling. - -/obj/item/gun/ballistic/automatic/pistol/antitank/update_icon() - ..() - if(magazine) - cut_overlays() - add_overlay("atp-mag") - else - cut_overlays() - icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" - -/obj/item/gun/ballistic/automatic/pistol/antitank/syndicate - name = "Syndicate Anti Tank Pistol" - desc = "A massively impractical and silly monstrosity of a pistol that fires .50 calliber rounds. The recoil is likely to dislocate a variety of joints without proper bracing." - pin = /obj/item/firing_pin/implant/pindicate ///foam stealth pistol/// @@ -56,72 +25,6 @@ cut_overlays() icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" -//////10mm soporific bullets////// - -/obj/item/projectile/bullet/c10mm/soporific - name ="10mm soporific bullet" - nodamage = TRUE - -/obj/item/projectile/bullet/c10mm/soporific/on_hit(atom/target, blocked = FALSE) - . = ..() - if((blocked != 100) && isliving(target)) - var/mob/living/L = target - L.blur_eyes(6) - if(L.getStaminaLoss() >= 60) - L.Sleeping(300) - else - L.adjustStaminaLoss(25) - -/obj/item/ammo_casing/c10mm/soporific - name = ".10mm soporific bullet casing" - desc = "A 10mm soporific bullet casing." - projectile_type = /obj/item/projectile/bullet/c10mm/soporific - -/obj/item/ammo_box/magazine/m10mm/soporific - name = "pistol magazine (10mm soporific)" - icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' - icon_state = "9x19pS" - desc = "A gun magazine. Loaded with rounds which inject the target with a variety of illegal substances to induce sleep in the target." - ammo_type = /obj/item/ammo_casing/c10mm/soporific - -/obj/item/ammo_box/c10mm/soporific - name = "ammo box (10mm soporific)" - ammo_type = /obj/item/ammo_casing/c10mm/soporific - max_ammo = 24 - -//////modular pistol////// (reskinnable stetchkins) - -/obj/item/gun/ballistic/automatic/pistol/modular - name = "modular pistol" - desc = "A small, easily concealable 10mm handgun. Has a threaded barrel for suppressors." - icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' - icon_state = "cde" - can_unsuppress = TRUE - obj_flags = UNIQUE_RENAME - unique_reskin = list("Default" = "cde", - "NT-99" = "n99", - "Stealth" = "stealthpistol", - "HKVP-78" = "vp78", - "Luger" = "p08b", - "Mk.58" = "secguncomp", - "PX4 Storm" = "px4" - ) - -/obj/item/gun/ballistic/automatic/pistol/modular/update_icon() - ..() - if(current_skin) - icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" - else - icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" - if(magazine && suppressed) - cut_overlays() - add_overlay("[unique_reskin[current_skin]]-magazine-sup") //Yes, this means the default iconstate can't have a magazine overlay - else if (magazine) - cut_overlays() - add_overlay("[unique_reskin[current_skin]]-magazine") - else - cut_overlays() - /////////RAYGUN MEMES///////// /obj/item/projectile/beam/lasertag/ray //the projectile, compatible with regular laser tag armor diff --git a/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm b/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm index 49a8a26f35..49d48e0000 100644 --- a/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm +++ b/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm @@ -39,7 +39,7 @@ obj/item/gun/energy/e_gun/cx/AltClick(mob/living/user) body_color = sanitize_hexcolor(body_color_input, desired_format=6, include_crunch=1) update_icon() -obj/item/gun/energy/e_gun/cx/worn_overlays(isinhands, icon_file, style_flags = NONE) +obj/item/gun/energy/e_gun/cx/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(isinhands) var/mutable_appearance/body_inhand = mutable_appearance(icon_file, "cxe_body") diff --git a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm index 05b5c195c2..a4b6429bea 100644 --- a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm +++ b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm @@ -87,7 +87,7 @@ . = ..() . += "Alt-click to change firing modes." -/obj/item/gun/energy/pumpaction/worn_overlays(isinhands, icon_file, style_flags = NONE) //ammo counter for inhands +/obj/item/gun/energy/pumpaction/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) //ammo counter for inhands . = ..() var/ratio = CEILING((cell.charge / cell.maxcharge) * charge_sections, 1) var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index] diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm index 28a776082f..198e6c5c24 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm @@ -54,15 +54,15 @@ return..() var/mob/living/carbon/human/H = M - var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS) //If they've opted out, then route processing though liver. if(!(H.client?.prefs.cit_toggles & BREAST_ENLARGEMENT)) var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER) if(L) - L.swelling += 0.05 + L.applyOrganDamage(0.25) else H.adjustToxLoss(1) return..() + var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS) //otherwise proceed as normal if(!B) //If they don't have breasts, give them breasts. @@ -95,7 +95,8 @@ /datum/reagent/fermi/breast_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a female if male and ODing, doesn't touch nonbinary and object genders. if(!(M.client?.prefs.cit_toggles & FORCED_FEM)) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) - L.swelling+= 0.05 + if(L) + L.applyOrganDamage(0.25) return ..() var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS) @@ -130,7 +131,8 @@ var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS) if(!(M.client?.prefs.cit_toggles & BREAST_ENLARGEMENT) || !B) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) - L.swelling-= 0.05 + if(L) + L.applyOrganDamage(-0.25) return ..() B.modify_size(-0.05) return ..() @@ -208,14 +210,14 @@ if(!ishuman(M)) return ..() var/mob/living/carbon/human/H = M - var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS) if(!(H.client?.prefs.cit_toggles & PENIS_ENLARGEMENT)) var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER) if(L) - L.swelling += 0.05 + L.applyOrganDamage(0.25) else H.adjustToxLoss(1) return ..() + var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS) //otherwise proceed as normal if(!P)//They do have a preponderance for escapism, or so I've heard. @@ -241,7 +243,8 @@ return ..() if(!(M.client?.prefs.cit_toggles & FORCED_MASC)) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) - L.swelling+= 0.05 + if(L) + L.applyOrganDamage(0.25) return..() var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS) @@ -278,7 +281,8 @@ var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS) if(!(H.client?.prefs.cit_toggles & PENIS_ENLARGEMENT) || !P) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) - L.swelling-= 0.05 + if(L) + L.applyOrganDamage(-0.25) return..() P.modify_size(-0.1) diff --git a/modular_citadel/code/modules/reagents/objects/clothes.dm b/modular_citadel/code/modules/reagents/objects/clothes.dm index 4707d5b460..34af39bbe0 100644 --- a/modular_citadel/code/modules/reagents/objects/clothes.dm +++ b/modular_citadel/code/modules/reagents/objects/clothes.dm @@ -5,7 +5,7 @@ name = "Synthetic hat" icon = 'icons/obj/clothing/hats.dmi' icon_state = "cowboy" - desc = "A sythesized hat, you can't seem to take it off. And tips their hat." + desc = "A synthesized hat, you can't seem to take it off. And tips their hat." armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) //item_flags = NODROP //Tips their hat! diff --git a/modular_citadel/code/modules/reagents/objects/items.dm b/modular_citadel/code/modules/reagents/objects/items.dm index 5d207f4c73..1924e7ee00 100644 --- a/modular_citadel/code/modules/reagents/objects/items.dm +++ b/modular_citadel/code/modules/reagents/objects/items.dm @@ -54,7 +54,6 @@ to_chat(user, "[src] is empty!") add_fingerprint(user) return - ..() /obj/item/fermichem/pHpaper name = "pH indicator strip" diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm index 41eccb7054..d2a063fd4e 100644 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm @@ -95,6 +95,7 @@ taste_description = "strawberry roofies" taste_mult = 2 //Hide the roofies in stronger flavors 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)) @@ -120,6 +121,7 @@ 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)) @@ -174,6 +176,7 @@ 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)) @@ -191,6 +194,7 @@ 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) diff --git a/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi b/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi index e8efbec216..9dbed5e9f0 100644 Binary files a/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi and b/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi differ diff --git a/modular_citadel/icons/polyclothes/item/neck.dmi b/modular_citadel/icons/polyclothes/item/neck.dmi deleted file mode 100644 index e2792cf9d0..0000000000 Binary files a/modular_citadel/icons/polyclothes/item/neck.dmi and /dev/null differ diff --git a/modular_citadel/icons/polyclothes/mob/neck.dmi b/modular_citadel/icons/polyclothes/mob/neck.dmi deleted file mode 100644 index 529c64caa2..0000000000 Binary files a/modular_citadel/icons/polyclothes/mob/neck.dmi and /dev/null differ diff --git a/sound/effects/printer.ogg b/sound/effects/printer.ogg new file mode 100644 index 0000000000..c9546490f1 Binary files /dev/null and b/sound/effects/printer.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_brass/c2.ogg b/sound/instruments/synthesis_samples/brass/crisis_brass/c2.ogg new file mode 100644 index 0000000000..9808431b25 Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_brass/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_brass/c3.ogg b/sound/instruments/synthesis_samples/brass/crisis_brass/c3.ogg new file mode 100644 index 0000000000..4118cff81c Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_brass/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_brass/c4.ogg b/sound/instruments/synthesis_samples/brass/crisis_brass/c4.ogg new file mode 100644 index 0000000000..ae9e1361d2 Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_brass/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_brass/c5.ogg b/sound/instruments/synthesis_samples/brass/crisis_brass/c5.ogg new file mode 100644 index 0000000000..f19ddd9300 Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_brass/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_trombone/C2.ogg b/sound/instruments/synthesis_samples/brass/crisis_trombone/C2.ogg new file mode 100644 index 0000000000..d2c872d5a3 Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_trombone/C2.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_trombone/C3.ogg b/sound/instruments/synthesis_samples/brass/crisis_trombone/C3.ogg new file mode 100644 index 0000000000..e1e3fc8635 Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_trombone/C3.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_trombone/C4.ogg b/sound/instruments/synthesis_samples/brass/crisis_trombone/C4.ogg new file mode 100644 index 0000000000..42c4aa755d Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_trombone/C4.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_trombone/C5.ogg b/sound/instruments/synthesis_samples/brass/crisis_trombone/C5.ogg new file mode 100644 index 0000000000..762d2868d0 Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_trombone/C5.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_trumpet/C4.ogg b/sound/instruments/synthesis_samples/brass/crisis_trumpet/C4.ogg new file mode 100644 index 0000000000..baf71063af Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_trumpet/C4.ogg differ diff --git a/sound/instruments/synthesis_samples/brass/crisis_trumpet/C5.ogg b/sound/instruments/synthesis_samples/brass/crisis_trumpet/C5.ogg new file mode 100644 index 0000000000..92b4a11018 Binary files /dev/null and b/sound/instruments/synthesis_samples/brass/crisis_trumpet/C5.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C2.ogg b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C2.ogg new file mode 100644 index 0000000000..5a50a5091c Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C2.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C3.ogg b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C3.ogg new file mode 100644 index 0000000000..f086938260 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C3.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C4.ogg b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C4.ogg new file mode 100644 index 0000000000..1246bd5341 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C4.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C5.ogg b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C5.ogg new file mode 100644 index 0000000000..73680ce627 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C5.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C6.ogg b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C6.ogg new file mode 100644 index 0000000000..72841fb189 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C6.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C7.ogg b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C7.ogg new file mode 100644 index 0000000000..47797e4c00 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C7.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C8.ogg b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C8.ogg new file mode 100644 index 0000000000..ea34703160 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/fluid_celeste/C8.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/sgmbox/c2.ogg b/sound/instruments/synthesis_samples/chromatic/sgmbox/c2.ogg new file mode 100644 index 0000000000..4b96dd3dd3 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/sgmbox/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/sgmbox/c3.ogg b/sound/instruments/synthesis_samples/chromatic/sgmbox/c3.ogg new file mode 100644 index 0000000000..25daf5372e Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/sgmbox/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/sgmbox/c4.ogg b/sound/instruments/synthesis_samples/chromatic/sgmbox/c4.ogg new file mode 100644 index 0000000000..9b989404e7 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/sgmbox/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/sgmbox/c5.ogg b/sound/instruments/synthesis_samples/chromatic/sgmbox/c5.ogg new file mode 100644 index 0000000000..7fa99d9278 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/sgmbox/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/vibraphone1/c2.ogg b/sound/instruments/synthesis_samples/chromatic/vibraphone1/c2.ogg new file mode 100644 index 0000000000..64578a8fe1 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/vibraphone1/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/vibraphone1/c3.ogg b/sound/instruments/synthesis_samples/chromatic/vibraphone1/c3.ogg new file mode 100644 index 0000000000..d97230ce1f Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/vibraphone1/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/vibraphone1/c4.ogg b/sound/instruments/synthesis_samples/chromatic/vibraphone1/c4.ogg new file mode 100644 index 0000000000..eb6f80654a Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/vibraphone1/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/chromatic/vibraphone1/c5.ogg b/sound/instruments/synthesis_samples/chromatic/vibraphone1/c5.ogg new file mode 100644 index 0000000000..8f25ee2747 Binary files /dev/null and b/sound/instruments/synthesis_samples/chromatic/vibraphone1/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_clean/C2.ogg b/sound/instruments/synthesis_samples/guitar/crisis_clean/C2.ogg new file mode 100644 index 0000000000..17bea8122c Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_clean/C2.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_clean/C3.ogg b/sound/instruments/synthesis_samples/guitar/crisis_clean/C3.ogg new file mode 100644 index 0000000000..6dc0d8ad38 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_clean/C3.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_clean/C4.ogg b/sound/instruments/synthesis_samples/guitar/crisis_clean/C4.ogg new file mode 100644 index 0000000000..fbbcacb372 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_clean/C4.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_clean/C5.ogg b/sound/instruments/synthesis_samples/guitar/crisis_clean/C5.ogg new file mode 100644 index 0000000000..f9bb3f6e92 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_clean/C5.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_muted/C2.ogg b/sound/instruments/synthesis_samples/guitar/crisis_muted/C2.ogg new file mode 100644 index 0000000000..777a38664f Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_muted/C2.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_muted/C3.ogg b/sound/instruments/synthesis_samples/guitar/crisis_muted/C3.ogg new file mode 100644 index 0000000000..c14aa5ec93 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_muted/C3.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_muted/C4.ogg b/sound/instruments/synthesis_samples/guitar/crisis_muted/C4.ogg new file mode 100644 index 0000000000..b2a457b496 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_muted/C4.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_muted/C5.ogg b/sound/instruments/synthesis_samples/guitar/crisis_muted/C5.ogg new file mode 100644 index 0000000000..c4f5aac8bf Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_muted/C5.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_nylon/c2.ogg b/sound/instruments/synthesis_samples/guitar/crisis_nylon/c2.ogg new file mode 100644 index 0000000000..6a8115f004 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_nylon/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_nylon/c3.ogg b/sound/instruments/synthesis_samples/guitar/crisis_nylon/c3.ogg new file mode 100644 index 0000000000..15ec741bb6 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_nylon/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_nylon/c4.ogg b/sound/instruments/synthesis_samples/guitar/crisis_nylon/c4.ogg new file mode 100644 index 0000000000..df4ef3fb79 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_nylon/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_nylon/c5.ogg b/sound/instruments/synthesis_samples/guitar/crisis_nylon/c5.ogg new file mode 100644 index 0000000000..961f4a6b90 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_nylon/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_steel/c2.ogg b/sound/instruments/synthesis_samples/guitar/crisis_steel/c2.ogg new file mode 100644 index 0000000000..06ccf6ae51 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_steel/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_steel/c3.ogg b/sound/instruments/synthesis_samples/guitar/crisis_steel/c3.ogg new file mode 100644 index 0000000000..14756fb249 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_steel/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_steel/c4.ogg b/sound/instruments/synthesis_samples/guitar/crisis_steel/c4.ogg new file mode 100644 index 0000000000..544b324786 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_steel/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/guitar/crisis_steel/c5.ogg b/sound/instruments/synthesis_samples/guitar/crisis_steel/c5.ogg new file mode 100644 index 0000000000..df2dc8def5 Binary files /dev/null and b/sound/instruments/synthesis_samples/guitar/crisis_steel/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_accordian/c2.ogg b/sound/instruments/synthesis_samples/organ/crisis_accordian/c2.ogg new file mode 100644 index 0000000000..ba20e3f4b6 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_accordian/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_accordian/c3.ogg b/sound/instruments/synthesis_samples/organ/crisis_accordian/c3.ogg new file mode 100644 index 0000000000..fcc8715e04 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_accordian/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_accordian/c4.ogg b/sound/instruments/synthesis_samples/organ/crisis_accordian/c4.ogg new file mode 100644 index 0000000000..aa21d7e230 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_accordian/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_accordian/c5.ogg b/sound/instruments/synthesis_samples/organ/crisis_accordian/c5.ogg new file mode 100644 index 0000000000..ac45bc6be4 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_accordian/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_church/c2.ogg b/sound/instruments/synthesis_samples/organ/crisis_church/c2.ogg new file mode 100644 index 0000000000..71b9280e86 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_church/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_church/c3.ogg b/sound/instruments/synthesis_samples/organ/crisis_church/c3.ogg new file mode 100644 index 0000000000..676a24669f Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_church/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_church/c4.ogg b/sound/instruments/synthesis_samples/organ/crisis_church/c4.ogg new file mode 100644 index 0000000000..24e3732d7e Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_church/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_church/c5.ogg b/sound/instruments/synthesis_samples/organ/crisis_church/c5.ogg new file mode 100644 index 0000000000..72dc2ce764 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_church/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_hammond/c2.ogg b/sound/instruments/synthesis_samples/organ/crisis_hammond/c2.ogg new file mode 100644 index 0000000000..853b7591b4 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_hammond/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_hammond/c3.ogg b/sound/instruments/synthesis_samples/organ/crisis_hammond/c3.ogg new file mode 100644 index 0000000000..205e190379 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_hammond/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_hammond/c4.ogg b/sound/instruments/synthesis_samples/organ/crisis_hammond/c4.ogg new file mode 100644 index 0000000000..e90c28f14c Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_hammond/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_hammond/c5.ogg b/sound/instruments/synthesis_samples/organ/crisis_hammond/c5.ogg new file mode 100644 index 0000000000..a56d3cc3f6 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_hammond/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_harmonica/c3.ogg b/sound/instruments/synthesis_samples/organ/crisis_harmonica/c3.ogg new file mode 100644 index 0000000000..14c5f35eef Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_harmonica/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_harmonica/c4.ogg b/sound/instruments/synthesis_samples/organ/crisis_harmonica/c4.ogg new file mode 100644 index 0000000000..e06e733eb2 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_harmonica/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_harmonica/c5.ogg b/sound/instruments/synthesis_samples/organ/crisis_harmonica/c5.ogg new file mode 100644 index 0000000000..3d21e92d53 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_harmonica/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c2.ogg b/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c2.ogg new file mode 100644 index 0000000000..be51b6dcd4 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c3.ogg b/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c3.ogg new file mode 100644 index 0000000000..7426d246a0 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c4.ogg b/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c4.ogg new file mode 100644 index 0000000000..af7b66cf19 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c5.ogg b/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c5.ogg new file mode 100644 index 0000000000..58ff4ff216 Binary files /dev/null and b/sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c2.ogg b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c2.ogg new file mode 100644 index 0000000000..4b7feb77a4 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c3.ogg b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c3.ogg new file mode 100644 index 0000000000..5e7eefa79a Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c4.ogg b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c4.ogg new file mode 100644 index 0000000000..13e49d4f3a Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c5.ogg b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c5.ogg new file mode 100644 index 0000000000..6ef00f0700 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c6.ogg b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c6.ogg new file mode 100644 index 0000000000..a868249ca8 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c6.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c7.ogg b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c7.ogg new file mode 100644 index 0000000000..2d08d98dd9 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c7.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c8.ogg b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c8.ogg new file mode 100644 index 0000000000..50e3cb76a7 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_bright_piano/c8.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c2.ogg b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c2.ogg new file mode 100644 index 0000000000..0b87714166 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c3.ogg b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c3.ogg new file mode 100644 index 0000000000..31fd625098 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c4.ogg b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c4.ogg new file mode 100644 index 0000000000..0ed309dbb7 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c5.ogg b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c5.ogg new file mode 100644 index 0000000000..7fd820d373 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c6.ogg b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c6.ogg new file mode 100644 index 0000000000..b4ed66e27c Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c6.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c7.ogg b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c7.ogg new file mode 100644 index 0000000000..13a5f7d873 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c7.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c8.ogg b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c8.ogg new file mode 100644 index 0000000000..0169d52c21 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_grand_piano/c8.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c2.ogg b/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c2.ogg new file mode 100644 index 0000000000..16d49cb15e Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c3.ogg b/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c3.ogg new file mode 100644 index 0000000000..83e906cd1a Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c4.ogg b/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c4.ogg new file mode 100644 index 0000000000..33f766e4aa Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c5.ogg b/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c5.ogg new file mode 100644 index 0000000000..6ce06dda56 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/crisis_harpsichord/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_harpsi/C2.ogg b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C2.ogg new file mode 100644 index 0000000000..3941e7af03 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C2.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_harpsi/C3.ogg b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C3.ogg new file mode 100644 index 0000000000..4f79ee9987 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C3.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_harpsi/C4.ogg b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C4.ogg new file mode 100644 index 0000000000..1d773c62e7 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C4.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_harpsi/C5.ogg b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C5.ogg new file mode 100644 index 0000000000..938a557e04 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C5.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_harpsi/C6.ogg b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C6.ogg new file mode 100644 index 0000000000..c65f06ce3e Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C6.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_harpsi/C7.ogg b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C7.ogg new file mode 100644 index 0000000000..87d4943509 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C7.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_harpsi/C8.ogg b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C8.ogg new file mode 100644 index 0000000000..5800b2d0ff Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_harpsi/C8.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_piano/c2.ogg b/sound/instruments/synthesis_samples/piano/fluid_piano/c2.ogg new file mode 100644 index 0000000000..9ce5eee76e Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_piano/c2.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_piano/c3.ogg b/sound/instruments/synthesis_samples/piano/fluid_piano/c3.ogg new file mode 100644 index 0000000000..4644327476 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_piano/c3.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_piano/c4.ogg b/sound/instruments/synthesis_samples/piano/fluid_piano/c4.ogg new file mode 100644 index 0000000000..ab6d8a2a92 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_piano/c4.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_piano/c5.ogg b/sound/instruments/synthesis_samples/piano/fluid_piano/c5.ogg new file mode 100644 index 0000000000..0041ea2e13 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_piano/c5.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_piano/c6.ogg b/sound/instruments/synthesis_samples/piano/fluid_piano/c6.ogg new file mode 100644 index 0000000000..5d836b9f7c Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_piano/c6.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_piano/c7.ogg b/sound/instruments/synthesis_samples/piano/fluid_piano/c7.ogg new file mode 100644 index 0000000000..1981572cf2 Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_piano/c7.ogg differ diff --git a/sound/instruments/synthesis_samples/piano/fluid_piano/c8.ogg b/sound/instruments/synthesis_samples/piano/fluid_piano/c8.ogg new file mode 100644 index 0000000000..35e5b147bc Binary files /dev/null and b/sound/instruments/synthesis_samples/piano/fluid_piano/c8.ogg differ diff --git a/sound/instruments/synthesis_samples/tones/Sawtooth.ogg b/sound/instruments/synthesis_samples/tones/Sawtooth.ogg new file mode 100644 index 0000000000..e46f5eaced Binary files /dev/null and b/sound/instruments/synthesis_samples/tones/Sawtooth.ogg differ diff --git a/sound/instruments/synthesis_samples/tones/Sine.ogg b/sound/instruments/synthesis_samples/tones/Sine.ogg new file mode 100644 index 0000000000..e0b14869e9 Binary files /dev/null and b/sound/instruments/synthesis_samples/tones/Sine.ogg differ diff --git a/sound/instruments/synthesis_samples/tones/Square.ogg b/sound/instruments/synthesis_samples/tones/Square.ogg new file mode 100644 index 0000000000..817531bcca Binary files /dev/null and b/sound/instruments/synthesis_samples/tones/Square.ogg differ diff --git a/sound/machines/machine_vend.ogg b/sound/machines/machine_vend.ogg new file mode 100644 index 0000000000..92867a1f3d Binary files /dev/null and b/sound/machines/machine_vend.ogg differ diff --git a/tgstation.dme b/tgstation.dme old mode 100644 new mode 100755 index 11e0946291..26bb4e2e5a --- a/tgstation.dme +++ b/tgstation.dme @@ -43,6 +43,7 @@ #include "code\__DEFINES\diseases.dm" #include "code\__DEFINES\DNA.dm" #include "code\__DEFINES\donator_groupings.dm" +#include "code\__DEFINES\dye_keys.dm" #include "code\__DEFINES\dynamic.dm" #include "code\__DEFINES\events.dm" #include "code\__DEFINES\exports.dm" @@ -51,13 +52,14 @@ #include "code\__DEFINES\food.dm" #include "code\__DEFINES\footsteps.dm" #include "code\__DEFINES\hud.dm" +#include "code\__DEFINES\instruments.dm" #include "code\__DEFINES\integrated_electronics.dm" #include "code\__DEFINES\interaction_flags.dm" #include "code\__DEFINES\inventory.dm" #include "code\__DEFINES\is_helpers.dm" #include "code\__DEFINES\jobs.dm" #include "code\__DEFINES\language.dm" -#include "code\__DEFINES\layers.dm" +#include "code\__DEFINES\layers_planes.dm" #include "code\__DEFINES\lighting.dm" #include "code\__DEFINES\logging.dm" #include "code\__DEFINES\machines.dm" @@ -102,6 +104,7 @@ #include "code\__DEFINES\stat.dm" #include "code\__DEFINES\stat_tracking.dm" #include "code\__DEFINES\status_effects.dm" +#include "code\__DEFINES\storage.dm" #include "code\__DEFINES\subsystems.dm" #include "code\__DEFINES\tgs.config.dm" #include "code\__DEFINES\tgs.dm" @@ -224,6 +227,7 @@ #include "code\_onclick\hud\robot.dm" #include "code\_onclick\hud\screen_objects.dm" #include "code\_onclick\hud\swarmer.dm" +#include "code\_onclick\hud\screen_objects\storage.dm" #include "code\controllers\admin.dm" #include "code\controllers\configuration_citadel.dm" #include "code\controllers\controller.dm" @@ -290,6 +294,7 @@ #include "code\controllers\subsystem\research.dm" #include "code\controllers\subsystem\server_maint.dm" #include "code\controllers\subsystem\shuttle.dm" +#include "code\controllers\subsystem\sounds.dm" #include "code\controllers\subsystem\spacedrift.dm" #include "code\controllers\subsystem\stickyban.dm" #include "code\controllers\subsystem\sun.dm" @@ -307,6 +312,7 @@ #include "code\controllers\subsystem\processing\circuit.dm" #include "code\controllers\subsystem\processing\fastprocess.dm" #include "code\controllers\subsystem\processing\fields.dm" +#include "code\controllers\subsystem\processing\instruments.dm" #include "code\controllers\subsystem\processing\nanites.dm" #include "code\controllers\subsystem\processing\networks.dm" #include "code\controllers\subsystem\processing\obj.dm" @@ -419,9 +425,10 @@ #include "code\datums\components\wearertargeting.dm" #include "code\datums\components\wet_floor.dm" #include "code\datums\components\crafting\craft.dm" -#include "code\datums\components\crafting\glassware.dm" #include "code\datums\components\crafting\guncrafting.dm" #include "code\datums\components\crafting\recipes.dm" +#include "code\datums\components\crafting\glassware\glassware.dm" +#include "code\datums\components\crafting\glassware\lens_crafting.dm" #include "code\datums\components\crafting\recipes\recipes_clothing.dm" #include "code\datums\components\crafting\recipes\recipes_misc.dm" #include "code\datums\components\crafting\recipes\recipes_primal.dm" @@ -432,6 +439,7 @@ #include "code\datums\components\fantasy\prefixes.dm" #include "code\datums\components\fantasy\suffixes.dm" #include "code\datums\components\storage\storage.dm" +#include "code\datums\components\storage\ui.dm" #include "code\datums\components\storage\concrete\_concrete.dm" #include "code\datums\components\storage\concrete\bag_of_holding.dm" #include "code\datums\components\storage\concrete\bluespace.dm" @@ -505,6 +513,7 @@ #include "code\datums\elements\flavor_text.dm" #include "code\datums\elements\ghost_role_eligibility.dm" #include "code\datums\elements\mob_holder.dm" +#include "code\datums\elements\polychromic.dm" #include "code\datums\elements\spellcasting.dm" #include "code\datums\elements\swimming.dm" #include "code\datums\elements\sword_point.dm" @@ -969,7 +978,6 @@ #include "code\game\objects\items\devices\geiger_counter.dm" #include "code\game\objects\items\devices\glue.dm" #include "code\game\objects\items\devices\gps.dm" -#include "code\game\objects\items\devices\instruments.dm" #include "code\game\objects\items\devices\laserpointer.dm" #include "code\game\objects\items\devices\lightreplacer.dm" #include "code\game\objects\items\devices\megaphone.dm" @@ -1115,7 +1123,6 @@ #include "code\game\objects\structures\mirror.dm" #include "code\game\objects\structures\mop_bucket.dm" #include "code\game\objects\structures\morgue.dm" -#include "code\game\objects\structures\musician.dm" #include "code\game\objects\structures\noticeboard.dm" #include "code\game\objects\structures\petrified_statue.dm" #include "code\game\objects\structures\plasticflaps.dm" @@ -1968,6 +1975,7 @@ #include "code\modules\hydroponics\grown\cotton.dm" #include "code\modules\hydroponics\grown\eggplant.dm" #include "code\modules\hydroponics\grown\flowers.dm" +#include "code\modules\hydroponics\grown\garlic.dm" #include "code\modules\hydroponics\grown\grass_carpet.dm" #include "code\modules\hydroponics\grown\kudzu.dm" #include "code\modules\hydroponics\grown\melon.dm" @@ -1987,6 +1995,22 @@ #include "code\modules\hydroponics\grown\tobacco.dm" #include "code\modules\hydroponics\grown\tomato.dm" #include "code\modules\hydroponics\grown\towercap.dm" +#include "code\modules\instruments\instrument_data\_instrument_data.dm" +#include "code\modules\instruments\instrument_data\_instrument_key.dm" +#include "code\modules\instruments\instrument_data\brass.dm" +#include "code\modules\instruments\instrument_data\chromatic_percussion.dm" +#include "code\modules\instruments\instrument_data\fun.dm" +#include "code\modules\instruments\instrument_data\guitar.dm" +#include "code\modules\instruments\instrument_data\hardcoded.dm" +#include "code\modules\instruments\instrument_data\organ.dm" +#include "code\modules\instruments\instrument_data\piano.dm" +#include "code\modules\instruments\instrument_data\synth_tones.dm" +#include "code\modules\instruments\instruments\item.dm" +#include "code\modules\instruments\instruments\stationary.dm" +#include "code\modules\instruments\songs\_song.dm" +#include "code\modules\instruments\songs\editor.dm" +#include "code\modules\instruments\songs\play_legacy.dm" +#include "code\modules\instruments\songs\play_synthesized.dm" #include "code\modules\integrated_electronics\_defines.dm" #include "code\modules\integrated_electronics\core\analyzer.dm" #include "code\modules\integrated_electronics\core\assemblies.dm" @@ -2217,6 +2241,7 @@ #include "code\modules\mob\living\emote.dm" #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" @@ -2294,6 +2319,7 @@ #include "code\modules\mob\living\carbon\human\emote.dm" #include "code\modules\mob\living\carbon\human\examine.dm" #include "code\modules\mob\living\carbon\human\human.dm" +#include "code\modules\mob\living\carbon\human\human_block.dm" #include "code\modules\mob\living\carbon\human\human_defense.dm" #include "code\modules\mob\living\carbon\human\human_defines.dm" #include "code\modules\mob\living\carbon\human\human_helpers.dm" @@ -3269,7 +3295,6 @@ #include "modular_citadel\code\modules\client\verbs\who.dm" #include "modular_citadel\code\modules\clothing\neck.dm" #include "modular_citadel\code\modules\clothing\trek.dm" -#include "modular_citadel\code\modules\clothing\suits\polychromic_cloaks.dm" #include "modular_citadel\code\modules\clothing\suits\suits.dm" #include "modular_citadel\code\modules\custom_loadout\custom_items.dm" #include "modular_citadel\code\modules\custom_loadout\load_to_mob.dm" diff --git a/tgui-next/packages/tgui/interfaces/Vending.js b/tgui-next/packages/tgui/interfaces/Vending.js index e394c2d241..b6ffde015d 100644 --- a/tgui-next/packages/tgui/interfaces/Vending.js +++ b/tgui-next/packages/tgui/interfaces/Vending.js @@ -9,54 +9,40 @@ export const Vending = props => { const { ref } = config; let inventory; let custom = false; - if (data.vending_machine_input) { - inventory = data.vending_machine_input; - custom = true; + const onstation = true; + if (data.extended_inventory && data.coin) { + inventory = [ + ...data.product_records, + ...data.hidden_records, + ...data.coin_records, + ]; } else if (data.extended_inventory) { inventory = [ ...data.product_records, - ...data.coin_records, ...data.hidden_records, ]; + } else if (data.coin) { + inventory = [ + ...data.product_records, + ...data.coin_records, + ]; } else { inventory = [ ...data.product_records, - ...data.coin_records, ]; } return ( - {data.onstation && ( -
- {data.user && ( - - Welcome, {data.user.name}, - {' '} - {data.user.job || "Unemployed"}! -
- Your balance is {data.user.cash} credits. -
- ) || ( - - No registered ID card!
- Please contact your local HoP! -
- )} + {data.coin && ( +
+
)}
{inventory.map((product => { - const free = ( - !data.onstation - || product.price === 0 - || ( - !product.premium - && data.department - && data.user - && data.department === data.user.department - ) - ); return ( @@ -91,23 +77,13 @@ export const Vending = props => { {custom && (