diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 403526d30b0..a553cef999c 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -210,6 +210,8 @@ This prevents nesting levels from getting deeper then they need to be. * Do not divide when you can easily convert it to a multiplication. (ie `4/2` should be done as `4*0.5`) +* Do not use the shorthand sql insert format (where no column names are specified) because it unnecessarily breaks all queries on minor column changes and prevents using these tables for tracking outside related info such as in a connected site/forum. + #### Enforced not enforced The following different coding styles are not only not enforced, but it is generally frowned upon to change them over from one to the other for little reason: diff --git a/_maps/map_files/Cerestation/cerestation.dmm b/_maps/map_files/Cerestation/cerestation.dmm index 81f6f918d35..9765dc77a4c 100644 --- a/_maps/map_files/Cerestation/cerestation.dmm +++ b/_maps/map_files/Cerestation/cerestation.dmm @@ -40086,7 +40086,7 @@ }, /area/medical/virology) "brX" = ( -/obj/machinery/smartfridge/chemistry/virology, +/obj/machinery/smartfridge/chemistry/virology/preloaded, /turf/open/floor/plasteel/whitegreen/side{ tag = "icon-whitegreen (EAST)"; icon_state = "whitegreen"; @@ -47853,7 +47853,7 @@ }, /area/medical/chemistry) "bEN" = ( -/obj/machinery/smartfridge/chemistry, +/obj/machinery/smartfridge/chemistry/preloaded, /turf/open/floor/plating{ baseturf = /turf/open/floor/plating/asteroid/airless }, @@ -76429,7 +76429,7 @@ }, /area/toxins/xenobiology) "cCm" = ( -/obj/machinery/smartfridge/extract, +/obj/machinery/smartfridge/extract/preloaded, /obj/structure/cable/orange{ d1 = 4; d2 = 8; diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 2ed8ec0149b..4a91a5b85fb 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -10753,7 +10753,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/loadingarea{ - baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; + baseturf = /turf/open/space; dir = 8 }, /area/quartermaster/storage) @@ -11240,7 +11240,7 @@ /area/quartermaster/storage) "awJ" = ( /turf/open/floor/plasteel/loadingarea{ - baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; + baseturf = /turf/open/space; dir = 8 }, /area/quartermaster/storage) @@ -31236,7 +31236,7 @@ icon_state = "1-4" }, /turf/open/floor/plasteel/loadingarea{ - baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; + baseturf = /turf/open/space; dir = 8 }, /area/quartermaster/miningdock{ @@ -34793,7 +34793,6 @@ dir = 4 }, /turf/open/floor/plasteel{ - desc = ""; icon_state = "L14" }, /area/hallway/primary/central) @@ -52476,7 +52475,7 @@ name = "Queue Shutters" }, /turf/open/floor/plasteel/loadingarea{ - baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; + baseturf = /turf/open/space; dir = 8 }, /area/hallway/primary/central) @@ -70988,7 +70987,6 @@ "cDW" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /turf/open/floor/plasteel{ - desc = ""; icon_state = "L13"; name = "floor" }, @@ -79544,7 +79542,7 @@ }) "cUh" = ( /obj/structure/disposalpipe/segment, -/obj/machinery/smartfridge/chemistry, +/obj/machinery/smartfridge/chemistry/preloaded, /turf/closed/wall, /area/medical/medbay{ name = "Medbay Central" @@ -81191,7 +81189,7 @@ /turf/open/floor/plating, /area/toxins/xenobiology) "cXc" = ( -/obj/machinery/smartfridge/extract, +/obj/machinery/smartfridge/extract/preloaded, /obj/machinery/light_switch{ pixel_x = -26 }, @@ -84276,7 +84274,7 @@ /turf/open/floor/plasteel/whiteyellow/corner, /area/medical/chemistry) "ddg" = ( -/obj/machinery/smartfridge/chemistry, +/obj/machinery/smartfridge/chemistry/preloaded, /turf/closed/wall, /area/medical/chemistry) "ddh" = ( @@ -104162,7 +104160,7 @@ name = "emergency shower" }, /turf/open/floor/plasteel/whiteblue/side{ - baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; + baseturf = /turf/open/space; dir = 4 }, /area/shuttle/escape) @@ -104907,7 +104905,7 @@ /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/machinery/smartfridge/chemistry/virology, +/obj/machinery/smartfridge/chemistry/virology/preloaded, /obj/effect/turf_decal/stripes/line{ dir = 4 }, diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index f6fe1c8188f..44421252ee4 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -27963,7 +27963,6 @@ dir = 4 }, /turf/open/floor/plasteel{ - desc = ""; icon_state = "L13"; name = "floor" }, @@ -28813,7 +28812,6 @@ icon_state = "4-8" }, /turf/open/floor/plasteel{ - desc = ""; icon_state = "L14" }, /area/hallway/primary/central) @@ -63164,7 +63162,7 @@ /turf/open/floor/plating, /area/medical/chemistry) "cfY" = ( -/obj/machinery/smartfridge/chemistry, +/obj/machinery/smartfridge/chemistry/preloaded, /turf/closed/wall, /area/medical/chemistry) "cfZ" = ( @@ -77232,7 +77230,7 @@ }, /area/medical/virology) "cDH" = ( -/obj/machinery/smartfridge/chemistry/virology, +/obj/machinery/smartfridge/chemistry/virology/preloaded, /obj/machinery/airalarm{ frequency = 1439; pixel_y = 23 @@ -91081,7 +91079,7 @@ d2 = 8; icon_state = "2-8" }, -/obj/machinery/smartfridge/extract, +/obj/machinery/smartfridge/extract/preloaded, /obj/structure/cable/yellow{ d1 = 4; d2 = 8; diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 778fb50c88d..c37c4ca3a3a 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -513,7 +513,7 @@ /obj/structure/cable{ d1 = 1; d2 = 4; - icon_state = "1-4"; + icon_state = "1-4" }, /obj/structure/cable{ d1 = 1; @@ -1040,7 +1040,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/brown{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 1; + dir = 1 }, /area/mine/living_quarters) "cg" = ( @@ -1074,7 +1074,7 @@ /obj/structure/cable{ d1 = 1; d2 = 4; - icon_state = "1-4"; + icon_state = "1-4" }, /turf/open/floor/plasteel{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface @@ -1497,10 +1497,21 @@ /area/mine/living_quarters) "dd" = ( /obj/structure/table, -/obj/item/weapon/reagent_containers/food/drinks/beer, +/obj/item/weapon/reagent_containers/food/drinks/beer{ + pixel_x = 7; + pixel_y = 5 + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 }, +/obj/item/weapon/reagent_containers/food/drinks/beer{ + pixel_x = -1; + pixel_y = 9 + }, +/obj/item/weapon/reagent_containers/food/drinks/beer{ + pixel_x = -8; + pixel_y = 0 + }, /turf/open/floor/plasteel/bar{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface }, @@ -1772,6 +1783,9 @@ pixel_x = -5; pixel_y = 30 }, +/obj/machinery/shower{ + dir = 8 + }, /turf/open/floor/plasteel/purple/corner{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface }, @@ -2192,7 +2206,7 @@ }, /turf/open/floor/plasteel/vault{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 8; + dir = 8 }, /area/mine/maintenance) "ez" = ( @@ -2214,13 +2228,13 @@ /obj/machinery/iv_drip, /turf/open/floor/plasteel/whiteblue/side{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 1; + dir = 1 }, /area/mine/living_quarters) "eB" = ( /turf/open/floor/plasteel/whiteblue/side{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 1; + dir = 1 }, /area/mine/living_quarters) "eC" = ( @@ -2231,7 +2245,7 @@ }, /turf/open/floor/plasteel/whiteblue/side{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 5; + dir = 5 }, /area/mine/living_quarters) "eD" = ( @@ -2398,7 +2412,7 @@ /obj/item/weapon/storage/firstaid/regular, /turf/open/floor/plasteel/whiteblue/side{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 4; + dir = 4 }, /area/mine/living_quarters) "eU" = ( @@ -2512,6 +2526,7 @@ dir = 2; network = list("MINE") }, +/obj/structure/reagent_dispensers/watertank, /turf/open/floor/plasteel/brown{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; dir = 5 @@ -2520,7 +2535,7 @@ "fe" = ( /turf/open/floor/plasteel/brown/corner{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 1; + dir = 1 }, /area/mine/production) "ff" = ( @@ -2578,7 +2593,7 @@ }, /turf/open/floor/plasteel/brown{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 1; + dir = 1 }, /area/mine/living_quarters) "fm" = ( @@ -2600,7 +2615,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/brown{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; - dir = 1; + dir = 1 }, /area/mine/living_quarters) "fp" = ( @@ -2674,7 +2689,7 @@ /obj/structure/cable{ d1 = 1; d2 = 4; - icon_state = "1-4"; + icon_state = "1-4" }, /turf/open/floor/plasteel{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface @@ -2712,6 +2727,10 @@ /obj/machinery/light/small{ dir = 1 }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -5; + pixel_y = 30 + }, /turf/open/floor/plasteel/purple/corner{ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; dir = 4 @@ -2794,6 +2813,41 @@ /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /turf/closed/indestructible/riveted, /area/space) +"fQ" = ( +/obj/machinery/shower{ + dir = 8 + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel/white, +/area/mine/laborcamp) +"fR" = ( +/obj/structure/sink/kitchen{ + dir = 4; + icon_state = "sink_alt"; + pixel_x = -13; + tag = "icon-sink_alt (EAST)" + }, +/turf/open/floor/plasteel{ + baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface + }, +/area/mine/laborcamp) +"fS" = ( +/obj/structure/reagent_dispensers/watertank, +/turf/open/floor/plasteel/purple/corner{ + baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface + }, +/area/mine/production) +"fT" = ( +/obj/structure/sink{ + dir = 4; + icon_state = "sink"; + pixel_x = 11; + tag = "icon-sink (EAST)" + }, +/turf/open/floor/plasteel/bar{ + baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface + }, +/area/mine/living_quarters) (1,1,1) = {" aa @@ -8919,7 +8973,7 @@ aA at at at -at +fR at au fH @@ -9175,7 +9229,7 @@ an an at at -at +fQ at dr an @@ -14594,8 +14648,8 @@ fj ee cT cZ -dg dk +fT ee al al @@ -18433,7 +18487,7 @@ af ab ab dx -dC +fS dK bI bS diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index e8cb9e2187f..16269074a47 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -7303,7 +7303,6 @@ icon_state = "1-2" }, /turf/open/floor/plasteel{ - desc = ""; icon_state = "L14" }, /area/hallway/primary/central{ @@ -9155,7 +9154,7 @@ }, /obj/effect/landmark/start/shaft_miner, /turf/open/floor/plasteel/loadingarea{ - baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface; + baseturf = /turf/open/space; dir = 8 }, /area/quartermaster/miningdock) @@ -25976,7 +25975,6 @@ icon_state = "4-8" }, /turf/open/floor/plasteel{ - desc = ""; icon_state = "L13"; name = "floor" }, @@ -27036,7 +27034,7 @@ /turf/open/floor/plating, /area/medical/chemistry) "aRh" = ( -/obj/machinery/smartfridge/chemistry, +/obj/machinery/smartfridge/chemistry/preloaded, /turf/closed/wall, /area/medical/chemistry) "aRi" = ( @@ -37373,7 +37371,7 @@ /turf/open/floor/plasteel, /area/toxins/xenobiology) "bjb" = ( -/obj/machinery/smartfridge/extract, +/obj/machinery/smartfridge/extract/preloaded, /obj/machinery/light{ dir = 1 }, diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 56bcff286e9..bd71cc47948 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -30296,7 +30296,7 @@ }, /area/medical/chemistry) "bjk" = ( -/obj/machinery/smartfridge/chemistry, +/obj/machinery/smartfridge/chemistry/preloaded, /turf/closed/wall, /area/medical/chemistry) "bjl" = ( @@ -30534,7 +30534,7 @@ /turf/open/floor/plasteel/white, /area/toxins/xenobiology) "bjH" = ( -/obj/machinery/smartfridge/extract, +/obj/machinery/smartfridge/extract/preloaded, /turf/open/floor/plasteel/whitepurple/side{ dir = 4 }, @@ -40057,9 +40057,8 @@ /turf/open/floor/plasteel/white, /area/medical/virology) "bBf" = ( -/obj/machinery/smartfridge/chemistry/virology, +/obj/machinery/smartfridge/chemistry/virology/preloaded, /turf/open/floor/plasteel/whitegreen/side{ - tag = "icon-whitegreen (EAST)"; icon_state = "whitegreen"; dir = 4 }, @@ -50530,7 +50529,7 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "bXR" = ( -/obj/machinery/smartfridge/chemistry, +/obj/machinery/smartfridge/chemistry/preloaded, /turf/open/floor/plasteel/black, /area/medical/chemistry) "bXS" = ( diff --git a/_maps/map_files/TgStation/tgstation.2.1.3.dmm b/_maps/map_files/TgStation/tgstation.2.1.3.dmm index 995b612b36d..fafc5fe5441 100644 --- a/_maps/map_files/TgStation/tgstation.2.1.3.dmm +++ b/_maps/map_files/TgStation/tgstation.2.1.3.dmm @@ -17429,7 +17429,6 @@ /area/hallway/primary/central) "aMf" = ( /turf/open/floor/plasteel{ - desc = ""; icon_state = "L13"; name = "floor" }, @@ -17935,7 +17934,6 @@ /area/hallway/primary/central) "aNB" = ( /turf/open/floor/plasteel{ - desc = ""; icon_state = "L14" }, /area/hallway/primary/central) @@ -27262,7 +27260,7 @@ /turf/open/floor/plasteel, /area/assembly/chargebay) "bjQ" = ( -/obj/machinery/smartfridge/chemistry, +/obj/machinery/smartfridge/chemistry/preloaded, /turf/open/floor/plating, /area/medical/chemistry) "bjR" = ( @@ -41268,7 +41266,7 @@ /turf/open/floor/plasteel/white, /area/toxins/xenobiology) "bMo" = ( -/obj/machinery/smartfridge/extract, +/obj/machinery/smartfridge/extract/preloaded, /turf/open/floor/plasteel/white, /area/toxins/xenobiology) "bMp" = ( @@ -45237,7 +45235,7 @@ /turf/open/floor/plating, /area/maintenance/asmaint) "bVa" = ( -/obj/machinery/smartfridge/chemistry/virology, +/obj/machinery/smartfridge/chemistry/virology/preloaded, /turf/open/floor/plasteel/whitegreen/side{ dir = 8 }, diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index d30a2d098fa..433f44e0954 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -1,3 +1,4 @@ -#define ANTAG_DATUM_CULT /datum/antagonist/cult -#define ANTAG_DATUM_CLOCKCULT /datum/antagonist/clockcult -#define ANTAG_DATUM_CLOCKCULT_SILENT /datum/antagonist/clockcult/silent \ No newline at end of file +#define ANTAG_DATUM_CULT /datum/antagonist/cult +#define ANTAG_DATUM_CULT_MASTER /datum/antagonist/cult/master +#define ANTAG_DATUM_CLOCKCULT /datum/antagonist/clockcult +#define ANTAG_DATUM_CLOCKCULT_SILENT /datum/antagonist/clockcult/silent \ No newline at end of file diff --git a/code/__DEFINES/menu.dm b/code/__DEFINES/menu.dm new file mode 100644 index 00000000000..2730adf87c7 --- /dev/null +++ b/code/__DEFINES/menu.dm @@ -0,0 +1,3 @@ +#define CHECKBOX_NONE 0 +#define CHECKBOX_GROUP 1 +#define CHECKBOX_TOGGLE 2 \ No newline at end of file diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index e66d528a5af..42151510587 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -457,6 +457,7 @@ #define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null) #define LAZYLEN(L) length(L) #define LAZYCLEARLIST(L) if(L) L.Cut() +#define SANITIZE_LIST(L) ( islist(L) ? L : list() ) /* Definining a counter as a series of key -> numeric value entries diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index c84475d2c04..8a9c1186686 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -415,68 +415,83 @@ return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y) -/proc/showCandidatePollWindow(mob/dead/observer/G, poll_time, Question, list/candidates, ignore_category, time_passed, flashwindow = TRUE) +/proc/showCandidatePollWindow(mob/M, poll_time, Question, list/candidates, ignore_category, time_passed, flashwindow = TRUE) set waitfor = 0 - G << 'sound/misc/notice2.ogg' //Alerting them to their consideration + M << 'sound/misc/notice2.ogg' //Alerting them to their consideration if(flashwindow) - window_flash(G.client) - switch(ignore_category ? askuser(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time)) + window_flash(M.client) + switch(ignore_category ? askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time)) if(1) - to_chat(G, "Choice registered: Yes.") - if((world.time-time_passed)>poll_time) - to_chat(G, "Sorry, you were too late for the consideration!") - G << 'sound/machines/buzz-sigh.ogg' + to_chat(M, "Choice registered: Yes.") + if(time_passed + poll_time <= world.time) + to_chat(M, "Sorry, you answered too late to be considered!") + M << 'sound/machines/buzz-sigh.ogg' + candidates -= M else - candidates += G + candidates += M if(2) - to_chat(G, "Choice registered: No.") + to_chat(M, "Choice registered: No.") + candidates -= M if(3) var/list/L = GLOB.poll_ignore[ignore_category] if(!L) GLOB.poll_ignore[ignore_category] = list() - GLOB.poll_ignore[ignore_category] += G.ckey - to_chat(G, "Choice registered: Never for this round.") + GLOB.poll_ignore[ignore_category] += M.ckey + to_chat(M, "Choice registered: Never for this round.") + candidates -= M + else + candidates -= M -/proc/pollCandidates(var/Question, var/jobbanType, var/datum/game_mode/gametypeCheck, var/be_special_flag = 0, var/poll_time = 300, var/ignore_category = null, flashwindow = TRUE) - var/list/mob/dead/observer/candidates = list() +/proc/pollGhostCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE) + var/list/candidates = list() + + for(var/mob/dead/observer/G in GLOB.player_list) + candidates += G + + pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates) + + return candidates + +/proc/pollCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE, list/group = null) var/time_passed = world.time if (!Question) Question = "Would you like to be a special role?" - for(var/mob/dead/observer/G in GLOB.player_list) - if(!G.key || !G.client || (ignore_category && GLOB.poll_ignore[ignore_category] && G.ckey in GLOB.poll_ignore[ignore_category])) + for(var/m in group) + var/mob/M = m + if(!M.key || !M.client || (ignore_category && GLOB.poll_ignore[ignore_category] && M.ckey in GLOB.poll_ignore[ignore_category])) continue if(be_special_flag) - if(!(G.client.prefs) || !(be_special_flag in G.client.prefs.be_special)) + if(!(M.client.prefs) || !(be_special_flag in M.client.prefs.be_special)) continue - if (gametypeCheck) - if(!gametypeCheck.age_check(G.client)) + if(gametypeCheck) + if(!gametypeCheck.age_check(M.client)) continue - if (jobbanType) - if(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate")) + if(jobbanType) + if(jobban_isbanned(M, jobbanType) || jobban_isbanned(M, "Syndicate")) continue - showCandidatePollWindow(G, poll_time, Question, candidates, ignore_category, time_passed, flashwindow) + showCandidatePollWindow(M, poll_time, Question, group, ignore_category, time_passed, flashwindow) sleep(poll_time) - //Check all our candidates, to make sure they didn't log off during the wait period. - for(var/mob/dead/observer/G in candidates) - if(!G.key || !G.client) - candidates.Remove(G) + //Check all our candidates, to make sure they didn't log off or get deleted during the wait period. + for(var/mob/M in group) + if(!M.key || !M.client) + group -= M - listclearnulls(candidates) + listclearnulls(group) - return candidates + return group /proc/pollCandidatesForMob(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, mob/M, ignore_category = null) - var/list/L = pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) + var/list/L = pollGhostCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) if(!M || QDELETED(M) || !M.loc) return list() return L /proc/pollCandidatesForMobs(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, list/mobs, ignore_category = null) - var/list/L = pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) + var/list/L = pollGhostCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) var/i=1 for(var/v in mobs) var/atom/A = v @@ -486,64 +501,6 @@ ++i return L -/proc/pollCultists(var/mob/living/Nominee) // Cult Master Poll - var/time_passed = world.time - var/list/yes_voters = new - var/list/cult_total = new - if(world.time < CULT_POLL_WAIT) - Nominee << "It would be premature to select a leader while everyone is still settling in, try again in [round((CULT_POLL_WAIT-world.time)/10)] seconds" - return - for(var/datum/mind/B in SSticker.mode.cult) - var/mob/living/M = B.current - if(!M.incapacitated()) - M << 'sound/hallucinations/im_here1.ogg' - M.verbs -= /mob/living/proc/cult_master - to_chat(M, "Acolyte [Nominee] has asserted that they are worthy of leading the cult. A vote will be called shortly.") - sleep(250) - for(var/datum/mind/B in SSticker.mode.cult) - var/mob/living/M = B.current - if(!M.incapacitated()) - M << 'sound/magic/exit_blood.ogg' - switch(askuser(M,"[Nominee] seeks to lead your cult, do you support them?","Please answer in 20 seconds!","Yes","No","Abstain", StealFocus=0, Timeout=200)) - if(1) - if((world.time-time_passed)>500) - to_chat(M, "Sorry, your vote came too late!") - M << 'sound/machines/buzz-sigh.ogg' - else - M << "Choice registered: Yes." - yes_voters += M - cult_total += M - if(2) - if((world.time-time_passed)>500) - to_chat(M, "Sorry, your vote came too late!") - M << 'sound/machines/buzz-sigh.ogg' - else - to_chat(M, "Choice registered: No.") - cult_total += M - if(3) - to_chat(M, "Choice registered: Abstain.") - sleep(300) - if(yes_voters.len > (cult_total.len/2)) - var/datum/action/innate/cultmast/finalreck/FinalReckoning = new() - var/datum/action/innate/cultmast/cultmark/Mark = new() - FinalReckoning.Grant(Nominee) - Mark.Grant(Nominee) - Nominee.mind.special_role = "Cult Master" - Nominee.update_action_buttons_icon() - Nominee.apply_status_effect(/datum/status_effect/cult_master) - SSticker.mode.set_antag_hud(Nominee,"cultmaster") - GLOB.cult_mastered = TRUE - for(var/datum/mind/B in SSticker.mode.cult) - if(!B.current.incapacitated()) - to_chat(B.current,"[Nominee] has the cult's support and is now their master. Follow their orders to the best of your ability!") - return TRUE - else - for(var/datum/mind/B in SSticker.mode.cult) - if(!B.current.incapacitated()) - to_chat(B.current, "[Nominee] could not win the cult's support and shall continue to serve as an acolyte.") - B.current.verbs += /mob/living/proc/cult_master - return FALSE - /proc/poll_helper(var/mob/living/M) /proc/makeBody(mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character diff --git a/code/_globalvars/game_modes.dm b/code/_globalvars/game_modes.dm index f31e8cf36f9..b0ae638ceed 100644 --- a/code/_globalvars/game_modes.dm +++ b/code/_globalvars/game_modes.dm @@ -6,7 +6,10 @@ GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report // Cult, needs to be global so admin cultists are functional GLOBAL_VAR_INIT(blood_target, null) // Cult Master's target or Construct's Master +GLOBAL_DATUM(blood_target_image, /image) GLOBAL_DATUM(sac_mind, /datum/mind) GLOBAL_VAR_INIT(sac_image, null) +GLOBAL_VAR_INIT(cult_vote_called, FALSE) GLOBAL_VAR_INIT(cult_mastered, FALSE) +GLOBAL_VAR_INIT(reckoning_complete, FALSE) GLOBAL_VAR_INIT(sac_complete, FALSE) \ No newline at end of file diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm index ff6a4edd403..fadd68526d1 100644 --- a/code/_globalvars/lists/poll_ignore.dm +++ b/code/_globalvars/lists/poll_ignore.dm @@ -5,5 +5,6 @@ #define POLL_IGNORE_POSSESSED_BLADE "possessed_blade" #define POLL_IGNORE_ALIEN_LARVA "alien_larva" #define POLL_IGNORE_CLOCKWORK_MARAUDER "clockwork_marauder" +#define POLL_IGNORE_SYNDICATE "syndicate" GLOBAL_LIST_EMPTY(poll_ignore) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 9bda2364623..0c40be56ac5 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -107,64 +107,112 @@ var/obj/item/W = get_active_held_item() - if(W == A) W.attack_self(src) update_inv_hands() return - - // operate three levels deep here (item in backpack in src; item in box in backpack in src, not any deeper) - if(A.ClickAccessible(src, depth=INVENTORY_DEPTH)) - // No adjacency needed + + //These are always reachable. + //User itself, current loc, and user inventory + if(DirectAccess(A)) if(W) - melee_item_attack_chain(src, W, A, params) + melee_item_attack_chain(src,W,A,params) else if(ismob(A)) changeNext_move(CLICK_CD_MELEE) UnarmedAttack(A) return - - if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that + + //Can't reach anything else in lockers or other weirdness + if(!loc.AllowClick()) return - // Allows you to click on a box's contents, if that box is on the ground, but no deeper than that - if(isturf(A) || isturf(A.loc) || (A.loc && isturf(A.loc.loc))) - if(Adjacent(A) || (W && CheckReach(src, A, W.reach))) //Adjacent or reaching attacks - if(W) - melee_item_attack_chain(src, W, A, params) - else - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - UnarmedAttack(A, 1) - return - else // non-adjacent click - if(W) - W.afterattack(A,src,0,params) // 0: not Adjacent - else - RangedAttack(A, params) + //Standard reach turf to turf or reaching inside storage + if(CanReach(A,W)) + if(W) + melee_item_attack_chain(src,W,A,params) + else + if(ismob(A)) + changeNext_move(CLICK_CD_MELEE) + UnarmedAttack(A,1) + else + if(W) + W.afterattack(A,src,0,params) + else + RangedAttack(A,params) -/proc/CheckReach(atom/movable/here, atom/movable/there, reach) +/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE) + if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms + if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks + return TRUE + else + //Things inside storage insde another storage + //Eg Contents of a box in a backpack + var/atom/outer_storage = get_atom_on_turf(target) + if(outer_storage == target) //whatever that is we don't want infinite loop. + return FALSE + if(outer_storage && CanReach(outer_storage,tool) && outer_storage.CanReachStorage(target,src,view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH)) + return TRUE + return FALSE + +//Can [target] in this container be reached by [user], can't be more than [depth] levels deep +/atom/proc/CanReachStorage(atom/target,user,depth) + return FALSE + +/obj/item/weapon/storage/CanReachStorage(atom/target,user,depth) + while(target && depth > 0) + target = target.loc + depth-- + if(target == src) + return TRUE + return FALSE + +/atom/movable/proc/DirectAccess(atom/target) + if(target == src) + return TRUE + if(target == loc) + return TRUE + +/mob/DirectAccess(atom/target) + if(..()) + return TRUE + if(target in contents) //This could probably use moving down and restricting to inventory only + return TRUE + return FALSE + +/mob/living/DirectAccess(atom/target) + if(..()) //Lightweight checks first + return TRUE + if(target in GetAllContents()) + return TRUE + +/atom/proc/AllowClick() + return FALSE + +/turf/AllowClick() + return TRUE + +/proc/CheckToolReach(atom/movable/here, atom/movable/there, reach) if(!here || !there) return switch(reach) if(0) - return here.loc == there.loc + return FALSE if(1) - return here.Adjacent(there) + return FALSE //here.Adjacent(there) if(2 to INFINITY) - var/obj/dummy = new(get_turf(here)) //We'll try to move this every tick, failing if we can't + var/obj/dummy = new(get_turf(here)) dummy.pass_flags |= PASSTABLE + dummy.invisibility = INVISIBILITY_ABSTRACT for(var/i in 1 to reach) //Limit it to that many tries var/turf/T = get_step(dummy, get_dir(dummy, there)) - if(dummy.loc == there.loc) + if(dummy.CanReach(there)) qdel(dummy) - return 1 - if(there.density && dummy in range(1, there)) //For windows and suchlike - qdel(dummy) - return 1 + return TRUE if(!dummy.Move(T)) //we're blocked! qdel(dummy) return + qdel(dummy) // Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click) /mob/proc/DblClickOn(atom/A, params) @@ -304,21 +352,6 @@ /atom/proc/CtrlShiftClick(mob/user) return -/* - Helper to check can the mob click/access an item. - Used by mob inventory and storage items. -*/ -/atom/proc/ClickAccessible(mob/user, depth=1) - if(src == user.loc || (src in user.contents)) - return TRUE - - if(loc && depth > 1) - return loc.ClickAccessible(user, depth-1) - -/turf/ClickAccessible(mob/user, depth=1) - return - - /* Misc helpers diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index b95750009fd..8409c85f4c8 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -265,20 +265,20 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." desc = "Allows you to sense blood that is manipulated by dark magicks." icon_state = "cult_sense" alerttooltipstyle = "cult" - var/image/sacimage + var/static/image/narnar var/angle = 0 var/mob/living/simple_animal/hostile/construct/Cviewer = null /obj/screen/alert/bloodsense/Initialize() - ..() - sacimage = GLOB.sac_image + . = ..() + if(!narnar) + narnar = new('icons/mob/screen_alert.dmi', "mini_nar") START_PROCESSING(SSprocessing, src) /obj/screen/alert/bloodsense/Destroy() - sacimage = null - Cviewer = null - STOP_PROCESSING(SSprocessing, src) - return ..() + Cviewer = null + STOP_PROCESSING(SSprocessing, src) + return ..() /obj/screen/alert/bloodsense/process() var/atom/blood_target @@ -290,36 +290,36 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." if(Cviewer) if(Cviewer.seeking && Cviewer.master) blood_target = Cviewer.master - if(!blood_target && !GLOB.sac_complete) - if(icon_state == "runed_sense0") - return - animate(src, transform = null, time = 1, loop = 0) - angle = 0 - cut_overlays() - icon_state = "runed_sense0" - desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin." - add_overlay(sacimage) - return - if(!blood_target && GLOB.sac_complete) - if(icon_state == "runed_sense1") - return - animate(src, transform = null, time = 1, loop = 0) - angle = 0 - cut_overlays() - icon_state = "runed_sense1" - var/image/narnar = new('icons/mob/screen_alert.dmi', "mini_nar") - desc = "The sacrifice is complete, prepare to summon Nar-Sie!" - add_overlay(narnar) - return if(!blood_target) + if(!GLOB.sac_complete) + if(icon_state == "runed_sense0") + return + animate(src, transform = null, time = 1, loop = 0) + angle = 0 + cut_overlays() + icon_state = "runed_sense0" + desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin." + add_overlay(GLOB.sac_image) + else + if(SSticker.mode.eldergod) + desc = "The sacrifice is complete, prepare to summon Nar-Sie!" + else + desc = "The summoning is complete, glory to Nar-Sie!" + if(icon_state == "runed_sense1") + return + animate(src, transform = null, time = 1, loop = 0) + angle = 0 + cut_overlays() + icon_state = "runed_sense1" + add_overlay(narnar) return var/turf/P = get_turf(blood_target) var/turf/Q = get_turf(mob_viewer) var/area/A = get_area(P) if(P.z != Q.z) //The target is on a different Z level, we cannot sense that far. return - desc = "You are currently tracking [blood_target] in [A.name]" - var/target_angle = Get_Angle(mob_viewer, blood_target) + desc = "You are currently tracking [blood_target] in [A.name]." + var/target_angle = Get_Angle(Q, P) var/target_dist = get_dist(P, Q) cut_overlays() switch(target_dist) diff --git a/code/datums/antagonists/datum_cult.dm b/code/datums/antagonists/datum_cult.dm index 59f165ff376..d5344ccb31e 100644 --- a/code/datums/antagonists/datum_cult.dm +++ b/code/datums/antagonists/datum_cult.dm @@ -1,21 +1,24 @@ /datum/antagonist/cult - var/datum/action/innate/cultcomm/communion = new + var/datum/action/innate/cult/comm/communion = new + var/datum/action/innate/cult/mastervote/vote = new /datum/antagonist/cult/Destroy() - qdel(communion) + QDEL_NULL(communion) + QDEL_NULL(vote) return ..() /datum/antagonist/cult/proc/add_objectives() var/list/target_candidates = list() for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !is_convertable_to_cult(player) && (player != owner) && isliving(player)) + if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && (player != owner) && player.stat != DEAD) target_candidates += player.mind if(target_candidates.len == 0) message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && (player != owner) && isliving(player)) + if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && (player != owner) && player.stat != DEAD) target_candidates += player.mind - if(target_candidates.len > 0) + listclearnulls(target_candidates) + if(LAZYLEN(target_candidates)) GLOB.sac_mind = pick(target_candidates) if(!GLOB.sac_mind) message_admins("Cult Sacrifice: ERROR - Null target chosen!") @@ -33,7 +36,6 @@ GLOB.sac_complete = TRUE SSticker.mode.cult_objectives += "sacrifice" SSticker.mode.cult_objectives += "eldergod" - on_gain() /datum/antagonist/cult/proc/cult_memorization(datum/mind/cult_mind) var/mob/living/current = cult_mind.current @@ -47,7 +49,8 @@ explanation = "The veil has already been weakened here, proceed to the final objective." if("eldergod") explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie' with nine acolytes on it. You must do this after sacrificing your target." - to_chat(current, "Objective #[obj_count]: [explanation]") + if(!silent) + to_chat(current, "Objective #[obj_count]: [explanation]") cult_mind.memory += "Objective #[obj_count]: [explanation]
" /datum/antagonist/cult/can_be_owned(datum/mind/new_owner) @@ -58,16 +61,16 @@ /datum/antagonist/cult/on_gain() . = ..() var/mob/living/current = owner.current - if(SSticker.mode.cult_objectives.len == 0) + if(!LAZYLEN(SSticker.mode.cult_objectives)) add_objectives() - return SSticker.mode.cult += owner // Only add after they've been given objectives cult_memorization(owner) if(jobban_isbanned(current, ROLE_CULTIST)) addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, current, ROLE_CULTIST, ROLE_CULTIST), 0) SSticker.mode.update_cult_icons_added(owner) - current.throw_alert("bloodsense", /obj/screen/alert/bloodsense) current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) + if(GLOB.blood_target && GLOB.blood_target_image && current.client) + current.client.images += GLOB.blood_target_image /datum/antagonist/cult/apply_innate_effects(mob/living/mob_override) . = ..() @@ -75,10 +78,12 @@ if(mob_override) current = mob_override current.faction |= "cult" + current.grant_language(/datum/language/narsie) current.verbs += /mob/living/proc/cult_help if(!GLOB.cult_mastered) - current.verbs += /mob/living/proc/cult_master + vote.Grant(current) communion.Grant(current) + current.throw_alert("bloodsense", /obj/screen/alert/bloodsense) /datum/antagonist/cult/remove_innate_effects(mob/living/mob_override) . = ..() @@ -86,19 +91,60 @@ if(mob_override) current = mob_override current.faction -= "cult" + current.remove_language(/datum/language/narsie) current.verbs -= /mob/living/proc/cult_help + vote.Remove(current) communion.Remove(current) - owner.current.verbs -= /mob/living/proc/cult_master - for(var/datum/action/innate/cultmast/H in owner.current.actions) - qdel(H) current.clear_alert("bloodsense") /datum/antagonist/cult/on_removal() owner.wipe_memory() SSticker.mode.cult -= owner SSticker.mode.update_cult_icons_removed(owner) - to_chat(owner, "An unfamiliar white light flashes through your mind, cleansing the taint of the Dark One and all your memories as its servant.") - owner.current.log_message("Has renounced the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) if(!silent) - owner.current.visible_message("[owner] looks like [owner.current.p_they()] just reverted to their old faith!") + 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!", INDIVIDUAL_ATTACK_LOG) + owner.current.visible_message("[owner.current] looks like [owner.current.p_they()] just reverted to their old faith!") + if(GLOB.blood_target && GLOB.blood_target_image && owner.current.client) + owner.current.client.images -= GLOB.blood_target_image . = ..() + +/datum/antagonist/cult/master + var/datum/action/innate/cult/master/finalreck/reckoning = new + var/datum/action/innate/cult/master/cultmark/bloodmark = new + +/datum/antagonist/cult/master/Destroy() + QDEL_NULL(reckoning) + QDEL_NULL(bloodmark) + return ..() + +/datum/antagonist/cult/master/on_gain() + . = ..() + var/mob/living/current = owner.current + SSticker.mode.set_antag_hud(current, "cultmaster") + +/datum/antagonist/cult/master/greet() + to_chat(owner.current, "You are the cult's Master. As the cult's Master, you have a unique title and loud voice when communicating, are capable of marking \ + targets, such as a location or a noncultist, to direct the cult to them, and, finally, you are capable of summoning the entire living cult to your location once.") + to_chat(owner.current, "Use these abilities to direct the cult to victory at any cost.") + +/datum/antagonist/cult/master/apply_innate_effects(mob/living/mob_override) + . = ..() + var/mob/living/current = owner.current + if(mob_override) + current = mob_override + if(!GLOB.reckoning_complete) + reckoning.Grant(current) + bloodmark.Grant(current) + current.update_action_buttons_icon() + current.apply_status_effect(/datum/status_effect/cult_master) + +/datum/antagonist/cult/master/remove_innate_effects(mob/living/mob_override) + . = ..() + var/mob/living/current = owner.current + if(mob_override) + current = mob_override + reckoning.Remove(current) + bloodmark.Remove(current) + current.update_action_buttons_icon() + current.remove_status_effect(/datum/status_effect/cult_master) diff --git a/code/datums/browser.dm b/code/datums/browser.dm index c30836f198e..62a005b5d96 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -169,7 +169,7 @@ opentime = 0 /datum/browser/alert/proc/wait() - while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout >= world.time)) + while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time)) stoplag() /datum/browser/alert/Topic(href,href_list) diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm index 774e0794ff8..d3427ac983b 100644 --- a/code/datums/shuttles.dm +++ b/code/datums/shuttles.dm @@ -72,7 +72,7 @@ /datum/map_template/shuttle/emergency/meteor suffix = "meteor" - name = "An Asteroid With Engines Strapped To It" + name = "Asteroid With Engines Strapped To It" description = "A hollowed out asteroid with engines strapped to it. Due to its size and difficulty in steering it, this shuttle may damage the docking area." admin_notes = "This shuttle will likely crush escape, killing anyone there." credit_cost = -5000 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 097e9d306de..23deaf99621 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -612,7 +612,9 @@ if(!H.has_language(dt)) return FALSE - else if(H.omnitongue || could_speak_in_language(dt)) + else if(H.omnitongue) + return TRUE + else if(could_speak_in_language(dt) && (!H.only_speaks_language || H.only_speaks_language == dt)) return TRUE else return FALSE @@ -623,7 +625,7 @@ var/datum/language_holder/H = get_language_holder() if(H.selected_default_language) - if(H.has_language(H.selected_default_language)) + if(can_speak_in_language(H.selected_default_language)) return H.selected_default_language else H.selected_default_language = null diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index 2cb5d16503a..cba7ded6316 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -155,7 +155,8 @@ if(!(check_usability(user))) return - var/list/nuke_candidates = pollCandidatesForMob("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, src) + to_chat(user, "You activate [src] and wait for confirmation.") + var/list/nuke_candidates = pollCandidatesForMob("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE, src) if(nuke_candidates.len) if(!(check_usability(user))) return diff --git a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm index abd5866442f..cf709f09b0d 100644 --- a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm +++ b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm @@ -57,7 +57,7 @@ alpha = 75 color = "#FAE48C" light_range = 1.4 - light_power = 0.4 + light_power = 1 light_color = "#FAE48C" sigil_name = "Sigil of Transgression" @@ -96,10 +96,6 @@ sigil_name = "Sigil of Submission" var/glow_type -/obj/effect/clockwork/sigil/submission/New() - ..() - update_light() - /obj/effect/clockwork/sigil/submission/proc/post_channel(mob/living/L) /obj/effect/clockwork/sigil/submission/sigil_effects(mob/living/L) @@ -285,7 +281,7 @@ if(!power_charge) set_light(0) else - set_light(round(alpha*0.02, 1), round(alpha*0.005, 1)) + set_light(max(alpha*0.02, 1.4), max(alpha*0.01, 0.1)) //Vitality Matrix: Drains health from non-servants to heal or even revive servants. /obj/effect/clockwork/sigil/vitality diff --git a/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm b/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm index 1c49d366930..5c1d3fb5fbc 100644 --- a/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm +++ b/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm @@ -180,17 +180,26 @@ return procure_gateway(invoker, time_duration, gateway_uses, two_way) var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk) var/issrcobelisk = istype(src, /obj/structure/destructible/clockwork/powered/clockwork_obelisk) - if(issrcobelisk && !anchored) - to_chat(invoker, "[src] is no longer secured!") - return FALSE + if(issrcobelisk) + if(!anchored) + to_chat(invoker, "[src] is no longer secured!") + return FALSE + var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = src //foolish as I am, how I set this proc up makes substypes unfeasible + if(CO.active) + to_chat(invoker, "[src] is now sustaining a gateway!") + return FALSE if(istargetobelisk) if(!target.anchored) to_chat(invoker, "That [target.name] is no longer secured!") return procure_gateway(invoker, time_duration, gateway_uses, two_way) var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = target + if(CO.active) + to_chat(invoker, "That [target.name] is sustaining a gateway, and cannot recieve another!") + return procure_gateway(invoker, time_duration, gateway_uses, two_way) var/efficiency = CO.get_efficiency_mod() gateway_uses = round(gateway_uses * (2 * efficiency), 1) time_duration = round(time_duration * (2 * efficiency), 1) + CO.active = TRUE //you'd be active in a second but you should update immediately invoker.visible_message("The air in front of [invoker] ripples before suddenly tearing open!", \ "With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [time_duration / 10] seconds and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].") var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir)) diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm index aa1a07ac2f2..21da8fab004 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm @@ -135,7 +135,7 @@ if(!check_special_requirements()) return FALSE to_chat(invoker, "The tendril shivers slightly as it selects a marauder...") - var/list/marauder_candidates = pollCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_CLOCKWORK_MARAUDER) + var/list/marauder_candidates = pollGhostCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_CLOCKWORK_MARAUDER) if(!check_special_requirements()) return FALSE if(!marauder_candidates.len) diff --git a/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm b/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm index 2bebb4c9a5c..580f5fbed5a 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm @@ -58,7 +58,7 @@ var/input = stripped_input(usr, "Please choose a message to send over the Hierophant Network.", "Hierophant Broadcast", "") if(!is_servant_of_ratvar(user) || !input || !user.canUseTopic(src, !issilicon(user))) return - if(anchored) + if(!anchored) to_chat(user, "[src] is no longer secured!") return FALSE if(active) @@ -84,7 +84,8 @@ return if(procure_gateway(user, round(100 * get_efficiency_mod(), 1), round(5 * get_efficiency_mod(), 1), 1)) process() - if(!active) + if(!active) //we won't be active if nobody has sent a gateway to us + active = TRUE clockwork_say(user, text2ratvar("Spatial Gateway, activate!")) return return_power(gateway_cost) //if we didn't return above, ie, successfully create a gateway, we give the power back @@ -92,7 +93,8 @@ /obj/structure/destructible/clockwork/powered/clockwork_obelisk/process() if(!anchored) return - if(locate(/obj/effect/clockwork/spatial_gateway) in loc) + var/obj/effect/clockwork/spatial_gateway/SG = locate(/obj/effect/clockwork/spatial_gateway) + if(SG && SG.timerid) //it's a valid gateway, we're active icon_state = active_icon density = 0 active = TRUE diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 3b30d3e44a6..e5153ffa36b 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -152,12 +152,12 @@ cult_mind.current.Paralyse(5) return 1 -/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = 1, stun) +/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, silent, stun) if(cult_mind.current) var/datum/antagonist/cult/cult_datum = cult_mind.has_antag_datum(ANTAG_DATUM_CULT) if(!cult_datum) return FALSE - cult_datum.silent = show_message + cult_datum.silent = silent cult_datum.on_removal() if(stun) cult_mind.current.Paralyse(5) @@ -187,7 +187,7 @@ if(cult_objectives.Find("eldergod")) cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once if(cult_objectives.Find("sacrifice")) - if(GLOB.sac_mind && GLOB.sac_complete) //if the target has been GLOB.sacrificed, ignore this step. otherwise, add 1 to cult_fail + if(GLOB.sac_mind && !GLOB.sac_complete) //if the target has been GLOB.sacrificed, ignore this step. otherwise, add 1 to cult_fail cult_fail++ return cult_fail //if any objectives aren't met, failure diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index ff8ee97de7e..781714c7166 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -1,19 +1,21 @@ // Contains cult communion, guide, and cult master abilities #define MARK_COOLDOWN -/datum/action/innate/cultcomm - name = "Communion" - button_icon_state = "cult_comms" +/datum/action/innate/cult background_icon_state = "bg_demon" buttontooltipstyle = "cult" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS -/datum/action/innate/cultcomm/IsAvailable() +/datum/action/innate/cult/IsAvailable() if(!iscultist(owner)) - return 0 + return FALSE return ..() -/datum/action/innate/cultcomm/Activate() +/datum/action/innate/cult/comm + name = "Communion" + button_icon_state = "cult_comms" + +/datum/action/innate/cult/comm/Activate() var/input = stripped_input(usr, "Please choose a message to tell to the other acolytes.", "Voice of Blood", "") if(!input || !IsAvailable()) return @@ -24,12 +26,19 @@ var/my_message if(!message) return - user.whisper("O bidai nabora se[pick("'","`")]sma!") + user.whisper("O bidai nabora se[pick("'","`")]sma!", language = /datum/language/common) user.whisper(html_decode(message)) - if (user.mind.special_role == "Cult Master") - my_message = "[(ishuman(user) ? "Master" : "Lord")] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: [message]" - else - my_message = "[(ishuman(user) ? "Acolyte" : "Construct")] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: [message]" + var/title = "Acolyte" + var/span = "cultitalic" + if(user.mind && user.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER)) + span = "cultlarge" + if(ishuman(user)) + title = "Master" + else + title = "Lord" + else if(!ishuman(user)) + title = "Construct" + my_message = "[title] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: [message]" for(var/mob/M in GLOB.mob_list) if(iscultist(M)) to_chat(M, my_message) @@ -77,114 +86,182 @@ set name = "Assert Leadership" pollCultists(src) // This proc handles the distribution of cult master actions -/datum/action/innate/cultmast - background_icon_state = "bg_demon" - buttontooltipstyle = "cult" - check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS +/datum/action/innate/cult/mastervote + name = "Assert Leadership" + button_icon_state = "cultvote" -/datum/action/innate/cultmast/IsAvailable() - if(owner.mind.special_role != "Cult Master") +/datum/action/innate/cult/mastervote/IsAvailable() + if(GLOB.cult_vote_called) + return FALSE + return ..() + +/datum/action/innate/cult/mastervote/Activate() + pollCultists(owner) + +/proc/pollCultists(var/mob/living/Nominee) //Cult Master Poll + if(world.time < CULT_POLL_WAIT) + to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [round((CULT_POLL_WAIT-world.time)/10)] seconds.") + return + GLOB.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current) + B.current.update_action_buttons_icon() + if(!B.current.incapacitated()) + B.current << 'sound/hallucinations/im_here1.ogg' + to_chat(B.current, "Acolyte [Nominee] has asserted that they are worthy of leading the cult. A vote will be called shortly.") + sleep(100) + var/list/asked_cultists = list() + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current && B.current != Nominee && !B.current.incapacitated()) + B.current << 'sound/magic/exit_blood.ogg' + asked_cultists += B.current + var/list/yes_voters = pollCandidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 300, group = asked_cultists) + if(QDELETED(Nominee) || Nominee.incapacitated()) + GLOB.cult_vote_called = FALSE + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current) + B.current.update_action_buttons_icon() + if(!B.current.incapacitated()) + to_chat(B.current,"[Nominee] has died in the process of attempting to win the cult's support!") + return FALSE + if(!Nominee.mind) + GLOB.cult_vote_called = FALSE + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current) + B.current.update_action_buttons_icon() + if(!B.current.incapacitated()) + to_chat(B.current,"[Nominee] has gone catatonic in the process of attempting to win the cult's support!") + return FALSE + if(LAZYLEN(yes_voters) <= LAZYLEN(asked_cultists) * 0.5) + GLOB.cult_vote_called = FALSE + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current) + B.current.update_action_buttons_icon() + if(!B.current.incapacitated()) + to_chat(B.current, "[Nominee] could not win the cult's support and shall continue to serve as an acolyte.") + return FALSE + GLOB.cult_mastered = TRUE + SSticker.mode.remove_cultist(Nominee.mind, FALSE) + Nominee.mind.add_antag_datum(ANTAG_DATUM_CULT_MASTER) + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current) + for(var/datum/action/innate/cult/mastervote/vote in B.current.actions) + vote.Remove(B.current) + if(!B.current.incapacitated()) + 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() + if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER)) return 0 return ..() -/datum/action/innate/cultmast/finalreck +/datum/action/innate/cult/master/finalreck name = "Final Reckoning" - desc = "A single-use spell that brings the entire cult to the master's location" + desc = "A single-use spell that brings the entire cult to the master's location." button_icon_state = "sintouch" -/datum/action/innate/cultmast/finalreck/Activate() - var/list/destinations = list() - for(var/turf/T in orange(1,owner)) - if(istype(T, /turf/open)) - destinations += T +/datum/action/innate/cult/master/finalreck/Activate() for(var/i in 1 to 4) - owner.chant(i) + chant(i) + var/list/destinations = list() + for(var/turf/T in orange(1, owner)) + if(!is_blocked_turf(T, TRUE)) + destinations += T + if(!LAZYLEN(destinations)) + to_chat(owner, "You need more space to summon the cult!") + return if(do_after(owner, 30, target = owner)) for(var/datum/mind/B in SSticker.mode.cult) - var/mob/living/M = B.current - if(isliving(M) && M.stat != DEAD) - var/turf/mobloc = get_turf(M) + if(B.current && B.current.stat != DEAD) + var/turf/mobloc = get_turf(B.current) switch(i) - if (1) - new /obj/effect/overlay/temp/cult/sparks(mobloc, M.dir) + if(1) + new /obj/effect/overlay/temp/cult/sparks(mobloc, B.current.dir) playsound(mobloc, "sparks", 50, 1) - if (2) - new /obj/effect/overlay/temp/dir_setting/cult/phase/out(mobloc, M.dir) + if(2) + new /obj/effect/overlay/temp/dir_setting/cult/phase/out(mobloc, B.current.dir) playsound(mobloc, "sparks", 75, 1) - if (3) - new /obj/effect/overlay/temp/dir_setting/cult/phase(mobloc, M.dir) + if(3) + new /obj/effect/overlay/temp/dir_setting/cult/phase(mobloc, B.current.dir) playsound(mobloc, "sparks", 100, 1) - if (4) + if(4) playsound(mobloc, 'sound/magic/exit_blood.ogg', 100, 1) - if(M != owner) + if(B.current != owner) var/turf/final = pick(destinations) + if(istype(B.current.loc, /obj/item/device/soulstone)) + var/obj/item/device/soulstone/S = B.current.loc + S.release_shades(owner) + B.current.setDir(SOUTH) new /obj/effect/overlay/temp/cult/blood(final) - addtimer(CALLBACK(M, /mob/.proc/reckon, final), 10) - else - for(var/datum/action/innate/cultmast/finalreck/H in owner.actions) - qdel(H) + addtimer(CALLBACK(B.current, /mob/.proc/reckon, final), 10) else return + GLOB.reckoning_complete = TRUE + Remove(owner) -/mob/proc/reckon(var/turf/final) +/mob/proc/reckon(turf/final) new /obj/effect/overlay/temp/cult/blood/out(get_turf(src)) forceMove(final) -/mob/proc/chant(var/i) - switch(i) - if (1) - say("C'arta Forbici!") - if (2) - say("Pleggh E'ntrath!") - playsound(get_turf(src),'sound/magic/clockwork/narsie_attack.ogg', 50, 1) - if (3) - say("Barhah hra Zar'garis!") - playsound(get_turf(src),'sound/magic/clockwork/narsie_attack.ogg', 75, 1) - if (4) - say("N'ath reth Sh'yro eth D'rekkathnor!!!") - playsound(get_turf(src),'sound/magic/clockwork/narsie_attack.ogg', 100, 1) +/datum/action/innate/cult/master/finalreck/proc/chant(chant_number) + switch(chant_number) + if(1) + owner.say("C'arta forbici!", language = /datum/language/common) + if(2) + owner.say("Pleggh e'ntrath!", language = /datum/language/common) + playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 50, 1) + if(3) + owner.say("Barhah hra zar'garis!", language = /datum/language/common) + playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 75, 1) + if(4) + owner.say("N'ath reth sh'yro eth d'rekkathnor!!!", language = /datum/language/common) + playsound(get_turf(owner),'sound/magic/clockwork/narsie_attack.ogg', 100, 1) -/datum/action/innate/cultmast/cultmark +/datum/action/innate/cult/master/cultmark name = "Mark Target" - desc = "Marks a target for the cult" + desc = "Marks a target for the cult." button_icon_state = "cult_mark" var/obj/effect/proc_holder/cultmark/CM - var/time = 0 + var/cooldown = 0 + var/base_cooldown = 1200 -/datum/action/innate/cultmast/cultmark/New() - CM = new() - ..() +/datum/action/innate/cult/master/cultmark/New() + CM = new() + CM.attached_action = src + ..() -/datum/action/innate/cultmast/cultmark/IsAvailable() - if(owner.mind.special_role != "Cult Master") - return 0 - if((world.time - time)<1200 && !CM.active) - owner << "You need to wait [round((1200-(world.time-time))/10)] seconds before you can mark another target!" - return 0 +/datum/action/innate/cult/master/cultmark/IsAvailable() + if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER)) + return FALSE + if(cooldown > world.time) + if(!CM.active) + owner << "You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can mark another target!" + return FALSE return ..() -/datum/action/innate/cultmast/cultmark/Destroy() +/datum/action/innate/cult/master/cultmark/Destroy() QDEL_NULL(CM) return ..() -/datum/action/innate/cultmast/cultmark/Activate() +/datum/action/innate/cult/master/cultmark/Activate() CM.toggle(owner) //the important bit - if(!active) - time = world.time - else - time = 0 return TRUE /obj/effect/proc_holder/cultmark - active = FALSE - ranged_mousepointer = 'icons/effects/cult_target.dmi' + active = FALSE + ranged_mousepointer = 'icons/effects/cult_target.dmi' + var/datum/action/innate/cult/master/cultmark/attached_action +/obj/effect/proc_holder/cultmark/Destroy() + attached_action = null + return ..() /obj/effect/proc_holder/cultmark/proc/toggle(mob/user) - if(active) - remove_ranged_ability("You cease the marking ritual...") - else - add_ranged_ability(user, "You prepare to mark a target for your cult...") + if(active) + remove_ranged_ability("You cease the marking ritual.") + else + add_ranged_ability(user, "You prepare to mark a target for your cult...") /obj/effect/proc_holder/cultmark/InterceptClickOn(mob/living/caller, params, atom/target) if(..()) @@ -196,24 +273,29 @@ if(!isturf(T)) return FALSE if(target in view(7, get_turf(ranged_ability_user))) - remove_ranged_ability(caller, "The marking rite is complete! It will last for 90 seconds.") GLOB.blood_target = target var/area/A = get_area(target) + attached_action.cooldown = world.time + attached_action.base_cooldown + addtimer(CALLBACK(attached_action.owner, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown) + GLOB.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) + GLOB.blood_target_image.appearance_flags = RESET_COLOR + GLOB.blood_target_image.pixel_x = -target.pixel_x + GLOB.blood_target_image.pixel_y = -target.pixel_y for(var/datum/mind/B in SSticker.mode.cult) - var/mob/living/M = B.current - if(M.stat != DEAD) - to_chat(M, "Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!") - M << pick(sound('sound/hallucinations/over_here2.ogg',0,1,75), sound('sound/hallucinations/over_here3.ogg',0,1,75)) - var/image/cult_marker = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) - M.client.images |= cult_marker - addtimer(CALLBACK(M, /mob/living/proc/reset_blood_image, cult_marker), 900, TIMER_OVERRIDE) + if(B.current && B.current.stat != DEAD && B.current.client) + to_chat(B.current, "Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!") + B.current << pick(sound('sound/hallucinations/over_here2.ogg',0,1,75), sound('sound/hallucinations/over_here3.ogg',0,1,75)) + B.current.client.images += GLOB.blood_target_image + attached_action.owner.update_action_buttons_icon() + remove_ranged_ability("The marking rite is complete! It will last for 90 seconds.") + addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target), 900, TIMER_OVERRIDE) return TRUE return FALSE -/mob/living/proc/reset_blood_image(var/image/cult_marker) - if(GLOB.blood_target && src.stat!=DEAD) - to_chat(src,"The blood mark has expired!") - if(client) - client.images.Remove(cult_marker) - QDEL_NULL(cult_marker) - GLOB.blood_target = null \ No newline at end of file +/proc/reset_blood_target() + for(var/datum/mind/B in SSticker.mode.cult) + if(B.current && B.current.stat != DEAD && B.current.client) + if(GLOB.blood_target) + to_chat(B.current,"The blood mark has expired!") + B.current.client.images -= GLOB.blood_target_image + QDEL_NULL(GLOB.blood_target) \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index f3939294636..069a4224800 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -200,7 +200,7 @@ This file contains the arcane tome files. if(!("eldergod" in SSticker.mode.cult_objectives)) to_chat(user, "Nar-Sie does not wish to be summoned!") return - if(GLOB.sac_complete) + if(!GLOB.sac_complete) to_chat(user, "The sacrifice is not complete. The portal would lack the power to open if you tried!") return if(!SSticker.mode.eldergod) @@ -209,7 +209,7 @@ This file contains the arcane tome files. if((loc.z && loc.z != ZLEVEL_STATION) || !A.blob_allowed) to_chat(user, "The Geometer is not interested in lesser locations; the station is the prize!") return - var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No") + var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie; it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No") if(confirm_final == "No") to_chat(user, "You decide to prepare further before scribing the rune.") return diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index b42c55b1618..2f85b5cd7c1 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -29,13 +29,13 @@ To draw a rune, use an arcane tome. var/invocation = "Aiy ele-mayo!" //This is said by cultists when the rune is invoked. var/req_cultists = 1 //The amount of cultists required around the rune to invoke it. If only 1, any cultist can invoke it. var/req_cultists_text //if we have a description override for required cultists to invoke - var/rune_in_use = 0 // Used for some runes, this is for when you want a rune to not be usable when in use. + var/rune_in_use = FALSE // Used for some runes, this is for when you want a rune to not be usable when in use. var/scribe_delay = 50 //how long the rune takes to create var/scribe_damage = 0.1 //how much damage you take doing it - var/allow_excess_invokers = 0 //if we allow excess invokers when being invoked - var/construct_invoke = 1 //if constructs can invoke it + var/allow_excess_invokers = FALSE //if we allow excess invokers when being invoked + var/construct_invoke = TRUE //if constructs can invoke it var/req_keyword = 0 //If the rune requires a keyword - go figure amirite var/keyword //The actual keyword for the rune @@ -136,7 +136,7 @@ structure_check() searches for nearby cultist structures required for the invoca if(invocation) for(var/M in invokers) var/mob/living/L = M - L.say(invocation) + L.say(invocation, language = /datum/language/common) do_invoke_glow() /obj/effect/rune/proc/do_invoke_glow() @@ -229,14 +229,12 @@ structure_check() searches for nearby cultist structures required for the invoca var/obj/item/weapon/paper/paper_to_imbue = papers_on_rune[1] ..() visible_message("Dark power begins to channel into the paper!") - rune_in_use = 1 - if(!do_after(user, initial(talisman_type.creation_time), target = paper_to_imbue)) - rune_in_use = 0 - return - new talisman_type(get_turf(src)) - visible_message("[src] glows with power, and bloody images form themselves on [paper_to_imbue].") - qdel(paper_to_imbue) - rune_in_use = 0 + rune_in_use = TRUE + if(do_after(user, initial(talisman_type.creation_time), target = paper_to_imbue)) + new talisman_type(get_turf(src)) + visible_message("[src] glows with power, and bloody images form themselves on [paper_to_imbue].") + qdel(paper_to_imbue) + rune_in_use = FALSE /obj/effect/rune/imbue/proc/checkpapers() . = list() @@ -250,7 +248,7 @@ structure_check() searches for nearby cultist structures required for the invoca invocation = "Sas'so c'arta forbici!" icon_state = "2" color = "#551A8B" - req_keyword = 1 + req_keyword = TRUE var/listkey /obj/effect/rune/teleport/Initialize(mapload, set_keyword) @@ -297,15 +295,15 @@ structure_check() searches for nearby cultist structures required for the invoca to_chat(user, "The target rune is blocked. Attempting to teleport to it would be massively unwise.") fail_invoke() return - var/movedsomething = 0 - var/moveuserlater = 0 + var/movedsomething = FALSE + var/moveuserlater = FALSE for(var/atom/movable/A in T) if(A == user) - moveuserlater = 1 - movedsomething = 1 + moveuserlater = TRUE + movedsomething = TRUE continue if(!A.anchored) - movedsomething = 1 + movedsomething = TRUE A.forceMove(target) if(movedsomething) ..() @@ -326,7 +324,7 @@ structure_check() searches for nearby cultist structures required for the invoca icon_state = "3" color = "#FFFFFF" req_cultists = 1 - allow_excess_invokers = 1 + allow_excess_invokers = TRUE rune_in_use = FALSE /obj/effect/rune/convert/do_invoke_glow() @@ -450,8 +448,7 @@ structure_check() searches for nearby cultist structures required for the invoca pixel_y = -32 scribe_delay = 450 //how long the rune takes to create scribe_damage = 40.1 //how much damage you take doing it - var/used - var/ignore_gamemode = TRUE + var/used = FALSE /obj/effect/rune/narsie/Initialize(mapload, set_keyword) . = ..() @@ -470,33 +467,20 @@ structure_check() searches for nearby cultist structures required for the invoca if(z != ZLEVEL_STATION) return - var/datum/game_mode/cult/cult_mode - - if(SSticker.mode.name == "cult") - cult_mode = SSticker.mode - - if(!cult_mode && !ignore_gamemode) - for(var/M in invokers) - to_chat(M, "Nar-Sie does not respond!") - fail_invoke() - log_game("Summon Nar-Sie rune failed - gametype is not cult") - return - if(locate(/obj/singularity/narsie) in GLOB.poi_list) for(var/M in invokers) to_chat(M, "Nar-Sie is already on this plane!") log_game("Summon Nar-Sie rune failed - already summoned") return //BEGIN THE SUMMONING - used = 1 + used = TRUE ..() send_to_playing_players('sound/effects/dimensional_rend.ogg') var/turf/T = get_turf(src) sleep(40) if(src) color = "#FF0000" - if(cult_mode) - cult_mode.eldergod = 0 + SSticker.mode.eldergod = FALSE new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed /obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal. @@ -516,7 +500,7 @@ structure_check() searches for nearby cultist structures required for the invoca /obj/effect/rune/raise_dead cultist_name = "Resurrect Cultist" cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived." - invocation = null //Depends on the name of the user - see below + invocation = "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!" //Depends on the name of the user - see below icon_state = "1" color = "#C80000" var/static/revives_used = 0 @@ -556,9 +540,9 @@ structure_check() searches for nearby cultist structures required for the invoca return rune_in_use = 1 if(user.name == "Herbert West") - user.say("To life, to life, I bring them!") + invocation = "To life, to life, I bring them!" else - user.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!") + invocation = initial(invocation) ..() revives_used++ mob_to_revive.revive(1, 1) //This does remove disabilities and such, but the rune might actually see some use because of it! diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index 9645b4bbce8..cd3431406cf 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -28,7 +28,7 @@ . = successfuluse if(successfuluse) //if the calling whatever says we succeed, do the fancy stuff if(invocation) - user.whisper(invocation) + user.whisper(invocation, language = /datum/language/common) if(health_cost && iscarbon(user)) var/mob/living/carbon/C = user C.apply_damage(health_cost, BRUTE, pick("l_arm", "r_arm")) diff --git a/code/game/gamemodes/gang/gang_items.dm b/code/game/gamemodes/gang/gang_items.dm index a8732c10469..c0bb1824b2d 100644 --- a/code/game/gamemodes/gang/gang_items.dm +++ b/code/game/gamemodes/gang/gang_items.dm @@ -108,10 +108,16 @@ /datum/gang_item/weapon/ammo/get_cost_display(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool) return " ↳" + ..() //this is pretty hacky but it looks nice on the popup +/datum/gang_item/weapon/shuriken + name = "Shuriken" + id = "shuriken" + cost = 3 + item_path = /obj/item/weapon/throwing_star + /datum/gang_item/weapon/switchblade name = "Switchblade" id = "switchblade" - cost = 10 + cost = 5 item_path = /obj/item/weapon/switchblade /datum/gang_item/weapon/pistol @@ -125,6 +131,18 @@ id = "pistol_ammo" cost = 10 item_path = /obj/item/ammo_box/magazine/m10mm + +/datum/gang_item/weapon/sniper + name = ".50cal Sniper Rifle" + id = "sniper" + cost = 40 + item_path = /obj/item/weapon/gun/ballistic/automatic/sniper_rifle + +/datum/gang_item/weapon/ammo/sniper_ammo + name = "Standard .50cal Sniper Rounds" + id = "sniper_ammo" + cost = 15 + item_path = /obj/item/ammo_box/magazine/sniper_rounds /datum/gang_item/weapon/uzi name = "Uzi SMG" @@ -138,30 +156,8 @@ id = "uzi_ammo" cost = 40 item_path = /obj/item/ammo_box/magazine/uzim9mm - -//SLEEPING CARP - -/datum/gang_item/weapon/bostaff - name = "Bo Staff" - id = "bostaff" - cost = 10 - item_path = /obj/item/weapon/twohanded/bostaff - -/datum/gang_item/weapon/sleeping_carp_scroll - name = "Sleeping Carp Scroll (one-use)" - id = "sleeping_carp_scroll" - cost = 30 - item_path = /obj/item/weapon/sleeping_carp_scroll - spawn_msg = "Anyone who reads the sleeping carp scroll will learn secrets of the sleeping carp martial arts style." - -/datum/gang_item/weapon/wrestlingbelt - name = "Wrestling Belt" - id = "wrastling_belt" - cost = 20 - item_path = /obj/item/weapon/storage/belt/champion/wrestling - spawn_msg = "Anyone wearing the wresting belt will know how to be effective with wrestling." - - + + /////////////////// //EQUIPMENT /////////////////// @@ -175,6 +171,12 @@ id = "spraycan" cost = 5 item_path = /obj/item/toy/crayon/spraycan/gang + +/datum/gang_item/equipment/sharpener + name = "Sharpener" + id = "whetstone" + cost = 3 + item_path = /obj/item/weapon/sharpener /datum/gang_item/equipment/necklace name = "Gold Necklace" @@ -182,12 +184,31 @@ cost = 1 item_path = /obj/item/clothing/neck/necklace/dope + +/datum/gang_item/equipment/emp + name = "EMP Grenade" + id = "EMP" + cost = 5 + item_path = /obj/item/weapon/grenade/empgrenade + /datum/gang_item/equipment/c4 name = "C4 Explosive" id = "c4" - cost = 10 + cost = 7 item_path = /obj/item/weapon/grenade/plastic/c4 +/datum/gang_item/equipment/frag + name = "Fragmentation Grenade" + id = "frag nade" + cost = 10 + item_path = /obj/item/weapon/grenade/syndieminibomb/concussion/frag + +/datum/gang_item/equipment/stimpack + name = "Black Market Stimulants" + id = "stimpack" + cost = 15 + item_path = /obj/item/weapon/reagent_containers/syringe/stimulants + /datum/gang_item/equipment/implant_breaker name = "Implant Breaker" id = "implant_breaker" diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index b840b64c93e..d3aeef178c1 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -69,6 +69,9 @@ user.Paralyse(5) to_chat(user, "Your body is wracked with debilitating pain!") return + release_shades(user) + +/obj/item/device/soulstone/proc/release_shades(mob/user) for(var/mob/living/simple_animal/shade/A in src) A.status_flags &= ~GODMODE A.canmove = 1 @@ -253,7 +256,7 @@ break if(!chosen_ghost) //Failing that, we grab a ghost - var/list/consenting_candidates = pollCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 50) + var/list/consenting_candidates = pollGhostCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 50) if(consenting_candidates.len) chosen_ghost = pick(consenting_candidates) if(!T) diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index b02f4219562..b9b899b4556 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -118,6 +118,9 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \ var/wetness = 30 //Reduced when exposed to high temperautres var/drying_threshold_temperature = 500 //Kelvin to start drying +/* + * Leather SHeet + */ /obj/item/stack/sheet/leather name = "leather" desc = "The by-product of mob grinding." @@ -125,6 +128,24 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \ icon_state = "sheet-leather" origin_tech = "materials=2" +GLOBAL_LIST_INIT(leather_recipes, list ( \ + new/datum/stack_recipe("wallet", /obj/item/weapon/storage/wallet, 1), \ + new/datum/stack_recipe("muzzle", /obj/item/clothing/mask/muzzle, 2), \ + new/datum/stack_recipe("botany gloves", /obj/item/clothing/gloves/botanic_leather, 3), \ + new/datum/stack_recipe("toolbelt", /obj/item/weapon/storage/belt/utility, 4), \ + new/datum/stack_recipe("leather satchel", /obj/item/weapon/storage/backpack/satchel, 5), \ + new/datum/stack_recipe("bandolier", /obj/item/weapon/storage/belt/bandolier, 5), \ + new/datum/stack_recipe("leather jacket", /obj/item/clothing/suit/jacket/leather, 7), \ + new/datum/stack_recipe("leather overcoat", /obj/item/clothing/suit/jacket/leather/overcoat, 10), \ +)) + +/obj/item/stack/sheet/leather/Initialize(mapload, new_amount, merge = TRUE) + recipes = GLOB.leather_recipes + return ..() + +/* + * Sinew + */ /obj/item/stack/sheet/sinew name = "watcher sinew" icon = 'icons/obj/mining.dmi' @@ -136,11 +157,12 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \ GLOBAL_LIST_INIT(sinew_recipes, list ( \ new/datum/stack_recipe("sinew restraints", /obj/item/weapon/restraints/handcuffs/sinew, 1, on_floor = 1), \ - )) +)) /obj/item/stack/sheet/sinew/Initialize(mapload, new_amount, merge = TRUE) recipes = GLOB.sinew_recipes return ..() + /* * Plates */ @@ -207,4 +229,4 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \ var/obj/item/stack/sheet/leather/HS = new(src.loc) HS.amount = 1 wetness = initial(wetness) - src.use(1) \ No newline at end of file + src.use(1) diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 436bc5ff598..026a120b7ba 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -337,7 +337,7 @@ GLOBAL_LIST_INIT(snow_recipes, list ( \ * Adamantine */ GLOBAL_LIST_INIT(adamantine_recipes, list( - new /datum/stack_recipe("artificial golem shell", /obj/item/golem_shell/artificial, req_amount=1, res_amount=1), + new /datum/stack_recipe("incomplete servant golem shell", /obj/item/golem_shell/servant, req_amount=1, res_amount=1), )) /obj/item/stack/sheet/mineral/adamantine diff --git a/code/game/objects/items/weapons/grenades/plastic.dm b/code/game/objects/items/weapons/grenades/plastic.dm index 20ebcf657a8..3118d731f22 100644 --- a/code/game/objects/items/weapons/grenades/plastic.dm +++ b/code/game/objects/items/weapons/grenades/plastic.dm @@ -96,7 +96,7 @@ to_chat(user, "You start planting the [src]. The timer is set to [det_time]...") - if(do_after(user, 50, target = AM)) + if(do_after(user, 30, target = AM)) if(!user.temporarilyRemoveItemFromInventory(src)) return src.target = AM @@ -274,4 +274,4 @@ icon_state = "plasticx40" item_state = "plasticx4" directional = TRUE - boom_sizes = list(0, 2, 5) \ No newline at end of file + boom_sizes = list(0, 2, 5) diff --git a/code/game/objects/items/weapons/his_grace.dm b/code/game/objects/items/weapons/his_grace.dm index be269d583d8..d8e7dabdf99 100644 --- a/code/game/objects/items/weapons/his_grace.dm +++ b/code/game/objects/items/weapons/his_grace.dm @@ -41,7 +41,7 @@ ..() /obj/item/weapon/his_grace/CtrlClick(mob/user) //you can't pull his grace - attack_hand(user) + return /obj/item/weapon/his_grace/examine(mob/user) ..() diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index aa720f19795..4b5acd949d3 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -214,7 +214,7 @@ possessed = TRUE - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE) var/mob/dead/observer/theghost = null if(LAZYLEN(candidates)) diff --git a/code/game/objects/items/weapons/storage/internal.dm b/code/game/objects/items/weapons/storage/internal.dm index 540ff0f206c..cfdc6cc3547 100644 --- a/code/game/objects/items/weapons/storage/internal.dm +++ b/code/game/objects/items/weapons/storage/internal.dm @@ -5,10 +5,6 @@ w_class = WEIGHT_CLASS_BULKY rustle_jimmies = FALSE -/obj/item/weapon/storage/internal/ClickAccessible(mob/user, depth=1) - if(loc) - return loc.ClickAccessible(user, depth) - /obj/item/weapon/storage/internal/Adjacent(A) if(loc) return loc.Adjacent(A) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 8c4edf19bfc..9399622acdf 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -38,7 +38,7 @@ return // this must come before the screen objects only block, dunno why it wasn't before - if(over_object == M && (src.ClickAccessible(M, depth=STORAGE_VIEW_DEPTH) || Adjacent(M))) + if(over_object == M && M.CanReach(src,view_only = TRUE)) orient2hud(M) if(M.s_active) M.s_active.close(M) diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 3d4cfaee93d..597efa8e120 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -11,8 +11,9 @@ max_integrity = 200 integrity_failure = 50 var/obj/item/showpiece = null - var/alert = 0 - var/open = 0 + var/alert = TRUE + var/open = FALSE + var/openable = TRUE var/obj/item/weapon/electronics/airlock/electronics var/start_showpiece_type = null //add type for items on display @@ -113,7 +114,7 @@ return /obj/structure/displaycase/attackby(obj/item/weapon/W, mob/user, params) - if(W.GetID() && !broken) + if(W.GetID() && !broken && openable) if(allowed(user)) to_chat(user, "You [open ? "close":"open"] the [src]") toggle_lock(user) @@ -132,7 +133,7 @@ else to_chat(user, "[src] is already in good condition!") return - else if(!alert && istype(W,/obj/item/weapon/crowbar)) //Only applies to the lab cage and player made display cases + else if(!alert && istype(W,/obj/item/weapon/crowbar) && openable) //Only applies to the lab cage and player made display cases if(broken) if(showpiece) to_chat(user, "Remove the displayed object first.") @@ -259,6 +260,7 @@ alert = TRUE integrity_failure = 0 + openable = FALSE /obj/structure/displaycase/trophy/Initialize() . = ..() @@ -278,6 +280,8 @@ if(!user.Adjacent(src)) //no TK museology return + if(user.a_intent == INTENT_HARM) + return ..() if(user.is_holding_item_of_type(/obj/item/key/displaycase)) if(added_roundstart) diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index d087b143905..989a2fdeb31 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -48,6 +48,11 @@ /obj/effect/mob_spawn/human/ash_walker/special(mob/living/new_spawn) new_spawn.real_name = random_unique_lizard_name(gender) to_chat(new_spawn, "Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Glory to the Necropolis!") + + new_spawn.grant_language(/datum/language/draconic) + var/datum/language_holder/holder = new_spawn.get_language_holder() + holder.selected_default_language = /datum/language/draconic + if(ishuman(new_spawn)) var/mob/living/carbon/human/H = new_spawn H.underwear = "Nude" @@ -91,7 +96,7 @@ //Golem shells: Spawns in Free Golem ships in lavaland. Ghosts become mineral golems and are advised to spread personal freedom. /obj/effect/mob_spawn/human/golem - name = "inert golem shell" + name = "inert free golem shell" desc = "A humanoid shape, empty, lifeless, and full of potential." mob_name = "a free golem" icon = 'icons/obj/wizard.dmi' @@ -101,13 +106,14 @@ death = FALSE anchored = 0 density = 0 + var/has_owner = FALSE var/can_transfer = TRUE //if golems can switch bodies to this new shell var/mob/living/owner = null //golem's owner if it has one flavour_text = "You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to \ travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \ golems, so that no golem may ever be forced to serve again." -/obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, has_owner = FALSE, mob/creator = null) +/obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null) ..() if(species) name += " ([initial(species.prefix)])" @@ -150,13 +156,15 @@ return ..() +/obj/effect/mob_spawn/human/golem/servant + has_owner = TRUE + name = "inert servant golem shell" + /obj/effect/mob_spawn/human/golem/adamantine - name = "dust-caked golem shell" + name = "dust-caked free golem shell" desc = "A humanoid shape, empty, lifeless, and full of potential." mob_name = "a free golem" - anchored = 1 - density = 1 can_transfer = FALSE mob_species = /datum/species/golem/adamantine diff --git a/code/game/say.dm b/code/game/say.dm index 674f4a1b759..93351137d60 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -62,7 +62,7 @@ GLOBAL_LIST_INIT(freqtospan, list( var/languageicon = "" var/datum/language/D = GLOB.language_datum_instances[message_language] - if(D.display_icon(src)) + if(istype(D) && D.display_icon(src)) languageicon = "[D.get_icon()] " return "[spanpart1][spanpart2][freqpart][languageicon][compose_track_href(speaker, namepart)][namepart][compose_job(speaker, message_language, raw_message, radio_freq)][endspanpart][messagepart]" diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 4c29d87dfa8..618894f2073 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -455,6 +455,8 @@ O = new() O.underlays.Add(T) T.ChangeTurf(type) + for(var/group in decals) + T.add_decal(decals[group],group) if(underlays.len) T.underlays = O.underlays if(T.icon_state != icon_state) diff --git a/code/modules/admin/DB_ban/functions.dm b/code/modules/admin/DB_ban/functions.dm index 37f4ea8835d..86688d8ba7a 100644 --- a/code/modules/admin/DB_ban/functions.dm +++ b/code/modules/admin/DB_ban/functions.dm @@ -71,16 +71,13 @@ computerid = bancid ip = banip - var/datum/DBQuery/query_add_ban_get_id = SSdbcore.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'") - if(!query_add_ban_get_id.warn_execute()) + var/datum/DBQuery/query_add_ban_get_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[ckey]'") + if(!query_add_ban_get_ckey.warn_execute()) return - var/validckey = 0 - if(query_add_ban_get_id.NextRow()) - validckey = 1 - if(!validckey) + if(!query_add_ban_get_ckey.NextRow()) if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key))) - message_admins("[key_name_admin(usr)] attempted to ban [ckey], but [ckey] has not been seen yet. Please only ban actual players.",1) - return + if(alert(usr, "[ckey] has not been seen before, are you sure you want to create a ban for them?", "Unknown ckey", "Yes", "No", "Cancel") != "Yes") + return var/a_ckey var/a_computerid diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index dd6eb90c6f6..0e46bbee97a 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -38,7 +38,10 @@ body += " \[Heal\] " if(M.client) - body += "
\[Player Age: [M.client.player_join_date]\]\[Byond Age: [M.client.account_join_date]\]" + body += "
\[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]" + body += "
Show related accounts by: " + body += "\[ CID | " + body += "IP \]" body += "

\[ " diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 469581f4b77..728db7372cb 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -4,18 +4,12 @@ GLOBAL_PROTECT(admin_verbs_default) GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault()) /world/proc/AVerbsDefault() return list( - /client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/ - /client/proc/toggleannouncelogin, /*toggles if an admin's login is announced during a round*/ /client/proc/deadmin, /*destroys our own admin datum so we can play as a regular player*/ /client/proc/cmd_admin_say, /*admin-only ooc chat*/ /client/proc/hide_verbs, /*hides all our adminverbs*/ /client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/ /client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/ - /client/proc/deadchat, /*toggles deadchat on/off*/ /client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/ - /client/proc/toggleprayers, /*toggles prayers on/off*/ - /client/verb/toggleprayersounds, /*Toggles prayer sounds (HALLELUJAH!)*/ - /client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/ /client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/ /client/proc/secrets, /client/proc/reload_admins, @@ -29,7 +23,6 @@ GLOBAL_PROTECT(admin_verbs_admin) GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin()) /world/proc/AVerbsAdmin() return list( - /client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/ /client/proc/invisimin, /*allows our mob to go invisible/visible*/ // /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ @@ -172,9 +165,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list( /client/proc/set_ooc, /client/proc/reset_ooc, /client/proc/deadmin, - /client/proc/deadchat, - /client/proc/toggleprayers, - /client/proc/toggle_hear_radio, /datum/admins/proc/show_traitor_panel, /datum/admins/proc/toggleenter, /datum/admins/proc/toggleguests, @@ -387,13 +377,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list( mob.invisibility = INVISIBILITY_OBSERVER to_chat(mob, "Invisimin on. You are now as invisible as a ghost.") -/client/proc/player_panel_new() - set name = "Player Panel" - set category = "Admin" - if(holder) - holder.player_panel_new() - SSblackbox.add_details("admin_verb","Player Panel New") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - /client/proc/check_antagonists() set name = "Check Antagonists" set category = "Admin" diff --git a/code/modules/admin/adminmenu.dm b/code/modules/admin/adminmenu.dm new file mode 100644 index 00000000000..fc7a57e212b --- /dev/null +++ b/code/modules/admin/adminmenu.dm @@ -0,0 +1,11 @@ +/datum/menu/Admin/Generate_list(client/C) + if (C.holder) + . = ..() + +/datum/menu/Admin/verb/playerpanel() + set name = "Player Panel" + set desc = "Player Panel" + set category = "Admin" + usr.client.holder.player_panel_new() + SSblackbox.add_details("admin_verb","Player Panel New") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return \ No newline at end of file diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index a126dbb225f..98c26857a25 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2243,3 +2243,20 @@ error_viewer.show_to(owner, locate(href_list["viewruntime_backto"]), href_list["viewruntime_linear"]) else error_viewer.show_to(owner, null, href_list["viewruntime_linear"]) + + else if(href_list["showrelatedacc"]) + var/client/C = locate(href_list["client"]) in GLOB.clients + var/list/thing_to_check + if(href_list["showrelatedacc"] == "cid") + thing_to_check = C.related_accounts_cid + else + thing_to_check = C.related_accounts_ip + thing_to_check = splittext(thing_to_check, ", ") + + + var/dat = "Related accounts by [uppertext(href_list["showrelatedacc"])]:
" + for(var/thing in thing_to_check) + dat += "[thing]
" + + usr << browse(dat, "size=420x300") + diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index d7b06ee9c87..87a9e5a040a 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -132,7 +132,7 @@ /datum/admins/proc/makeWizard() - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard", null) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard", null) var/mob/dead/observer/selected = pick_n_take(candidates) @@ -215,7 +215,7 @@ /datum/admins/proc/makeNukeTeam() var/datum/game_mode/nuclear/temp = new - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp) var/list/mob/dead/observer/chosen = list() var/mob/dead/observer/theghost = null @@ -288,7 +288,7 @@ // DEATH SQUADS /datum/admins/proc/makeDeathsquad() var/mission = input("Assign a mission to the deathsquad", "Assign Mission", "Leave no witnesses.") - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for an elite Nanotrasen Strike Team?", "deathsquad", null) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for an elite Nanotrasen Strike Team?", "deathsquad", null) var/squadSpawned = 0 if(candidates.len >= 2) //Minimum 2 to be considered a squad @@ -396,7 +396,7 @@ /datum/admins/proc/makeOfficial() var/mission = input("Assign a task for the official", "Assign Task", "Conduct a routine preformance review of [station_name()] and its Captain.") - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered to be a Centcom Official?", "deathsquad") + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered to be a Centcom Official?", "deathsquad") if(candidates.len) var/mob/dead/observer/chosen_candidate = pick(candidates) @@ -457,7 +457,7 @@ var/mission = input("Assign a mission to the Emergency Response Team", "Assign Mission", "Assist the station.") as null|text if(!mission) return - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for a Code [alert] Nanotrasen Emergency Response Team?", "deathsquad", null) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a Code [alert] Nanotrasen Emergency Response Team?", "deathsquad", null) var/teamSpawned = 0 if(candidates.len > 0) diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index 1c6c0e3a1ad..a1cba47271a 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -227,7 +227,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation) if(check_exile_implant(C)) say("Rejecting [AM]: Exile implant detected in contained lifeform.") return - if(AM.buckled_mobs.len) + if(AM.has_buckled_mobs()) for(var/mob/living/carbon/C in AM.buckled_mobs) if(check_exile_implant(C)) say("Rejecting [AM]: Exile implant detected in close proximity lifeform.") diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index bb8ccea1379..32cb9dfaa77 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -265,8 +265,8 @@ GLOBAL_LIST(external_rsc_urls) if((global.comms_key == "default_pwd" || length(global.comms_key) <= 6) && global.comms_allowed) //It's the default value or less than 6 characters long, but it somehow didn't disable comms. to_chat(src, "The server's API key is either too short or is the default value! Consider changing it immediately!") - add_verbs_from_config(tdata) - set_client_age_from_db() + add_verbs_from_config() + set_client_age_from_db(tdata) var/cached_player_age = player_age //we have to cache this because other shit may change it and we need it's current value now down below. if (isnum(cached_player_age) && cached_player_age == -1) //first connection player_age = 0 @@ -294,8 +294,6 @@ GLOBAL_LIST(external_rsc_urls) message_admins("[key_name_admin(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].") if (config.irc_first_connection_alert) send2irc_adminless_only("new_byond_user", "[key_name(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].") - else //We failed to get an age for this user, let admins know they need to keep an eye on them - message_admins("Failed to get BYOND account age for [key_name_admin(src)]") get_message_output("watchlist entry", ckey) check_ip_intel() @@ -329,6 +327,26 @@ GLOBAL_LIST(external_rsc_urls) if(!tooltips) tooltips = new /datum/tooltip(src) + var/list/topmenus = GLOB.menulist[/datum/menu] + for (var/thing in topmenus) + var/datum/menu/topmenu = thing + var/topmenuname = "[topmenu]" + if (topmenuname == "[topmenu.type]") + var/list/tree = splittext(topmenuname, "/") + topmenuname = tree[tree.len] + winset(src, "[topmenu.type]", "parent=menu;name=[url_encode(topmenuname)]") + var/list/entries = topmenu.Generate_list(src) + for (var/child in entries) + winset(src, "[url_encode(child)]", "[entries[child]]") + if (!ispath(child, /datum/menu)) + var/atom/verb/verbpath = child + if (copytext(verbpath.name,1,2) != "@") + new child(src) + + for (var/thing in prefs.menuoptions) + var/datum/menu/menuitem = GLOB.menulist[thing] + if (menuitem) + menuitem.Load_checked(src) ////////////// //DISCONNECT// @@ -403,7 +421,7 @@ GLOBAL_LIST(external_rsc_urls) if(!query_client_in_db.NextRow()) new_player = 1 account_join_date = sanitizeSQL(findJoinDate()) - var/datum/DBQuery/query_add_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] VALUES ('[sql_ckey]', Now(), Now(), INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]', [account_join_date ? "'[account_join_date]'" : "NULL"])") + var/datum/DBQuery/query_add_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (`ckey`, `firstseen`, `lastseen`, `ip`, `computerid`, `lastadminrank`, `accountjoindate`) VALUES ('[sql_ckey]', Now(), Now(), INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]', [account_join_date ? "'[account_join_date]'" : "NULL"])") if(!query_add_player.Execute()) return if(!account_join_date) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 19368c7d110..33e2a63f835 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -102,6 +102,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/uplink_spawn_loc = UPLINK_PDA + var/list/menuoptions + /datum/preferences/New(client/C) parent = C custom_names["ai"] = pick(GLOB.ai_names) @@ -124,6 +126,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(!loaded_preferences_successfully) save_preferences() save_character() //let's save this new random character so it doesn't keep generating new ones. + menuoptions = list() return diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 6aaae5f029a..11ed30de4fd 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -1,5 +1,5 @@ //This is the lowest supported version, anything below this is completely obsolete and the entire savefile will be wiped. -#define SAVEFILE_VERSION_MIN 10 +#define SAVEFILE_VERSION_MIN 15 //This is the current version, anything below this will attempt to update (if it's not obsolete) #define SAVEFILE_VERSION_MAX 17 @@ -88,15 +88,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car /datum/preferences/proc/update_preferences(current_version, savefile/S) - if(current_version < 10) - toggles |= MEMBER_PUBLIC - if(current_version < 11) - chat_toggles = TOGGLES_DEFAULT_CHAT - toggles = TOGGLES_DEFAULT - if(current_version < 12) - ignoring = list() - if(current_version < 15) - toggles |= SOUND_ANNOUNCEMENTS //should this proc get fairly long (say 3 versions long), @@ -106,16 +97,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car //It's only really meant to avoid annoying frequent players //if your savefile is 3 months out of date, then 'tough shit'. /datum/preferences/proc/update_character(current_version, savefile/S) - if(pref_species && !(pref_species.id in GLOB.roundstart_species)) - var/rando_race = pick(config.roundstart_races) - pref_species = new rando_race() - - if(current_version < 13 || !istext(backbag)) - switch(backbag) - if(2) - backbag = DSATCHEL - else - backbag = DBACKPACK if(current_version < 16) var/berandom S["userandomjob"] >> berandom @@ -156,12 +137,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["tgui_fancy"] >> tgui_fancy S["tgui_lock"] >> tgui_lock S["windowflash"] >> windowflashing + S["be_special"] >> be_special - if(islist(S["be_special"])) - S["be_special"] >> be_special - else //force update and store the old bitflag version of be_special - needs_update = 11 - S["be_special"] >> old_be_special S["default_slot"] >> default_slot S["chat_toggles"] >> chat_toggles @@ -177,6 +154,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["uses_glasses_colour"]>> uses_glasses_colour S["clientfps"] >> clientfps S["parallax"] >> parallax + S["menuoptions"] >> menuoptions //try to fix any outdated data if necessary if(needs_update >= 0) @@ -199,6 +177,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit)) ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION) ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION) + menuoptions = SANITIZE_LIST(menuoptions) + be_special = SANITIZE_LIST(be_special) + return 1 @@ -235,6 +216,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["uses_glasses_colour"]<< uses_glasses_colour S["clientfps"] << clientfps S["parallax"] << parallax + S["menuoptions"] << menuoptions return 1 @@ -445,7 +427,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car #undef SAVEFILE_VERSION_MAX #undef SAVEFILE_VERSION_MIN -/* + +#ifdef TESTING //DEBUG //Some crude tools for testing savefiles //path is the savefile path @@ -456,4 +439,5 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car /client/verb/savefile_import(path as text) var/savefile/S = new /savefile(path) S.ImportText("/",file("[path].txt")) -*/ + +#endif \ No newline at end of file diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 22155a02039..5ed5980883f 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -1,162 +1,249 @@ +//this works as is to create a single checked item, but has no back end code for toggleing the check yet +#define TOGGLE_CHECKBOX(PARENT, CHILD) PARENT/CHILD/abstract = TRUE;PARENT/CHILD/checkbox = CHECKBOX_TOGGLE;PARENT/CHILD/verb/CHILD + +//Example usage TOGGLE_CHECKBOX(datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)() + +//override because we don't want to save preferences twice. +/datum/menu/Settings/Set_checked(client/C, verbpath) + if (checkbox == CHECKBOX_GROUP) + C.prefs.menuoptions[type] = verbpath + else if (checkbox == CHECKBOX_TOGGLE) + var/checked = Get_checked(C) + C.prefs.menuoptions[type] = !checked + winset(C, "[verbpath]", "is-checked = [!checked]") + +/datum/menu/Settings/verb/setup_character() + set name = "Game Preferences" + set category = "Preferences" + set desc = "Open Game Preferences Window" + usr.client.prefs.current_tab = 1 + usr.client.prefs.ShowChoices(usr) + //toggles -/client/verb/toggle_ghost_ears() +/datum/menu/Settings/Ghost/chatterbox + name = "Chat Box Spam" + +TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)() set name = "Show/Hide GhostEars" set category = "Preferences" - set desc = ".Toggle Between seeing all mob speech, and only speech of nearby mobs" - prefs.chat_toggles ^= CHAT_GHOSTEARS - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].") - prefs.save_preferences() - SSblackbox.add_details("preferences_verb","Toggle Ghost Ears|[prefs.chat_toggles & CHAT_GHOSTEARS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + set desc = "See All Speech" + usr.client.prefs.chat_toggles ^= CHAT_GHOSTEARS + to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].") + usr.client.prefs.save_preferences() + SSblackbox.add_details("preferences_verb","Toggle Ghost Ears|[usr.client.prefs.chat_toggles & CHAT_GHOSTEARS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_ears/Get_checked(client/C) + return C.prefs.chat_toggles & CHAT_GHOSTEARS -/client/verb/toggle_ghost_sight() +TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)() set name = "Show/Hide GhostSight" set category = "Preferences" - set desc = ".Toggle Between seeing all mob emotes, and only emotes of nearby mobs" - prefs.chat_toggles ^= CHAT_GHOSTSIGHT - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].") - prefs.save_preferences() - SSblackbox.add_details("preferences_verb","Toggle Ghost Sight|[prefs.chat_toggles & CHAT_GHOSTSIGHT]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + set desc = "See All Emotes" + usr.client.prefs.chat_toggles ^= CHAT_GHOSTSIGHT + to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].") + usr.client.prefs.save_preferences() + SSblackbox.add_details("preferences_verb","Toggle Ghost Sight|[usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_sight/Get_checked(client/C) + return C.prefs.chat_toggles & CHAT_GHOSTSIGHT -/client/verb/toggle_ghost_whispers() +TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_whispers)() set name = "Show/Hide GhostWhispers" set category = "Preferences" - set desc = ".Toggle between hearing all whispers, and only whispers of nearby mobs" - prefs.chat_toggles ^= CHAT_GHOSTWHISPER - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTWHISPER) ? "see all whispers in the world" : "only see whispers from nearby mobs"].") - prefs.save_preferences() - SSblackbox.add_details("preferences_verb","Toggle Ghost Whispers|[prefs.chat_toggles & CHAT_GHOSTWHISPER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + set desc = "See All Whispers" + usr.client.prefs.chat_toggles ^= CHAT_GHOSTWHISPER + to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER) ? "see all whispers in the world" : "only see whispers from nearby mobs"].") + usr.client.prefs.save_preferences() + SSblackbox.add_details("preferences_verb","Toggle Ghost Whispers|[usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_whispers/Get_checked(client/C) + return C.prefs.chat_toggles & CHAT_GHOSTWHISPER -/client/verb/toggle_ghost_radio() +TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)() set name = "Show/Hide GhostRadio" set category = "Preferences" - set desc = ".Enable or disable hearing radio chatter as a ghost" - prefs.chat_toggles ^= CHAT_GHOSTRADIO - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTRADIO) ? "see radio chatter" : "not see radio chatter"].") - prefs.save_preferences() - SSblackbox.add_details("preferences_verb","Toggle Ghost Radio|[prefs.chat_toggles & CHAT_GHOSTRADIO]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //social experiment, increase the generation whenever you copypaste this shamelessly GENERATION 1 + set desc = "See All Radio Chatter" + usr.client.prefs.chat_toggles ^= CHAT_GHOSTRADIO + to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO) ? "see radio chatter" : "not see radio chatter"].") + usr.client.prefs.save_preferences() + SSblackbox.add_details("preferences_verb","Toggle Ghost Radio|[usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //social experiment, increase the generation whenever you copypaste this shamelessly GENERATION 1 +/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_radio/Get_checked(client/C) + return C.prefs.chat_toggles & CHAT_GHOSTRADIO -/client/verb/toggle_ghost_pda() +TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox, toggle_ghost_pda)() set name = "Show/Hide GhostPDA" set category = "Preferences" - set desc = ".Toggle Between seeing all mob pda messages, and only pda messages of nearby mobs" - prefs.chat_toggles ^= CHAT_GHOSTPDA - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTPDA) ? "see all pda messages in the world" : "only see pda messages from nearby mobs"].") - prefs.save_preferences() - SSblackbox.add_details("preferences_verb","Toggle Ghost PDA|[prefs.chat_toggles & CHAT_GHOSTPDA]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + set desc = "See All PDA Messages" + usr.client.prefs.chat_toggles ^= CHAT_GHOSTPDA + to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTPDA) ? "see all pda messages in the world" : "only see pda messages from nearby mobs"].") + usr.client.prefs.save_preferences() + SSblackbox.add_details("preferences_verb","Toggle Ghost PDA|[usr.client.prefs.chat_toggles & CHAT_GHOSTPDA]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Ghost/chatterbox/toggle_ghost_pda/Get_checked(client/C) + return C.prefs.chat_toggles & CHAT_GHOSTPDA + +/datum/menu/Settings/Ghost/chatterbox/Events + name = "Events" //please be aware that the following two verbs have inverted stat output, so that "Toggle Deathrattle|1" still means you activated it -/client/verb/toggle_deathrattle() +TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox/Events, toggle_deathrattle)() set name = "Toggle Deathrattle" set category = "Preferences" - set desc = "Toggle recieving a message in deadchat when sentient mobs die." - prefs.toggles ^= DISABLE_DEATHRATTLE - prefs.save_preferences() - to_chat(usr, "You will [(prefs.toggles & DISABLE_DEATHRATTLE) ? "no longer" : "now"] get messages when a sentient mob dies.") - SSblackbox.add_details("preferences_verb", "Toggle Deathrattle|[!(prefs.toggles & DISABLE_DEATHRATTLE)]") //If you are copy-pasting this, maybe you should spend some time reading the comments. + set desc = "Death" + usr.client.prefs.toggles ^= DISABLE_DEATHRATTLE + usr.client.prefs.save_preferences() + to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_DEATHRATTLE) ? "no longer" : "now"] get messages when a sentient mob dies.") + SSblackbox.add_details("preferences_verb", "Toggle Deathrattle|[!(usr.client.prefs.toggles & DISABLE_DEATHRATTLE)]") //If you are copy-pasting this, maybe you should spend some time reading the comments. +/datum/menu/Settings/Ghost/chatterbox/Events/toggle_deathrattle/Get_checked(client/C) + return !(C.prefs.toggles & DISABLE_DEATHRATTLE) -/client/verb/toggle_arrivalrattle() +TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost/chatterbox/Events, toggle_arrivalrattle)() set name = "Toggle Arrivalrattle" set category = "Preferences" - set desc = "Toggle recieving a message in deadchat when someone joins the station." - prefs.toggles ^= DISABLE_ARRIVALRATTLE - to_chat(usr, "You will [(prefs.toggles & DISABLE_ARRIVALRATTLE) ? "no longer" : "now"] get messages when someone joins the station.") - prefs.save_preferences() - SSblackbox.add_details("preferences_verb", "Toggle Arrivalrattle|[!(prefs.toggles & DISABLE_ARRIVALRATTLE)]") //If you are copy-pasting this, maybe you should rethink where your life went so wrong. + set desc = "New Player Arrival" + usr.client.prefs.toggles ^= DISABLE_ARRIVALRATTLE + to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE) ? "no longer" : "now"] get messages when someone joins the station.") + usr.client.prefs.save_preferences() + SSblackbox.add_details("preferences_verb", "Toggle Arrivalrattle|[!(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE)]") //If you are copy-pasting this, maybe you should rethink where your life went so wrong. +/datum/menu/Settings/Ghost/chatterbox/Events/toggle_arrivalrattle/Get_checked(client/C) + return !(C.prefs.toggles & DISABLE_ARRIVALRATTLE) -/client/verb/togglemidroundantag() +TOGGLE_CHECKBOX(/datum/menu/Settings/Ghost, togglemidroundantag)() set name = "Toggle Midround Antagonist" set category = "Preferences" - set desc = "Toggles whether or not you will be considered for antagonist status given during a round." - prefs.toggles ^= MIDROUND_ANTAG - prefs.save_preferences() - to_chat(src, "You will [(prefs.toggles & MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions.") - SSblackbox.add_details("preferences_verb","Toggle Midround Antag|[prefs.toggles & MIDROUND_ANTAG]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + set desc = "Midround Antagonist" + usr.client.prefs.toggles ^= MIDROUND_ANTAG + usr.client.prefs.save_preferences() + to_chat(usr, "You will [(usr.client.prefs.toggles & MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions.") + SSblackbox.add_details("preferences_verb","Toggle Midround Antag|[usr.client.prefs.toggles & MIDROUND_ANTAG]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Ghost/togglemidroundantag/Get_checked(client/C) + return C.prefs.toggles & MIDROUND_ANTAG -/client/verb/toggletitlemusic() +TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggletitlemusic)() set name = "Hear/Silence LobbyMusic" set category = "Preferences" - set desc = "Toggles hearing the GameLobby music" - prefs.toggles ^= SOUND_LOBBY - prefs.save_preferences() - if(prefs.toggles & SOUND_LOBBY) - to_chat(src, "You will now hear music in the game lobby.") - if(isnewplayer(mob)) - playtitlemusic() + set desc = "Hear Music In Lobby" + usr.client.prefs.toggles ^= SOUND_LOBBY + usr.client.prefs.save_preferences() + if(usr.client.prefs.toggles & SOUND_LOBBY) + to_chat(usr, "You will now hear music in the game lobby.") + if(isnewplayer(usr)) + usr.client.playtitlemusic() else - to_chat(src, "You will no longer hear music in the game lobby.") - mob.stop_sound_channel(CHANNEL_LOBBYMUSIC) - SSblackbox.add_details("preferences_verb","Toggle Lobby Music|[prefs.toggles & SOUND_LOBBY]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + to_chat(usr, "You will no longer hear music in the game lobby.") + usr.stop_sound_channel(CHANNEL_LOBBYMUSIC) + SSblackbox.add_details("preferences_verb","Toggle Lobby Music|[usr.client.prefs.toggles & SOUND_LOBBY]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Sound/toggletitlemusic/Get_checked(client/C) + return C.prefs.toggles & SOUND_LOBBY -/client/verb/togglemidis() + +TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, togglemidis)() set name = "Hear/Silence Midis" set category = "Preferences" - set desc = "Toggles hearing sounds uploaded by admins" - prefs.toggles ^= SOUND_MIDI - prefs.save_preferences() - if(prefs.toggles & SOUND_MIDI) - to_chat(src, "You will now hear any sounds uploaded by admins.") + set desc = "Hear Admin Triggered Sounds (Midis)" + usr.client.prefs.toggles ^= SOUND_MIDI + usr.client.prefs.save_preferences() + if(usr.client.prefs.toggles & SOUND_MIDI) + to_chat(usr, "You will now hear any sounds uploaded by admins.") else - to_chat(src, "You will no longer hear sounds uploaded by admins") - mob.stop_sound_channel(CHANNEL_ADMIN) - SSblackbox.add_details("preferences_verb","Toggle Hearing Midis|[prefs.toggles & SOUND_MIDI]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + to_chat(usr, "You will no longer hear sounds uploaded by admins") + usr.stop_sound_channel(CHANNEL_ADMIN) + SSblackbox.add_details("preferences_verb","Toggle Hearing Midis|[usr.client.prefs.toggles & SOUND_MIDI]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Sound/togglemidis/Get_checked(client/C) + return C.prefs.toggles & SOUND_MIDI -/client/verb/stop_client_sounds() - set name = "Stop Sounds" - set category = "Preferences" - set desc = "Kills all currently playing sounds, use if admin taste in midis a shite" - src << sound(null) - SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/verb/listen_ooc() - set name = "Show/Hide OOC" - set category = "Preferences" - set desc = "Toggles seeing OutOfCharacter chat" - prefs.chat_toggles ^= CHAT_OOC - prefs.save_preferences() - to_chat(src, "You will [(prefs.chat_toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.") - SSblackbox.add_details("preferences_verb","Toggle Seeing OOC|[prefs.chat_toggles & CHAT_OOC]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/Toggle_Soundscape() //All new ambience should be added here so it works with this verb until someone better at things comes up with a fix that isn't awful - set name = "Hear/Silence Ambience" - set category = "Preferences" - set desc = "Toggles hearing ambient sound effects" - prefs.toggles ^= SOUND_AMBIENCE - prefs.save_preferences() - if(prefs.toggles & SOUND_AMBIENCE) - to_chat(src, "You will now hear ambient sounds.") - else - to_chat(src, "You will no longer hear ambient sounds.") - src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1) - src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2) - SSblackbox.add_details("preferences_verb","Toggle Ambience|[prefs.toggles & SOUND_AMBIENCE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -// This needs a toggle because you people are awful and spammed terrible music -/client/verb/toggle_instruments() +TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_instruments)() set name = "Hear/Silence Instruments" set category = "Preferences" - set desc = "Toggles hearing musical instruments like the violin and piano" - prefs.toggles ^= SOUND_INSTRUMENTS - prefs.save_preferences() - if(prefs.toggles & SOUND_INSTRUMENTS) - to_chat(src, "You will now hear people playing musical instruments.") + set desc = "Hear In-game Instruments" + usr.client.prefs.toggles ^= SOUND_INSTRUMENTS + usr.client.prefs.save_preferences() + if(usr.client.prefs.toggles & SOUND_INSTRUMENTS) + to_chat(usr, "You will now hear people playing musical instruments.") else - to_chat(src, "You will no longer hear musical instruments.") - SSblackbox.add_details("preferences_verb","Toggle Instruments|[prefs.toggles & SOUND_INSTRUMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + to_chat(usr, "You will no longer hear musical instruments.") + SSblackbox.add_details("preferences_verb","Toggle Instruments|[usr.client.prefs.toggles & SOUND_INSTRUMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Sound/toggle_instruments/Get_checked(client/C) + return C.prefs.toggles & SOUND_INSTRUMENTS -//Lots of people get headaches from the normal ship ambience, this is to prevent that -/client/verb/toggle_ship_ambience() + +TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, Toggle_Soundscape)() + set name = "Hear/Silence Ambience" + set category = "Preferences" + set desc = "Hear Ambient Sound Effects" + usr.client.prefs.toggles ^= SOUND_AMBIENCE + usr.client.prefs.save_preferences() + if(usr.client.prefs.toggles & SOUND_AMBIENCE) + to_chat(usr, "You will now hear ambient sounds.") + else + to_chat(usr, "You will no longer hear ambient sounds.") + usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1) + usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2) + SSblackbox.add_details("preferences_verb","Toggle Ambience|[usr.client.prefs.toggles & SOUND_AMBIENCE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Sound/Toggle_Soundscape/Get_checked(client/C) + return C.prefs.toggles & SOUND_AMBIENCE + + +TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_ship_ambience)() set name = "Hear/Silence Ship Ambience" set category = "Preferences" - set desc = "Toggles hearing generalized ship ambience, no matter your area." - prefs.toggles ^= SOUND_SHIP_AMBIENCE - prefs.save_preferences() - if(prefs.toggles & SOUND_SHIP_AMBIENCE) - to_chat(src, "You will now hear ship ambience.") + set desc = "Hear Ship Ambience Roar" + usr.client.prefs.toggles ^= SOUND_SHIP_AMBIENCE + usr.client.prefs.save_preferences() + if(usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE) + to_chat(usr, "You will now hear ship ambience.") else - to_chat(src, "You will no longer hear ship ambience.") - src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2) - src.ambience_playing = 0 - SSblackbox.add_details("preferences_verb", "Toggle Ship Ambience|[prefs.toggles & SOUND_SHIP_AMBIENCE]") //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^) + to_chat(usr, "You will no longer hear ship ambience.") + usr << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2) + usr.client.ambience_playing = 0 + SSblackbox.add_details("preferences_verb", "Toggle Ship Ambience|[usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE]") //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^) +/datum/menu/Settings/Sound/toggle_ship_ambience/Get_checked(client/C) + return C.prefs.toggles & SOUND_SHIP_AMBIENCE + + +TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggle_announcement_sound)() + set name = "Hear/Silence Announcements" + set category = "Preferences" + set desc = "Hear Announcement Sound" + usr.client.prefs.toggles ^= SOUND_ANNOUNCEMENTS + to_chat(usr, "You will now [(usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS) ? "hear announcement sounds" : "no longer hear announcements"].") + usr.client.prefs.save_preferences() + SSblackbox.add_details("preferences_verb","Toggle Announcement Sound|[usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/Sound/toggle_announcement_sound/Get_checked(client/C) + return C.prefs.toggles & SOUND_ANNOUNCEMENTS + + +TOGGLE_CHECKBOX(/datum/menu/Settings/Sound, toggleprayersounds)() + set name = "Hear/Silence Prayer Sounds" + set category = "Preferences" + set desc = "Hear Prayer Sounds" + usr.client.prefs.toggles ^= SOUND_PRAYERS + usr.client.prefs.save_preferences() + if(usr.client.prefs.toggles & SOUND_PRAYERS) + to_chat(usr, "You will now hear prayer sounds.") + else + to_chat(usr, "You will no longer prayer sounds.") + SSblackbox.add_details("admin_toggle", "Toggle Prayer Sounds|[usr.client.prefs.toggles & SOUND_PRAYERS]") +/datum/menu/Settings/Sound/toggleprayersounds/Get_checked(client/C) + return C.prefs.toggles & SOUND_PRAYERS + + +/datum/menu/Settings/Sound/verb/stop_client_sounds() + set name = "Stop Sounds" + set category = "Preferences" + set desc = "Stop Current Sounds" + usr << sound(null) + SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +TOGGLE_CHECKBOX(/datum/menu/Settings, listen_ooc)() + set name = "Show/Hide OOC" + set category = "Preferences" + set desc = "Show OOC Chat" + usr.client.prefs.chat_toggles ^= CHAT_OOC + usr.client.prefs.save_preferences() + to_chat(usr, "You will [(usr.client.prefs.chat_toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.") + SSblackbox.add_details("preferences_verb","Toggle Seeing OOC|[usr.client.prefs.chat_toggles & CHAT_OOC]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/menu/Settings/listen_ooc/Get_checked(client/C) + return C.prefs.chat_toggles & CHAT_OOC + GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \ "ghost_blue","ghost_yellow","ghost_green","ghost_pink", \ @@ -246,13 +333,6 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS prefs.save_preferences() SSblackbox.add_details("preferences_verb","Toggle Intent Selection|[prefs.toggles & INTENT_STYLE]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/verb/setup_character() - set name = "Game Preferences" - set category = "Preferences" - set desc = "Allows you to access the Setup Character screen. Changes to your character won't take effect until next round, but other changes will." - prefs.current_tab = 1 - prefs.ShowChoices(usr) - /client/verb/toggle_ghost_hud_pref() set name = "Toggle Ghost HUD" set category = "Preferences" @@ -278,15 +358,6 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS to_chat(src, "You will no longer examine things you click on.") SSblackbox.add_details("preferences_verb","Toggle Ghost Inquisitiveness|[prefs.inquisitive_ghost]") -/client/verb/toggle_announcement_sound() - set name = "Hear/Silence Announcements" - set category = "Preferences" - set desc = ".Toggles hearing Central Command, Captain, VOX, and other announcement sounds" - prefs.toggles ^= SOUND_ANNOUNCEMENTS - to_chat(src, "You will now [(prefs.toggles & SOUND_ANNOUNCEMENTS) ? "hear announcement sounds" : "no longer hear announcements"].") - prefs.save_preferences() - SSblackbox.add_details("preferences_verb","Toggle Announcement Sound|[prefs.toggles & SOUND_ANNOUNCEMENTS]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - //Admin Preferences /client/proc/toggleadminhelpsound() set name = "Hear/Silence Adminhelps" @@ -338,14 +409,3 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.") SSblackbox.add_details("admin_toggle","Toggle Prayer Visibility|[prefs.chat_toggles & CHAT_PRAYER]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/verb/toggleprayersounds() - set name = "Hear/Silence Prayer Sounds" - set category = "Preferences" - set desc = "Toggles hearing pray sounds." - prefs.toggles ^= SOUND_PRAYERS - prefs.save_preferences() - if(prefs.toggles & SOUND_PRAYERS) - to_chat(src, "You will now hear prayer sounds.") - else - to_chat(src, "You will no longer prayer sounds.") - SSblackbox.add_details("admin_toggle", "Toggle Prayer Sounds|[prefs.toggles & SOUND_PRAYERS]") diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 0994c2f1777..f287870ef65 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -161,7 +161,9 @@ /obj/item/clothing/obj_break(damage_flag) if(!damaged_clothes) update_clothes_damaged_state(TRUE) - to_chat(usr, "Your [src] starts to fall apart!") + if(ismob(loc)) //It's not important enough to warrant a message if nobody's wearing it + var/mob/M = loc + M.visible_message("[M]'s [name] starts to fall apart!", "Your [name] starts to fall apart!") /obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE) var/index = "\ref[initial(icon)]-[initial(icon_state)]" diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm index 479ad777420..b1c0bb325d7 100644 --- a/code/modules/clothing/spacesuits/flightsuit.dm +++ b/code/modules/clothing/spacesuits/flightsuit.dm @@ -663,6 +663,9 @@ flight = FALSE if(suit.shoes) suit.shoes.toggle(FALSE) + if(isturf(wearer.loc)) + var/turf/T = wearer.loc + T.Entered(src) else if(override_safe) disable_flight(TRUE) diff --git a/code/modules/events/ghost_role.dm b/code/modules/events/ghost_role.dm index 93eff54b270..2468ddb5c6a 100644 --- a/code/modules/events/ghost_role.dm +++ b/code/modules/events/ghost_role.dm @@ -59,7 +59,7 @@ var/list/mob/dead/observer/regular_candidates // don't get their hopes up if(priority_candidates.len < minimum_required) - regular_candidates = pollCandidates("Do you wish to be considered for the special role of '[role_name]'?", jobban, gametypecheck, be_special) + regular_candidates = pollGhostCandidates("Do you wish to be considered for the special role of '[role_name]'?", jobban, gametypecheck, be_special) else regular_candidates = list() diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 1b41cd45cd5..705c532260e 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -15,12 +15,21 @@ var/max_n_of_items = 1500 var/icon_on = "smartfridge" var/icon_off = "smartfridge-off" + var/list/initial_contents /obj/machinery/smartfridge/Initialize() ..() create_reagents() reagents.set_reacting(FALSE) + if(islist(initial_contents)) + for(var/typekey in initial_contents) + var/amount = initial_contents[typekey] + if(isnull(amount)) + amount = 1 + for(var/i in 1 to amount) + load(new typekey(src)) + var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/smartfridge(null) B.apply_default_parts(src) @@ -51,7 +60,7 @@ else return ..() -/obj/item/weapon/circuitboard/machine/smartfridge/examine/(mob/user) +/obj/item/weapon/circuitboard/machine/smartfridge/examine(mob/user) ..() to_chat(user, "[src] is set to [fridges[build_path]]. You can use a screwdriver to reconfigure it.") @@ -384,12 +393,8 @@ return TRUE return FALSE -/obj/machinery/smartfridge/extract/New() - ..() - var/obj/item/device/slime_scanner/I = new /obj/item/device/slime_scanner(src) - load(I) - var/obj/item/device/slime_scanner/T = new /obj/item/device/slime_scanner(src) - load(T) +/obj/machinery/smartfridge/extract/preloaded + initial_contents = list(/obj/item/device/slime_scanner = 2) // ----------------------------- // Chemistry Medical Smartfridge @@ -397,21 +402,6 @@ /obj/machinery/smartfridge/chemistry name = "smart chemical storage" desc = "A refrigerated storage unit for medicine storage." - var/list/spawn_meds = list( - /obj/item/weapon/reagent_containers/pill/epinephrine = 12, - /obj/item/weapon/reagent_containers/pill/charcoal = 5, - /obj/item/weapon/reagent_containers/glass/bottle/epinephrine = 1, - /obj/item/weapon/reagent_containers/glass/bottle/charcoal = 1) - -/obj/machinery/smartfridge/chemistry/New() - ..() - for(var/typekey in spawn_meds) - var/amount = spawn_meds[typekey] - if(isnull(amount)) amount = 1 - while(amount) - var/obj/item/I = new typekey(src) - load(I) - amount-- /obj/machinery/smartfridge/chemistry/accept_check(obj/item/O) if(istype(O,/obj/item/weapon/storage/pill_bottle)) @@ -431,13 +421,22 @@ return TRUE return FALSE +/obj/machinery/smartfridge/chemistry/preloaded + initial_contents = list( + /obj/item/weapon/reagent_containers/pill/epinephrine = 12, + /obj/item/weapon/reagent_containers/pill/charcoal = 5, + /obj/item/weapon/reagent_containers/glass/bottle/epinephrine = 1, + /obj/item/weapon/reagent_containers/glass/bottle/charcoal = 1) + // ---------------------------- // Virology Medical Smartfridge // ---------------------------- /obj/machinery/smartfridge/chemistry/virology name = "smart virus storage" desc = "A refrigerated storage unit for volatile sample storage." - spawn_meds = list( + +/obj/machinery/smartfridge/chemistry/virology/preloaded + initial_contents = list( /obj/item/weapon/reagent_containers/syringe/antiviral = 4, /obj/item/weapon/reagent_containers/glass/bottle/cold = 1, /obj/item/weapon/reagent_containers/glass/bottle/flu_virion = 1, diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm index 264261dd69b..82cc192344b 100644 --- a/code/modules/hydroponics/grown/nettle.dm +++ b/code/modules/hydroponics/grown/nettle.dm @@ -50,17 +50,22 @@ /obj/item/weapon/grown/nettle/pickup(mob/living/user) ..() if(!iscarbon(user)) - return 0 + return FALSE var/mob/living/carbon/C = user if(C.gloves) - return 0 + return FALSE + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(H.dna && H.dna.species) + if(PIERCEIMMUNE in H.dna.species.species_traits) + return FALSE var/hit_zone = (C.held_index_to_dir(C.active_hand_index) == "l" ? "l_":"r_") + "arm" var/obj/item/bodypart/affecting = C.get_bodypart(hit_zone) if(affecting) if(affecting.receive_damage(0, force)) C.update_damage_overlays() to_chat(C, "The nettle burns your bare hand!") - return 1 + return TRUE /obj/item/weapon/grown/nettle/afterattack(atom/A as mob|obj, mob/user,proximity) if(!proximity) return diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm index 2f01cd06e0a..55a57de9941 100644 --- a/code/modules/language/language.dm +++ b/code/modules/language/language.dm @@ -1,4 +1,4 @@ -#define SCRAMBLE_CACHE_LEN 20 +#define SCRAMBLE_CACHE_LEN 50 //maximum of 50 specific scrambled lines per language /* Datum based languages. Easily editable and modular. @@ -16,10 +16,10 @@ // If key is null, then the language isn't real or learnable. var/flags // Various language flags. var/list/syllables // Used when scrambling text for a non-speaker. - var/list/sentence_chance = 5 // Likelihood of making a new sentence after each syllable. - var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string + var/sentence_chance = 5 // Likelihood of making a new sentence after each syllable. + var/space_chance = 55 // Likelihood of getting a space in the random scramble string var/list/spans = list() - var/static/list/scramble_cache = list() + var/list/scramble_cache = list() var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default. // if you are seeing someone speak popcorn language, then something is wrong. diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index cd0ce23b23f..c8ba5094000 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -87,6 +87,10 @@ languages = list(/datum/language/common, /datum/language/ratvar) only_speaks_language = /datum/language/ratvar +/datum/language_holder/construct + languages = list(/datum/language/common, /datum/language/narsie) + only_speaks_language = /datum/language/narsie + /datum/language_holder/drone languages = list(/datum/language/common, /datum/language/drone, /datum/language/machine) only_speaks_language = /datum/language/drone diff --git a/code/modules/language/language_menu.dm b/code/modules/language/language_menu.dm index 87fc1e0d528..3a30c6c11a6 100644 --- a/code/modules/language/language_menu.dm +++ b/code/modules/language/language_menu.dm @@ -76,7 +76,7 @@ switch(action) if("select_default") - if(language_datum) + if(language_datum && AM.can_speak_in_language(language_datum)) language_holder.selected_default_language = language_datum . = TRUE if("grant_language") diff --git a/code/modules/language/narsian.dm b/code/modules/language/narsian.dm new file mode 100644 index 00000000000..70966ad8802 --- /dev/null +++ b/code/modules/language/narsian.dm @@ -0,0 +1,43 @@ +/datum/language/narsie + name = "Nar-Sian" + desc = "The ancient, blood-soaked, impossibly complex language of Nar-Sian cultists." + speech_verb = "intones" + ask_verb = "inquires" + exclaim_verb = "invokes" + key = "n" + sentence_chance = 8 + space_chance = 95 //very high due to the potential length of each syllable + var/static/list/base_syllables = list( + "h", "v", "c", "e", "g", "d", "r", "n", "h", "o", "p", + "ra", "so", "at", "il", "ta", "gh", "sh", "ya", "te", "sh", "ol", "ma", "om", "ig", "ni", "in", + "sha", "mir", "sas", "mah", "zar", "tok", "lyr", "nqa", "nap", "olt", "val", "qha", + "fwe", "ath", "yro", "eth", "gal", "gib", "bar", "jin", "kla", "atu", "kal", "lig", + "yoka", "drak", "loso", "arta", "weyh", "ines", "toth", "fara", "amar", "nyag", "eske", "reth", "dedo", "btoh", "nikt", "neth", + "kanas", "garis", "uloft", "tarat", "khari", "thnor", "rekka", "ragga", "rfikk", "harfr", "andid", "ethra", "dedol", "totum", + "ntrath", "keriam" + ) //the list of syllables we'll combine with itself to get a larger list of syllables + syllables = list( + "sha", "mir", "sas", "mah", "hra", "zar", "tok", "lyr", "nqa", "nap", "olt", "val", + "yam", "qha", "fel", "det", "fwe", "mah", "erl", "ath", "yro", "eth", "gal", "mud", + "gib", "bar", "tea", "fuu", "jin", "kla", "atu", "kal", "lig", + "yoka", "drak", "loso", "arta", "weyh", "ines", "toth", "fara", "amar", "nyag", "eske", "reth", "dedo", "btoh", "nikt", "neth", "abis", + "kanas", "garis", "uloft", "tarat", "khari", "thnor", "rekka", "ragga", "rfikk", "harfr", "andid", "ethra", "dedol", "totum", + "verbot", "pleggh", "ntrath", "barhah", "pasnar", "keriam", "usinar", "savrae", "amutan", "tannin", "remium", "barada", + "forbici" + ) //the base syllables, which include a few rare ones that won't appear in the mixed syllables + icon_state = "narsie" + default_priority = 10 + +/datum/language/narsie/New() + for(var/syllable in base_syllables) //we only do this once, since there's only ever a single one of each language datum. + for(var/target_syllable in base_syllables) + if(syllable != target_syllable) //don't combine with yourself + if(length(syllable) + length(target_syllable) > 8) //if the resulting syllable would be very long, don't put anything between it + syllables += "[syllable][target_syllable]" + else if(prob(80)) //we'll be minutely different each round. + syllables += "[syllable]'[target_syllable]" + else if(prob(25)) //5% chance of - instead of ' + syllables += "[syllable]-[target_syllable]" + else //15% chance of no ' or - at all + syllables += "[syllable][target_syllable]" + ..() diff --git a/code/modules/language/ratvar.dm b/code/modules/language/ratvarian.dm similarity index 51% rename from code/modules/language/ratvar.dm rename to code/modules/language/ratvarian.dm index cef4a3164ec..b924d2fc79d 100644 --- a/code/modules/language/ratvar.dm +++ b/code/modules/language/ratvarian.dm @@ -1,14 +1,19 @@ /datum/language/ratvar name = "Ratvarian" desc = "A timeless language full of power and incomprehensible to the unenlightened." - speech_verb = "clinks" - ask_verb = "clunks" - exclaim_verb = "clanks" + var/static/random_speech_verbs = list("clanks", "clinks", "clunks", "clangs") + ask_verb = "requests" + exclaim_verb = "proclaims" + whisper_verb = "imparts" key = "r" default_priority = 10 spans = list(SPAN_ROBOT) - icon_state = "ratvar" /datum/language/ratvar/scramble(var/input) . = text2ratvar(input) + +/datum/language/ratvar/get_spoken_verb(msg_end) + if(!msg_end) + return pick(random_speech_verbs) + return ..() \ No newline at end of file diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index ca8b8f2d9d5..8d842d8a48d 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -31,8 +31,23 @@ if(bodytemperature >= 225 && !(disabilities & NOCLONE)) //cryosleep or husked people do not pump the blood. //Blood regeneration if there is some space - if(blood_volume < BLOOD_VOLUME_NORMAL) - blood_volume += 0.1 // regenerate blood VERY slowly + if(blood_volume < BLOOD_VOLUME_NORMAL && !(NOHUNGER in dna.species.species_traits)) + var/nutrition_ratio = 0 + switch(nutrition) + if(0 to NUTRITION_LEVEL_STARVING) + nutrition_ratio = 0.2 + if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) + nutrition_ratio = 0.4 + if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) + nutrition_ratio = 0.6 + if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) + nutrition_ratio = 0.8 + else + nutrition_ratio = 1 + if(satiety > 80) + nutrition_ratio *= 1.25 + nutrition = max(0, nutrition - nutrition_ratio * HUNGER_FACTOR) + blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio) //Effects of bloodloss var/word = pick("dizzy","woozy","faint") diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 7eb6d182ef4..86ea3d64e9e 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -69,7 +69,7 @@ bursting = TRUE - var/list/candidates = pollCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA) + var/list/candidates = pollGhostCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA) if(QDELETED(src) || QDELETED(owner)) return diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index c18f6721edc..06cfbe16cb1 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -165,5 +165,8 @@ dna.species.mutant_bodyparts -= "wingsopen" dna.species.mutant_bodyparts |= "wings" update_body() + if(isturf(loc)) + var/turf/T = loc + T.Entered(src) //Ayy lmao diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 92725d73a65..4bbeb3bcfda 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -446,7 +446,7 @@ if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move. pulledby.stop_pulling() - if (s_active && !(s_active.ClickAccessible(src, depth=STORAGE_VIEW_DEPTH) || s_active.Adjacent(src))) + if (s_active && !(CanReach(s_active,view_only = TRUE))) s_active.close(src) /mob/living/movement_delay(ignorewalk = 0) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index ebbf4c1de99..6f2a7ef0fa5 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -27,7 +27,8 @@ unique_name = 1 AIStatus = AI_OFF //normal constructs don't have AI loot = list(/obj/item/weapon/ectoplasm) - del_on_death = 1 + del_on_death = TRUE + initial_language_holder = /datum/language_holder/construct deathmessage = "collapses in a shattered heap." var/list/construct_spells = list() var/playstyle_string = "You are a generic construct! Your job is to not exist, and you should probably adminhelp this." diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index be889a4183c..fe6e22bcab2 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -414,7 +414,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians var/mob/living/simple_animal/hostile/guardian/G = input(src, "Pick the guardian you wish to reset", "Guardian Reset") as null|anything in guardians if(G) to_chat(src, "You attempt to reset [G.real_name]'s personality...") - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [src.real_name]'s [G.real_name]?", "pAI", null, FALSE, 100) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as [src.real_name]'s [G.real_name]?", "pAI", null, FALSE, 100) var/mob/dead/observer/new_stand = null if(candidates.len) new_stand = pick(candidates) @@ -489,7 +489,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians return used = TRUE to_chat(user, "[use_message]") - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_PAI, null, FALSE, 100) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_PAI, null, FALSE, 100) var/mob/dead/observer/theghost = null if(candidates.len) diff --git a/code/modules/mob/living/simple_animal/hostile/jungle_mobs.dm b/code/modules/mob/living/simple_animal/hostile/jungle_mobs.dm new file mode 100644 index 00000000000..de1bf0b3083 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/jungle_mobs.dm @@ -0,0 +1,85 @@ +/mob/living/simple_animal/hostile/jungle + vision_range = 5 + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + faction = list("jungle") + weather_immunities = list("acid") + obj_damage = 30 + environment_smash = 2 + minbodytemp = 0 + maxbodytemp = 450 + response_help = "pokes" + response_disarm = "shoves" + response_harm = "strikes" + status_flags = 0 + a_intent = INTENT_HARM + see_in_dark = 4 + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + mob_size = MOB_SIZE_LARGE + + + +//Mega arachnid + +/mob/living/simple_animal/hostile/jungle/mega_arachnid + name = "mega arachnid" + desc = "Though physically imposing, it prefers to ambush its prey, and it will only engage with an already crippled opponent." + melee_damage_lower = 30 + melee_damage_upper = 30 + maxHealth = 300 + health = 300 + speed = 1 + ranged = 1 + pixel_x = -16 + move_to_delay = 10 + aggro_vision_range = 9 + speak_emote = list("chitters") + attack_sound = 'sound/weapons/bladeslice.ogg' + ranged_cooldown_time = 60 + projectiletype = /obj/item/projectile/mega_arachnid + projectilesound = 'sound/weapons/pierce.ogg' + icon = 'icons/mob/jungle/arachnid.dmi' + icon_state = "arachnid" + icon_living = "arachnid" + icon_dead = "dead_purple" + alpha = 50 + +/mob/living/simple_animal/hostile/jungle/mega_arachnid/Life() + ..() + if(target && ranged_cooldown > world.time && iscarbon(target)) + var/mob/living/carbon/C = target + if(!C.legcuffed && C.health < 50) + retreat_distance = 9 + minimum_distance = 9 + alpha = 125 + return + retreat_distance = 0 + minimum_distance = 0 + alpha = 255 + + +/mob/living/simple_animal/hostile/jungle/mega_arachnid/Aggro() + ..() + alpha = 255 + +/mob/living/simple_animal/hostile/jungle/mega_arachnid/LoseAggro() + ..() + alpha = 50 + +/obj/item/projectile/mega_arachnid + name = "flesh snare" + nodamage = 1 + damage = 0 + icon_state = "tentacle_end" + +/obj/item/projectile/mega_arachnid/on_hit(atom/target, blocked = 0) + if(iscarbon(target) && blocked < 100) + var/obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid/B = new /obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid(get_turf(target)) + B.Crossed(target) + ..() + +/obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid + name = "fleshy restraints" + desc = "Used by mega arachnids to immobilize their prey." + flags = DROPDEL + icon_state = "tentacle_end" + icon = 'icons/obj/projectiles.dmi' \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index b426aa996cb..404ad8b0a57 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -28,7 +28,8 @@ status_flags = CANPUSH movement_type = FLYING loot = list(/obj/item/weapon/ectoplasm) - del_on_death = 1 + del_on_death = TRUE + initial_language_holder = /datum/language_holder/construct /mob/living/simple_animal/shade/death() deathmessage = "lets out a contented sigh as [p_their()] form unwinds." diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index d3a002a4a56..e2b8d86e91e 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -567,6 +567,7 @@ var/datum/map_config/cached = SSmapping.next_map_config if(cached) stat(null, "Next Map: [cached.map_name]") + stat("Round ID:", "[GLOB.round_id ? GLOB.round_id : "NULL"]") stat(null, "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]") stat(null, "Station Time: [worldtime2text()]") stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)") diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 23836e866d2..31ec27fb79c 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -966,7 +966,7 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_desc = "Only for the experienced. You think you see sand floating in the glass." /datum/reagent/consumable/ethanol/bananahonk - name = "Banana Mama" + name = "Banana Honk" id = "bananahonk" description = "A drink from Clown Heaven." nutriment_factor = 1 * REAGENTS_METABOLISM diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 56a89fe389f..260d09a81a8 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -29,16 +29,11 @@ var/brute_heal = 1 var/burn_heal = 0 - var/blood_gain = 0.4 /datum/reagent/consumable/nutriment/on_mob_life(mob/living/M) if(prob(50)) M.heal_bodypart_damage(brute_heal,burn_heal, 0) . = 1 - if(iscarbon(M)) - var/mob/living/carbon/C = M - if(C.blood_volume < BLOOD_VOLUME_NORMAL) - C.blood_volume += blood_gain ..() /datum/reagent/consumable/nutriment/on_new(list/supplied_data) @@ -82,7 +77,6 @@ brute_heal = 1 burn_heal = 1 - blood_gain = 0.5 /datum/reagent/consumable/nutriment/vitamin/on_mob_life(mob/living/M) if(M.satiety < 600) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 90617f064be..415b316dd17 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1570,6 +1570,13 @@ M.update_transform() ..() +/datum/reagent/plastic_polymers + name = "plastic polymers" + id = "plastic_polymers" + description = "the petroleum based components of plastic." + color = "#f7eded" + taste_description = "plastic" + /datum/reagent/glitter name = "generic glitter" id = "glitter" diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index 19bb28666d4..0bc843a6054 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -624,3 +624,14 @@ id = "laughter" results = list("laughter" = 10) // Fuck it. I'm not touching this one. required_reagents = list("sugar" = 1, "banana" = 1) + +/datum/chemical_reaction/plastic_polymers + name = "plastic polymers" + id = "plastic_polymers" + required_reagents = list("oil" = 5, "sodiumchloride" = 2, "ash" = 3) + required_temp = 374 //lazily consistent with soap & other crafted objects generically created with heat. + +/datum/chemical_reaction/plastic_polymers/on_reaction(datum/reagents/holder, created_volume) + var/location = get_turf(holder.my_atom) + for(var/i in 1 to 10) + new /obj/item/stack/sheet/plastic(location) diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 41ba8197a17..76bf2a002a3 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -47,7 +47,7 @@ other types of metals and chemistry for reagents). //////////////////////////////////////// /obj/item/weapon/disk/design_disk - name = "component design disk" + name = "Component Design Disk" desc = "A disk for storing device design data for construction in lathes." icon_state = "datadisk1" materials = list(MAT_METAL=300, MAT_GLASS=100) @@ -62,7 +62,7 @@ other types of metals and chemistry for reagents). blueprints += null /obj/item/weapon/disk/design_disk/adv - name = "advanced component design disk" + name = "Advanced Component Design Disk" desc = "A disk for storing device design data for construction in lathes. This one has extra storage space." materials = list(MAT_METAL=300, MAT_GLASS=100, MAT_SILVER = 50) max_blueprints = 5 @@ -587,7 +587,7 @@ other types of metals and chemistry for reagents). category = list("Equipment") /datum/design/diskplantgene - name = "Plant data disk" + name = "Plant Data Disk" desc = "A disk for storing plant genetic data." id = "diskplantgene" req_tech = list("programming" = 4, "biotech" = 3) diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index 9f2fbda1f34..7fbc8309a8f 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -11,7 +11,7 @@ category = list("initial","Tools") /datum/design/crowbar - name = "Pocket crowbar" + name = "Pocket Crowbar" id = "crowbar" build_type = AUTOLATHE materials = list(MAT_METAL = 50) @@ -27,7 +27,7 @@ category = list("initial","Tools") /datum/design/extinguisher - name = "Fire extinguisher" + name = "Fire Extinguisher" id = "extinguisher" build_type = AUTOLATHE materials = list(MAT_METAL = 90) @@ -51,7 +51,7 @@ category = list("initial","Tools") /datum/design/tscanner - name = "T-ray scanner" + name = "T-Ray Scanner" id = "tscanner" build_type = AUTOLATHE materials = list(MAT_METAL = 150) @@ -59,7 +59,7 @@ category = list("initial","Tools") /datum/design/weldingtool - name = "Welding tool" + name = "Welding Tool" id = "welding_tool" build_type = AUTOLATHE materials = list(MAT_METAL = 70, MAT_GLASS = 20) @@ -67,7 +67,7 @@ category = list("initial","Tools") /datum/design/mini_weldingtool - name = "Emergency welding tool" + name = "Emergency Welding Tool" id = "mini_welding_tool" build_type = AUTOLATHE materials = list(MAT_METAL = 30, MAT_GLASS = 10) @@ -99,7 +99,7 @@ category = list("initial","Tools") /datum/design/welding_helmet - name = "Welding helmet" + name = "Welding Helmet" id = "welding_helmet" build_type = AUTOLATHE materials = list(MAT_METAL = 1750, MAT_GLASS = 400) @@ -107,7 +107,7 @@ category = list("initial","Tools") /datum/design/cable_coil - name = "Cable coil" + name = "Cable Coil" id = "cable_coil" build_type = AUTOLATHE materials = list(MAT_METAL = 10, MAT_GLASS = 5) @@ -124,7 +124,7 @@ category = list("initial","Tools") /datum/design/console_screen - name = "Console screen" + name = "Console Screen" id = "console_screen" build_type = AUTOLATHE materials = list(MAT_GLASS = 200) @@ -132,7 +132,7 @@ category = list("initial", "Electronics") /datum/design/apc_board - name = "APC module" + name = "APC Module" id = "power control" build_type = AUTOLATHE materials = list(MAT_METAL = 100, MAT_GLASS = 100) @@ -140,7 +140,7 @@ category = list("initial", "Electronics") /datum/design/airlock_board - name = "Airlock electronics" + name = "Airlock Electronics" id = "airlock_board" build_type = AUTOLATHE materials = list(MAT_METAL = 50, MAT_GLASS = 50) @@ -148,7 +148,7 @@ category = list("initial", "Electronics") /datum/design/firelock_board - name = "Firelock circuitry" + name = "Firelock Circuitry" id = "firelock_board" build_type = AUTOLATHE materials = list(MAT_METAL = 50, MAT_GLASS = 50) @@ -156,7 +156,7 @@ category = list("initial", "Electronics") /datum/design/airalarm_electronics - name = "Air alarm electronics" + name = "Air Alarm Electronics" id = "airalarm_electronics" build_type = AUTOLATHE materials = list(MAT_METAL = 50, MAT_GLASS = 50) @@ -164,7 +164,7 @@ category = list("initial", "Electronics") /datum/design/firealarm_electronics - name = "Fire alarm electronics" + name = "Fire Alarm Electronics" id = "firealarm_electronics" build_type = AUTOLATHE materials = list(MAT_METAL = 50, MAT_GLASS = 50) @@ -180,7 +180,7 @@ category = list("initial", "Misc") /datum/design/pipe_painter - name = "Pipe painter" + name = "Pipe Painter" id = "pipe_painter" build_type = AUTOLATHE materials = list(MAT_METAL = 5000, MAT_GLASS = 2000) @@ -188,7 +188,7 @@ category = list("initial", "Misc") /datum/design/airlock_painter - name = "Airlock painter" + name = "Airlock Painter" id = "airlock_painter" build_type = AUTOLATHE materials = list(MAT_METAL = 50, MAT_GLASS = 50) @@ -214,7 +214,7 @@ maxstack = 50 /datum/design/rglass - name = "Reinforced glass" + name = "Reinforced Glass" id = "rglass" build_type = AUTOLATHE materials = list(MAT_METAL = 1000, MAT_GLASS = MINERAL_MATERIAL_AMOUNT) @@ -223,7 +223,7 @@ maxstack = 50 /datum/design/rods - name = "Metal rod" + name = "Metal Rod" id = "rods" build_type = AUTOLATHE materials = list(MAT_METAL = 1000) @@ -232,7 +232,7 @@ maxstack = 50 /datum/design/rcd_ammo - name = "Compressed matter cardridge" + name = "Compressed Matter Cartridge" id = "rcd_ammo" build_type = AUTOLATHE materials = list(MAT_METAL = 3000, MAT_GLASS=2000) @@ -240,7 +240,7 @@ category = list("initial","Construction") /datum/design/kitchen_knife - name = "Kitchen knife" + name = "Kitchen Knife" id = "kitchen_knife" build_type = AUTOLATHE materials = list(MAT_METAL = 12000) @@ -272,7 +272,7 @@ category = list("initial","Dinnerware") /datum/design/drinking_glass - name = "Drinking glass" + name = "Drinking Glass" id = "drinking_glass" build_type = AUTOLATHE materials = list(MAT_GLASS = 500) @@ -280,7 +280,7 @@ category = list("initial","Dinnerware") /datum/design/shot_glass - name = "Shot glass" + name = "Shot Glass" id = "shot_glass" build_type = AUTOLATHE materials = list(MAT_GLASS = 100) @@ -304,7 +304,7 @@ category = list("initial","Misc") /datum/design/plant_analyzer - name = "Plant analyzer" + name = "Plant Analyzer" id = "plant_analyzer" build_type = AUTOLATHE materials = list(MAT_METAL = 30, MAT_GLASS = 20) @@ -344,7 +344,7 @@ category = list("initial", "Medical") /datum/design/circular_saw - name = "Circular saw" + name = "Circular Saw" id = "circular_saw" build_type = AUTOLATHE materials = list(MAT_METAL = 10000, MAT_GLASS = 6000) @@ -352,7 +352,7 @@ category = list("initial", "Medical") /datum/design/surgicaldrill - name = "Surgical drill" + name = "Surgical Drill" id = "surgicaldrill" build_type = AUTOLATHE materials = list(MAT_METAL = 10000, MAT_GLASS = 6000) @@ -392,7 +392,7 @@ category = list("initial", "Medical") /datum/design/large_beaker - name = "Large beaker" + name = "Large Beaker" id = "large_beaker" build_type = AUTOLATHE materials = list(MAT_GLASS = 2500) @@ -408,7 +408,7 @@ category = list("initial", "Medical") /datum/design/beanbag_slug - name = "Beanbag slug" + name = "Beanbag Slug" id = "beanbag_slug" build_type = AUTOLATHE materials = list(MAT_METAL = 250) @@ -416,7 +416,7 @@ category = list("initial", "Security") /datum/design/rubbershot - name = "Rubber shot" + name = "Rubber Shot" id = "rubber_shot" build_type = AUTOLATHE materials = list(MAT_METAL = 4000) @@ -424,7 +424,7 @@ category = list("initial", "Security") /datum/design/c38 - name = "Speed loader (.38)" + name = "Speed Loader (.38)" id = "c38" build_type = AUTOLATHE materials = list(MAT_METAL = 30000) @@ -432,7 +432,7 @@ category = list("initial", "Security") /datum/design/recorder - name = "Universal recorder" + name = "Universal Recorder" id = "recorder" build_type = AUTOLATHE materials = list(MAT_METAL = 60, MAT_GLASS = 30) @@ -456,7 +456,7 @@ category = list("initial", "Misc") /datum/design/signaler - name = "Remote signaling device" + name = "Remote Signaling Device" id = "signaler" build_type = AUTOLATHE materials = list(MAT_METAL = 400, MAT_GLASS = 120) @@ -464,7 +464,7 @@ category = list("initial", "T-Comm") /datum/design/radio_headset - name = "Radio headset" + name = "Radio Headset" id = "radio_headset" build_type = AUTOLATHE materials = list(MAT_METAL = 75) @@ -472,7 +472,7 @@ category = list("initial", "T-Comm") /datum/design/bounced_radio - name = "Station bounced radio" + name = "Station Bounced Radio" id = "bounced_radio" build_type = AUTOLATHE materials = list(MAT_METAL = 75, MAT_GLASS = 25) @@ -480,7 +480,7 @@ category = list("initial", "T-Comm") /datum/design/infrared_emitter - name = "Infrared emitter" + name = "Infrared Emitter" id = "infrared_emitter" build_type = AUTOLATHE materials = list(MAT_METAL = 1000, MAT_GLASS = 500) @@ -488,7 +488,7 @@ category = list("initial", "Misc") /datum/design/health_sensor - name = "Health sensor" + name = "Health Sensor" id = "health_sensor" build_type = AUTOLATHE materials = list(MAT_METAL = 800, MAT_GLASS = 200) @@ -504,7 +504,7 @@ category = list("initial", "Misc") /datum/design/voice_analyser - name = "Voice analyser" + name = "Voice Analyser" id = "voice_analyser" build_type = AUTOLATHE materials = list(MAT_METAL = 500, MAT_GLASS = 50) @@ -512,7 +512,7 @@ category = list("initial", "Misc") /datum/design/light_tube - name = "Light tube" + name = "Light Tube" id = "light_tube" build_type = AUTOLATHE materials = list(MAT_GLASS = 100) @@ -520,7 +520,7 @@ category = list("initial", "Construction") /datum/design/light_bulb - name = "Light bulb" + name = "Light Bulb" id = "light_bulb" build_type = AUTOLATHE materials = list(MAT_GLASS = 100) @@ -528,7 +528,7 @@ category = list("initial", "Construction") /datum/design/camera_assembly - name = "Camera assembly" + name = "Camera Assembly" id = "camera_assembly" build_type = AUTOLATHE materials = list(MAT_METAL = 400, MAT_GLASS = 250) @@ -536,7 +536,7 @@ category = list("initial", "Construction") /datum/design/newscaster_frame - name = "Newscaster frame" + name = "Newscaster Frame" id = "newscaster_frame" build_type = AUTOLATHE materials = list(MAT_METAL = 14000, MAT_GLASS = 8000) @@ -552,7 +552,7 @@ category = list("initial", "Medical") /datum/design/prox_sensor - name = "Proximity sensor" + name = "Proximity Sensor" id = "prox_sensor" build_type = AUTOLATHE materials = list(MAT_METAL = 800, MAT_GLASS = 200) @@ -577,7 +577,7 @@ category = list("hacked", "Weapons and ammo") /datum/design/rcd - name = "Rapid construction device (RCD)" + name = "Rapid Construction Device (RCD)" id = "rcd" build_type = AUTOLATHE materials = list(MAT_METAL = 30000) @@ -585,7 +585,7 @@ category = list("hacked", "Construction") /datum/design/rpd - name = "Rapid pipe dispenser (RPD)" + name = "Rapid Pipe Dispenser (RPD)" id = "rpd" build_type = AUTOLATHE materials = list(MAT_METAL = 75000, MAT_GLASS = 37500) @@ -601,7 +601,7 @@ category = list("hacked", "Tools") /datum/design/large_welding_tool - name = "Industrial welding tool" + name = "Industrial Welding Tool" id = "large_welding_tool" build_type = AUTOLATHE materials = list(MAT_METAL = 70, MAT_GLASS = 60) @@ -625,7 +625,7 @@ category = list("hacked", "Security") /datum/design/shotgun_slug - name = "Shotgun slug" + name = "Shotgun Slug" id = "shotgun_slug" build_type = AUTOLATHE materials = list(MAT_METAL = 4000) @@ -633,7 +633,7 @@ category = list("hacked", "Security") /datum/design/buckshot_shell - name = "Buckshot shell" + name = "Buckshot Shell" id = "buckshot_shell" build_type = AUTOLATHE materials = list(MAT_METAL = 4000) @@ -641,7 +641,7 @@ category = list("hacked", "Security") /datum/design/shotgun_dart - name = "Shotgun dart" + name = "Shotgun Dart" id = "shotgun_dart" build_type = AUTOLATHE materials = list(MAT_METAL = 4000) @@ -649,7 +649,7 @@ category = list("hacked", "Security") /datum/design/incendiary_slug - name = "Incendiary slug" + name = "Incendiary Slug" id = "incendiary_slug" build_type = AUTOLATHE materials = list(MAT_METAL = 4000) @@ -657,7 +657,7 @@ category = list("hacked", "Security") /datum/design/riot_dart - name = "Foam riot dart" + name = "Foam Riot Dart" id = "riot_dart" build_type = AUTOLATHE materials = list(MAT_METAL = 1000) //Discount for making individually - no box = less metal! @@ -665,7 +665,7 @@ category = list("hacked", "Security") /datum/design/riot_darts - name = "Foam riot dart box" + name = "Foam Riot Dart Box" id = "riot_darts" build_type = AUTOLATHE materials = list(MAT_METAL = 50000) //Comes with 40 darts @@ -673,7 +673,7 @@ category = list("hacked", "Security") /datum/design/a357 - name = "Ammo box (.357)" + name = "Ammo Box (.357)" id = "a357" build_type = AUTOLATHE materials = list(MAT_METAL = 30000) @@ -681,7 +681,7 @@ category = list("hacked", "Security") /datum/design/c10mm - name = "Ammo box (10mm)" + name = "Ammo Box (10mm)" id = "c10mm" build_type = AUTOLATHE materials = list(MAT_METAL = 30000) @@ -689,7 +689,7 @@ category = list("hacked", "Security") /datum/design/c45 - name = "Ammo box (.45)" + name = "Ammo Box (.45)" id = "c45" build_type = AUTOLATHE materials = list(MAT_METAL = 30000) @@ -697,7 +697,7 @@ category = list("hacked", "Security") /datum/design/c9mm - name = "Ammo box (9mm)" + name = "Ammo Box (9mm)" id = "c9mm" build_type = AUTOLATHE materials = list(MAT_METAL = 30000) @@ -705,7 +705,7 @@ category = list("hacked", "Security") /datum/design/cleaver - name = "Butcher's cleaver" + name = "Butcher's Cleaver" id = "cleaver" build_type = AUTOLATHE materials = list(MAT_METAL = 18000) @@ -721,7 +721,7 @@ category = list("initial", "Tools") /datum/design/desttagger - name = "Destination tagger" + name = "Destination Tagger" id = "desttagger" build_type = AUTOLATHE materials = list(MAT_METAL = 250, MAT_GLASS = 125) @@ -729,7 +729,7 @@ category = list("initial", "Electronics") /datum/design/handlabeler - name = "Hand labeler" + name = "Hand Labeler" id = "handlabel" build_type = AUTOLATHE materials = list(MAT_METAL = 150, MAT_GLASS = 125) @@ -737,7 +737,7 @@ category = list("initial", "Electronics") /datum/design/geiger - name = "Geiger counter" + name = "Geiger Counter" id = "geigercounter" build_type = AUTOLATHE materials = list(MAT_METAL = 150, MAT_GLASS = 150) @@ -745,7 +745,7 @@ category = list("initial", "Tools") /datum/design/turret_control_frame - name = "Turret control frame" + name = "Turret Control Frame" id = "turret_control" build_type = AUTOLATHE materials = list(MAT_METAL = 12000) @@ -753,7 +753,7 @@ category = list("initial", "Construction") /datum/design/conveyor_belt - name = "Conveyor belt" + name = "Conveyor Belt" id = "conveyor_belt" build_type = AUTOLATHE materials = list(MAT_METAL = 5000) @@ -761,7 +761,7 @@ category = list("initial", "Construction") /datum/design/conveyor_switch - name = "Conveyor belt switch" + name = "Conveyor Belt Switch" id = "conveyor_switch" build_type = AUTOLATHE materials = list(MAT_METAL = 450, MAT_GLASS = 190) @@ -783,3 +783,12 @@ materials = list(MAT_METAL = 2000, MAT_GLASS = 1000) build_path = /obj/item/device/modular_computer/tablet category = list("initial","Misc") + +/datum/design/slime_scanner + name = "Slime Scanner" + id = "slime_scanner" + build_type = AUTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 200) + build_path = /obj/item/device/slime_scanner + category = list("initial", "Misc") + \ No newline at end of file diff --git a/code/modules/research/designs/biogenerator_designs.dm b/code/modules/research/designs/biogenerator_designs.dm index d2931012299..7319e507ae6 100644 --- a/code/modules/research/designs/biogenerator_designs.dm +++ b/code/modules/research/designs/biogenerator_designs.dm @@ -3,7 +3,7 @@ /////////////////////////////////// /datum/design/milk - name = "10 milk" + name = "10 Milk" id = "milk" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 20) @@ -11,7 +11,7 @@ category = list("initial","Food") /datum/design/cream - name = "10 cream" + name = "10 Cream" id = "cream" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 30) @@ -19,7 +19,7 @@ category = list("initial","Food") /datum/design/milk_carton - name = "Milk carton" + name = "Milk Carton" id = "milk_carton" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 100) @@ -27,7 +27,7 @@ category = list("initial","Food") /datum/design/cream_carton - name = "Cream carton" + name = "Cream Carton" id = "cream_carton" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 300) @@ -35,7 +35,7 @@ category = list("initial","Food") /datum/design/black_pepper - name = "10u black pepper" + name = "10u Black Pepper" id = "black_pepper" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 25) @@ -43,7 +43,7 @@ category = list("initial","Food") /datum/design/pepper_mill - name = "Pepper mill" + name = "Pepper Mill" id = "pepper_mill" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 50) @@ -52,7 +52,7 @@ category = list("initial","Food") /datum/design/monkey_cube - name = "Monkey cube" + name = "Monkey Cube" id = "mcube" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 250) @@ -60,7 +60,7 @@ category = list("initial", "Food") /datum/design/ez_nut - name = "E-Z-Nutrient" + name = "E-Z Nutrient" id = "ez_nut" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 10) @@ -108,39 +108,23 @@ category = list("initial", "Botany Chemicals") /datum/design/cloth - name = "Roll of cloth" + name = "Roll of Cloth" id = "cloth" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 50) build_path = /obj/item/stack/sheet/cloth category = list("initial","Leather and Cloth") -/datum/design/wallet - name = "Wallet" - id = "wallet" - build_type = BIOGENERATOR - materials = list(MAT_BIOMASS = 100) - build_path = /obj/item/weapon/storage/wallet - category = list("initial","Leather and Cloth") - -/datum/design/botany_gloves - name = "Botanical gloves" - id = "botany_gloves" +/datum/design/leather + name = "Sheet of Leather" + id = "leather" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 150) - build_path = /obj/item/clothing/gloves/botanic_leather - category = list("initial","Leather and Cloth") - -/datum/design/toolbelt - name = "Utility Belt" - id = "toolbelt" - build_type = BIOGENERATOR - materials = list(MAT_BIOMASS = 300) - build_path = /obj/item/weapon/storage/belt/utility + build_path = /obj/item/stack/sheet/leather category = list("initial","Leather and Cloth") /datum/design/secbelt - name = "Security belt" + name = "Security Belt" id = "secbelt" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 300) @@ -148,7 +132,7 @@ category = list("initial","Leather and Cloth") /datum/design/medbelt - name = "Medical belt" + name = "Medical Belt" id = "medbel" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 300) @@ -156,55 +140,23 @@ category = list("initial","Leather and Cloth") /datum/design/janibelt - name = "Janitorial belt" + name = "Janitorial Belt" id = "janibelt" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 300) build_path = /obj/item/weapon/storage/belt/janitor category = list("initial","Leather and Cloth") -/datum/design/bandolier - name = "Bandolier belt" - id = "bandolier" - build_type = BIOGENERATOR - materials = list(MAT_BIOMASS = 300) - build_path = /obj/item/weapon/storage/belt/bandolier - category = list("initial","Leather and Cloth") - /datum/design/s_holster - name = "Shoulder holster" + name = "Shoulder Holster" id = "s_holster" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 400) build_path = /obj/item/weapon/storage/belt/holster category = list("initial","Leather and Cloth") -/datum/design/leather_satchel - name = "Leather satchel" - id = "leather_satchel" - build_type = BIOGENERATOR - materials = list(MAT_BIOMASS = 400) - build_path = /obj/item/weapon/storage/backpack/satchel - category = list("initial","Leather and Cloth") - -/datum/design/leather_jacket - name = "Leather jacket" - id = "leather_jacket" - build_type = BIOGENERATOR - materials = list(MAT_BIOMASS = 500) - build_path = /obj/item/clothing/suit/jacket/leather - category = list("initial","Leather and Cloth") - -/datum/design/leather_overcoat - name = "Leather overcoat" - id = "leather_overcoat" - build_type = BIOGENERATOR - materials = list(MAT_BIOMASS = 1000) - build_path = /obj/item/clothing/suit/jacket/leather/overcoat - category = list("initial","Leather and Cloth") - /datum/design/rice_hat - name = "Rice hat" + name = "Rice Hat" id = "rice_hat" build_type = BIOGENERATOR materials = list(MAT_BIOMASS = 300) diff --git a/code/modules/research/designs/computer_part_designs.dm b/code/modules/research/designs/computer_part_designs.dm index cd75eada7aa..dbdd15817c0 100644 --- a/code/modules/research/designs/computer_part_designs.dm +++ b/code/modules/research/designs/computer_part_designs.dm @@ -3,7 +3,7 @@ //////////////////////////////////////// /datum/design/disk/normal - name = "hard disk drive" + name = "Hard Disk Drive" id = "hdd_basic" req_tech = list("programming" = 1, "engineering" = 1) build_type = PROTOLATHE @@ -12,7 +12,7 @@ category = list("Computer Parts") /datum/design/disk/advanced - name = "advanced hard disk drive" + name = "Advanced Hard Disk Drive" id = "hdd_advanced" req_tech = list("programming" = 2, "engineering" = 2) build_type = PROTOLATHE @@ -21,7 +21,7 @@ category = list("Computer Parts") /datum/design/disk/super - name = "super hard disk drive" + name = "Super Hard Disk Drive" id = "hdd_super" req_tech = list("programming" = 3, "engineering" = 3) build_type = PROTOLATHE @@ -30,7 +30,7 @@ category = list("Computer Parts") /datum/design/disk/cluster - name = "cluster hard disk drive" + name = "Cluster Hard Disk Drive" id = "hdd_cluster" req_tech = list("programming" = 4, "engineering" = 4) build_type = PROTOLATHE @@ -39,7 +39,7 @@ category = list("Computer Parts") /datum/design/disk/small - name = "solid state drive" + name = "Solid State Drive" id = "ssd_small" req_tech = list("programming" = 2, "engineering" = 2) build_type = PROTOLATHE @@ -48,7 +48,7 @@ category = list("Computer Parts") /datum/design/disk/micro - name = "micro solid state drive" + name = "Micro Solid State Drive" id = "ssd_micro" req_tech = list("programming" = 1, "engineering" = 1) build_type = PROTOLATHE @@ -59,7 +59,7 @@ // Network cards /datum/design/netcard/basic - name = "network card" + name = "Network Card" id = "netcard_basic" req_tech = list("programming" = 2, "engineering" = 1) build_type = IMPRINTER @@ -69,7 +69,7 @@ category = list("Computer Parts") /datum/design/netcard/advanced - name = "advanced network card" + name = "Advanced Network Card" id = "netcard_advanced" req_tech = list("programming" = 4, "engineering" = 2) build_type = IMPRINTER @@ -79,7 +79,7 @@ category = list("Computer Parts") /datum/design/netcard/wired - name = "wired network card" + name = "Wired Network Card" id = "netcard_wired" req_tech = list("programming" = 5, "engineering" = 3) build_type = IMPRINTER @@ -91,7 +91,7 @@ // Data disks /datum/design/portabledrive/basic - name = "data disk" + name = "Data Disk" id = "portadrive_basic" req_tech = list("programming" = 1) build_type = IMPRINTER @@ -101,7 +101,7 @@ category = list("Computer Parts") /datum/design/portabledrive/advanced - name = "advanced data disk" + name = "Advanced Data Disk" id = "portadrive_advanced" req_tech = list("programming" = 2) build_type = IMPRINTER @@ -111,7 +111,7 @@ category = list("Computer Parts") /datum/design/portabledrive/super - name = "super data disk" + name = "Super Data Disk" id = "portadrive_super" req_tech = list("programming" = 4) build_type = IMPRINTER @@ -123,7 +123,7 @@ // Card slot /datum/design/cardslot - name = "ID card slot" + name = "ID Card Slot" id = "cardslot" req_tech = list("programming" = 2) build_type = PROTOLATHE @@ -133,7 +133,7 @@ // Intellicard slot /datum/design/aislot - name = "Intellicard slot" + name = "Intellicard Slot" id = "aislot" req_tech = list("programming" = 2) build_type = PROTOLATHE @@ -143,7 +143,7 @@ // Mini printer /datum/design/miniprinter - name = "miniprinter" + name = "Miniprinter" id = "miniprinter" req_tech = list("programming" = 2, "engineering" = 2) build_type = PROTOLATHE @@ -154,7 +154,7 @@ // APC Link /datum/design/APClink - name = "area power connector" + name = "Area Power Connector" id = "APClink" req_tech = list("programming" = 2, "powerstorage" = 3, "engineering" = 2) build_type = PROTOLATHE @@ -165,7 +165,7 @@ // Batteries /datum/design/battery/controller - name = "power cell controller" + name = "Power Cell Controller" id = "bat_control" req_tech = list("powerstorage" = 1, "engineering" = 1) build_type = PROTOLATHE @@ -174,7 +174,7 @@ category = list("Computer Parts") /datum/design/battery/normal - name = "battery module" + name = "Battery Module" id = "bat_normal" req_tech = list("powerstorage" = 1, "engineering" = 1) build_type = PROTOLATHE @@ -183,7 +183,7 @@ category = list("Computer Parts") /datum/design/battery/advanced - name = "advanced battery module" + name = "Advanced Battery Module" id = "bat_advanced" req_tech = list("powerstorage" = 2, "engineering" = 2) build_type = PROTOLATHE @@ -192,7 +192,7 @@ category = list("Computer Parts") /datum/design/battery/super - name = "super battery module" + name = "Super Battery Module" id = "bat_super" req_tech = list("powerstorage" = 3, "engineering" = 3) build_type = PROTOLATHE @@ -201,7 +201,7 @@ category = list("Computer Parts") /datum/design/battery/nano - name = "nano battery module" + name = "Nano Battery Module" id = "bat_nano" req_tech = list("powerstorage" = 1, "engineering" = 1) build_type = PROTOLATHE @@ -210,7 +210,7 @@ category = list("Computer Parts") /datum/design/battery/micro - name = "micro battery module" + name = "Micro Battery Module" id = "bat_micro" req_tech = list("powerstorage" = 2, "engineering" = 2) build_type = PROTOLATHE @@ -221,7 +221,7 @@ // Processor unit /datum/design/cpu - name = "processor board" + name = "Processor Board" id = "cpu_normal" req_tech = list("programming" = 3, "engineering" = 2) build_type = IMPRINTER @@ -231,7 +231,7 @@ category = list("Computer Parts") /datum/design/cpu/small - name = "microprocessor" + name = "Microprocessor" id = "cpu_small" req_tech = list("programming" = 2, "engineering" = 2) build_type = IMPRINTER @@ -241,7 +241,7 @@ category = list("Computer Parts") /datum/design/cpu/photonic - name = "photonic processor board" + name = "Photonic Processor Board" id = "pcpu_normal" req_tech = list("programming" = 5, "engineering" = 4) build_type = IMPRINTER @@ -251,7 +251,7 @@ category = list("Computer Parts") /datum/design/cpu/photonic/small - name = "photonic microprocessor" + name = "Photonic Microprocessor" id = "pcpu_small" req_tech = list("programming" = 4, "engineering" = 3) build_type = IMPRINTER diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 002112b717d..f72458af4ea 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -96,7 +96,7 @@ category = list("Medical Designs") /datum/design/bluespacebodybag - name = "Bluespace body bag" + 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" req_tech = list("bluespace" = 5, "materials" = 4, "plasmatech" = 4) @@ -106,7 +106,7 @@ category = list("Medical Designs") /datum/design/plasmarefiller - name = "Plasma-man jumpsuit refill" + name = "Plasma-Man Jumpsuit Refill" desc = "A refill pack for the auto-extinguisher on Plasma-man suits." id = "plasmarefiller" req_tech = list("materials" = 2, "plasmatech" = 3) //Why did this have no plasmatech @@ -191,7 +191,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_breather - name = "Breathing Tube implant" + name = "Breathing Tube Implant" desc = "This simple implant adds an internals connector to your back, allowing you to use internals without a mask and protecting you from being choked." id = "ci-breather" req_tech = list("materials" = 2, "biotech" = 3) @@ -202,7 +202,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_toolset - name = "Toolset Arm implant" + name = "Toolset Arm Implant" desc = "A stripped-down version of engineering cyborg toolset, designed to be installed on subject's arm." id = "ci-toolset" req_tech = list("materials" = 3, "engineering" = 4, "biotech" = 4, "powerstorage" = 4) @@ -213,7 +213,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_medical_hud - name = "Medical HUD implant" + name = "Medical HUD Implant" desc = "These cybernetic eyes will display a medical HUD over everything you see. Wiggle eyes to control." id = "ci-medhud" req_tech = list("materials" = 5, "programming" = 4, "biotech" = 4) @@ -224,7 +224,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_security_hud - name = "Security HUD implant" + name = "Security HUD Implant" desc = "These cybernetic eyes will display a security HUD over everything you see. Wiggle eyes to control." id = "ci-sechud" req_tech = list("materials" = 5, "programming" = 4, "biotech" = 4, "combat" = 3) @@ -235,7 +235,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_xray - name = "X-Ray eyes" + name = "X-Ray Eyes" desc = "These cybernetic eyes will give you X-ray vision. Blinking is futile." id = "ci-xray" req_tech = list("materials" = 7, "programming" = 5, "biotech" = 7, "magnets" = 5,"plasmatech" = 6) @@ -246,7 +246,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_thermals - name = "Thermal eyes" + name = "Thermal Eyes" desc = "These cybernetic eyes will give you Thermal vision. Vertical slit pupil included." id = "ci-thermals" req_tech = list("materials" = 6, "programming" = 4, "biotech" = 7, "magnets" = 5,"plasmatech" = 4) @@ -257,7 +257,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_antidrop - name = "Anti-Drop implant" + name = "Anti-Drop Implant" desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle." id = "ci-antidrop" req_tech = list("materials" = 5, "programming" = 6, "biotech" = 5) @@ -268,7 +268,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_antistun - name = "CNS Rebooter implant" + name = "CNS Rebooter Implant" desc = "This implant will automatically give you back control over your central nervous system, reducing downtime when stunned." id = "ci-antistun" req_tech = list("materials" = 6, "programming" = 5, "biotech" = 6) @@ -279,7 +279,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_nutriment - name = "Nutriment pump implant" + name = "Nutriment Pump Implant" desc = "This implant with synthesize and pump into your bloodstream a small amount of nutriment when you are starving." id = "ci-nutriment" req_tech = list("materials" = 3, "powerstorage" = 4, "biotech" = 3) @@ -290,7 +290,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_nutriment_plus - name = "Nutriment pump implant PLUS" + name = "Nutriment Pump Implant PLUS" desc = "This implant with synthesize and pump into your bloodstream a small amount of nutriment when you are hungry." id = "ci-nutrimentplus" req_tech = list("materials" = 5, "powerstorage" = 4, "biotech" = 4) @@ -301,7 +301,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_reviver - name = "Reviver implant" + name = "Reviver Implant" desc = "This implant will attempt to revive you if you lose consciousness. For the faint of heart!" id = "ci-reviver" req_tech = list("materials" = 5, "programming" = 4, "biotech" = 5) @@ -312,7 +312,7 @@ category = list("Misc", "Medical Designs") /datum/design/cyberimp_thrusters - name = "Thrusters set implant" + name = "Thrusters Set Implant" desc = "This implant will allow you to use gas from environment or your internals for propulsion in zero-gravity areas." id = "ci-thrusters" req_tech = list("materials" = 5, "biotech" = 5, "magnets" = 4, "engineering" = 7) diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 80863259e85..15704651f6d 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -3,7 +3,7 @@ ///////////////////////////////////////// /datum/design/pin_testing - name = "test-range firing pin" + name = "Test-Range Firing Pin" desc = "This safety firing pin allows firearms to be operated within proximity to a firing range." id = "pin_testing" req_tech = list("combat" = 2, "materials" = 2) @@ -13,7 +13,7 @@ category = list("Firing Pins") /datum/design/pin_mindshield - name = "mindshield firing pin" + name = "Mindshield Firing Pin" desc = "This is a security firing pin which only authorizes users who are mindshield-implanted." id = "pin_loyalty" req_tech = list("combat" = 5, "materials" = 6) diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index 35ffdefce67..25567b90e23 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -40,7 +40,7 @@ category = list("Imported") /obj/item/golem_shell - name = "incomplete golem shell" + name = "incomplete free golem shell" icon = 'icons/obj/wizard.dmi' icon_state = "construct" desc = "The incomplete body of a golem. Add ten sheets of any mineral to finish." @@ -113,7 +113,7 @@ if(species) if(O.use(10)) to_chat(user, "You finish up the golem shell with ten sheets of [O].") - new shell_type(get_turf(src), species, has_owner, user) + new shell_type(get_turf(src), species, user) qdel(src) else to_chat(user, "You need at least ten sheets to finish a golem.") @@ -121,9 +121,9 @@ to_chat(user, "You can't build a golem out of this kind of material.") //made with xenobiology, the golem obeys its creator -/obj/item/golem_shell/artificial - name = "incomplete artificial golem shell" - has_owner = TRUE +/obj/item/golem_shell/servant + name = "incomplete servant golem shell" + shell_type = /obj/effect/mob_spawn/human/golem/servant ///Syndicate Listening Post /obj/effect/mob_spawn/human/lavaland_syndicate diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 6e3c224924d..9d88e491b2f 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -106,7 +106,7 @@ "You begin to mend the incision in [target]'s [parse_zone(target_zone)]...") else if(istype(tool, /obj/item/weapon/reagent_containers/food/snacks/organ)) - to_chat(user, "[tool] was biten by someone! It's too damaged to use!") + to_chat(user, "[tool] was bitten by someone! It's too damaged to use!") return -1 /datum/surgery_step/manipulate_organs/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index f3f9d7a8cd1..2636e2e5d55 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -15,6 +15,7 @@ /datum/language/common, /datum/language/draconic, /datum/language/monkey, + /datum/language/narsie, /datum/language/ratvar )) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 9d3377cc9c2..887c26038a2 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -111,17 +111,8 @@ if(contents.len) to_chat(user, "[src] already has something inside it.") return - if(isorgan(I)) - var/obj/item/organ/O = I - if(O.status != ORGAN_ORGANIC) - to_chat(user, "[src] can only hold organic body parts!") - return - else if(isbodypart(I)) - var/obj/item/bodypart/BP = I - if(BP.status != BODYPART_ORGANIC) - to_chat(user, "[src] can only hold organic body parts!") - return - else + if(!isorgan(I) && !isbodypart(I)) + to_chat(user, "[src] can only hold body parts!") return user.visible_message("[user] puts [I] into [src].", "You put [I] inside [src].") @@ -150,4 +141,4 @@ desc = "A container for holding body parts." else to_chat(user, "[src] is empty.") - return \ No newline at end of file + return diff --git a/code/world.dm b/code/world.dm index 42326f6ba69..353d8198183 100644 --- a/code/world.dm +++ b/code/world.dm @@ -59,6 +59,7 @@ load_mode() load_motd() load_admins() + load_menu() if(config.usewhitelist) load_whitelist() LoadBans() @@ -341,5 +342,6 @@ status = s + /world/proc/has_round_started() return SSticker.HasRoundStarted() diff --git a/config/admins.txt b/config/admins.txt index d90c33bcda7..b4485c08411 100644 --- a/config/admins.txt +++ b/config/admins.txt @@ -127,4 +127,5 @@ Sweaterkittens = Game Master Feemjmeem = Game Master JStheguy = Game Master excessiveuseofcobby = Game Master -Plizzard = Game Master \ No newline at end of file +Plizzard = Game Master +octareenroon91 = Game Master diff --git a/html/changelog.html b/html/changelog.html index f7044fd30a5..55b4761bba7 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,81 @@ -->
+

08 May 2017

+

Dorsisdwarf updated:

+
    +
  • Fixed being unable to hit museum cases in melee
  • +
+

Joan updated:

+
    +
  • The verb to Assert Leadership over the cult has been replaced with an action button that does the same thing, but is much more visible.
  • +
+

Moonlighting Mac says updated:

+
    +
  • After a recent trade fair, employees have took it upon themselves to learn how to craft leather objects out of finished leather sheets, for novices they are pretty good at it! Try it yourself!
  • +
  • Muzzles to silence people are now craftable out of leather sheets.
  • +
  • You can no longer print off designs from a bio-generator that can now be crafted out of leather sheets.
  • +
  • Complete sheets of leather can be printed from the bio-generator for 150 biomass to accommodate for a loss of designs.
  • +
  • Specialist objects from the leather & cloth category bio-generator category were not removed as to encourage interdepartmental interaction & balance.
  • +
+

Penguaro updated:

+
    +
  • The Slime Scanner is available from the Autolathe.
  • +
  • The Design Names in the various machines are now capitalized consistently
  • +
+

coiax updated:

+
    +
  • Fixes various mobs speaking languages that they were only supposed to understand.
  • +
  • Fixes being able to bypass language restrictions by selecting languages you can't speak as your default language.
  • +
+

ninjanomnom updated:

+
    +
  • Highlander no longer breaks your speakers
  • +
+ +

07 May 2017

+

Anonmare updated:

+
    +
  • Removes organic check from mediborg storage container
  • +
+

Joan updated:

+
    +
  • Cultists of Nar-sie have their own language. The language's key is ",n".
  • +
  • Sigils of Transgression are slightly brighter.
  • +
+

Moonlighting Mac updated:

+
    +
  • Due to budget cuts and oil synthesis replacing expensive processes of digging up haunted primeval ashwalker burial grounds, Nanotransen has taught chemists how to make plastic from chemicals in the hopes that new plastic products can reduce expenditure on metal and glass.
  • +
  • you can now make plastic sheets from chemistry out of heated up crude oil, ash & sodium chloride
  • +
+

MrStonedOne updated:

+
    +
  • fixed bug that caused an infinite connection loop when connecting on a new computer or computer with recently changed hardware.
  • +
  • Moved to a new system to make top menu items easier to edit.
  • +
  • Moved icon size stuff to a sub menu
  • +
  • Added option to change icon scaling mode.
  • +
  • Byond added fancy shader supported scaling(Point Sampling), this sucks because it's blurry, the default for /tg/station has changed back to the old nearest neighbor scaling.
  • +
+

Penguaro updated:

+
    +
  • Adjusted the Examine description of the right-most tiles of the Space Station 13 sign to be consistent with the rest of the tiles.
  • +
  • Anywhere there was lava below a tile on the station is now space.
  • +
+

Robustin updated:

+
    +
  • c4 planting is now 40% faster
  • +
+

coiax updated:

+
    +
  • Smartfridges no longer magically gain medicines if deconstructed and rebuilt.
  • +
  • Ash walkers now know and speak Draconic by default, but still know Galactic Common. Remember, Galcom's language key is ",0" and you can review your known languages with the Language Menu.
  • +
+

octareenroon91 updated:

+
    +
  • Showers and sinks added to gulag and mining station for hygiene and fire safety.
  • +
  • Watertanks added to mining station for convenient fire extinguisher refill.
  • +
+

06 May 2017

4dplanner updated:

    @@ -1335,45 +1410,6 @@
    • Wannabe ninjas have been found carrying an experimental chameleon belt. The Spider clan has disavowed any involvement.
    - -

    06 March 2017

    -

    Cyberboss updated:

    -
      -
    • Map rotation has been made smoother
    • -
    -

    Gun Hog updated:

    -
      -
    • The Aux Base Construction Console now directs to the correct Base Management Console.
    • -
    • The missing Science Department access has been added to the Auxiliary Base Management Console.
    • -
    -

    Hyena updated:

    -
      -
    • Space bar is out of bussiness
    • -
    -

    MrStonedOne updated:

    -
      -
    • patched a hacky workaround for /vg/lights memory leaking crashing the server
    • -
    -

    Penguaro updated:

    -
      -
    • Changed DIR of Gas Filter for O2 in Waste Loop from 1 to 4
    • -
    -

    Sligneris updated:

    -
      -
    • 'xeno queen' AI hologram now actually uses the xeno queen sprite as a reference
    • -
    -

    Tofa01 updated:

    -
      -
    • [Omega] Fixes missing walls and wires new dock to the powergrid
    • -
    -

    XDTM updated:

    -
      -
    • Changelings can now click their fake clothing to remove it, without needing to drop the full disguise.
    • -
    -

    coiax updated:

    -
      -
    • The Bardrone and Barmaid are neutral, even in the face of reality altering elder gods.
    • -
GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index dcb1e21f30f..cc17b5e0f24 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -10980,3 +10980,67 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. flexible enough to crawl through vents (while not carrying equipment). They also can pass through plastic flaps. - bugfix: Fixed adamantine vocal cord (F) links not working for observers. +2017-05-07: + Anonmare: + - tweak: Removes organic check from mediborg storage container + Joan: + - rscadd: Cultists of Nar-sie have their own language. The language's key is ",n". + - balance: Sigils of Transgression are slightly brighter. + Moonlighting Mac: + - experiment: Due to budget cuts and oil synthesis replacing expensive processes + of digging up haunted primeval ashwalker burial grounds, Nanotransen has taught + chemists how to make plastic from chemicals in the hopes that new plastic products + can reduce expenditure on metal and glass. + - rscadd: you can now make plastic sheets from chemistry out of heated up crude + oil, ash & sodium chloride + MrStonedOne: + - bugfix: fixed bug that caused an infinite connection loop when connecting on a + new computer or computer with recently changed hardware. + - rscadd: Moved to a new system to make top menu items easier to edit. + - tweak: Moved icon size stuff to a sub menu + - rscadd: Added option to change icon scaling mode. + - bugfix: Byond added fancy shader supported scaling(Point Sampling), this sucks + because it's blurry, the default for /tg/station has changed back to the old + nearest neighbor scaling. + Penguaro: + - bugfix: Adjusted the Examine description of the right-most tiles of the Space + Station 13 sign to be consistent with the rest of the tiles. + - bugfix: Anywhere there was lava below a tile on the station is now space. + Robustin: + - tweak: c4 planting is now 40% faster + coiax: + - bugfix: Smartfridges no longer magically gain medicines if deconstructed and rebuilt. + - rscadd: Ash walkers now know and speak Draconic by default, but still know Galactic + Common. Remember, Galcom's language key is ",0" and you can review your known + languages with the Language Menu. + octareenroon91: + - rscadd: Showers and sinks added to gulag and mining station for hygiene and fire + safety. + - rscadd: Watertanks added to mining station for convenient fire extinguisher refill. +2017-05-08: + Dorsisdwarf: + - bugfix: Fixed being unable to hit museum cases in melee + Joan: + - tweak: The verb to Assert Leadership over the cult has been replaced with an action + button that does the same thing, but is much more visible. + Moonlighting Mac says: + - tweak: After a recent trade fair, employees have took it upon themselves to learn + how to craft leather objects out of finished leather sheets, for novices they + are pretty good at it! Try it yourself! + - rscadd: Muzzles to silence people are now craftable out of leather sheets. + - rscdel: You can no longer print off designs from a bio-generator that can now + be crafted out of leather sheets. + - tweak: Complete sheets of leather can be printed from the bio-generator for 150 + biomass to accommodate for a loss of designs. + - experiment: Specialist objects from the leather & cloth category bio-generator + category were not removed as to encourage interdepartmental interaction & balance. + Penguaro: + - rscadd: The Slime Scanner is available from the Autolathe. + - tweak: The Design Names in the various machines are now capitalized consistently + coiax: + - bugfix: Fixes various mobs speaking languages that they were only supposed to + understand. + - bugfix: Fixes being able to bypass language restrictions by selecting languages + you can't speak as your default language. + ninjanomnom: + - tweak: Highlander no longer breaks your speakers diff --git a/html/changelogs/AutoChangeLog-pr-27053.yml b/html/changelogs/AutoChangeLog-pr-27053.yml new file mode 100644 index 00000000000..65ab5ed7f9e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-27053.yml @@ -0,0 +1,4 @@ +author: "Penguaro" +delete-after: True +changes: + - tweak: "Adjusts Meteor Shuttle Name" diff --git a/icons/misc/language.dmi b/icons/misc/language.dmi index e961c351912..081bbf1aa3c 100644 Binary files a/icons/misc/language.dmi and b/icons/misc/language.dmi differ diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index 58c877d4d95..ae30a592d5b 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/icons/mob/jungle/arachnid.dmi b/icons/mob/jungle/arachnid.dmi new file mode 100644 index 00000000000..a1db8e351f0 Binary files /dev/null and b/icons/mob/jungle/arachnid.dmi differ diff --git a/interface/menu.dm b/interface/menu.dm new file mode 100644 index 00000000000..4bebd5b2023 --- /dev/null +++ b/interface/menu.dm @@ -0,0 +1,203 @@ +/* +/datum/menu/Example/verb/Example() + set name = "" //if this starts with @ the verb is not created and name becomes the command to invoke. + set desc = "" //desc is the text given to this entry in the menu + //You can not use src in these verbs. It will be the menu at compile time, but the client at runtime. +*/ + +GLOBAL_LIST_EMPTY(menulist) + +/world/proc/load_menu() + for (var/typepath in subtypesof(/datum/menu)) + new typepath() + +/datum/menu + var/name + var/list/children + var/datum/menu/myparent + var/list/verblist + var/checkbox = CHECKBOX_NONE //checkbox type. + var/default //default checked type. + //Set to true to append our children to our parent, + //Rather then add us as a node (used for having more then one checkgroups in the same menu) + var/abstract = FALSE + +/datum/menu/New() + var/ourentry = GLOB.menulist[type] + children = list() + verblist = list() + if (ourentry) + if (islist(ourentry)) //some of our childern already loaded + Add_children(ourentry) + else + stack_trace("Menu item double load: [type]") + qdel(src) + return + + GLOB.menulist[type] = src + + Load_verbs(type, typesof("[type]/verb")) + + var/datum/menu/parent = GLOB.menulist[parent_type] + if (!parent) + GLOB.menulist[parent_type] = list(src) + else if (islist(parent)) + parent += src + else + parent.Add_children(list(src)) + +/datum/menu/proc/Set_parent(datum/menu/parent) + myparent = parent + if (abstract) + myparent.Add_children(children) + var/list/verblistoftypes = list() + for(var/thing in verblist) + LAZYADD(verblistoftypes[verblist[thing]], thing) + + for(var/verbparenttype in verblistoftypes) + myparent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype]) + +/datum/menu/proc/Add_children(list/kids) + if (abstract && myparent) + myparent.Add_children(kids) + return + + for(var/thing in kids) + var/datum/menu/menuitem = thing + menuitem.Set_parent(src) + if (!menuitem.abstract) + children += menuitem + +/datum/menu/proc/Load_verbs(verb_parent_type, list/verbs) + if (abstract && myparent) + myparent.Load_verbs(verb_parent_type, verbs) + return + + for (var/verbpath in verbs) + verblist[verbpath] = verb_parent_type + +/datum/menu/proc/Generate_list(client/C) + . = list() + if (length(children)) + for (var/thing in children) + var/datum/menu/child = thing + var/list/childlist = child.Generate_list(C) + if (childlist) + var/childname = "[child]" + if (childname == "[child.type]") + var/list/tree = splittext(childname, "/") + childname = tree[tree.len] + .[child.type] = "parent=[url_encode(type)];name=[url_encode(childname)]" + . += childlist + + + + for (var/thing in verblist) + var/atom/verb/verbpath = thing + if (!verbpath) + stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]") + var/list/entry = list() + entry["parent"] = "[type]" + entry["name"] = verbpath.desc + if (copytext(verbpath.name,1,2) == "@") + entry["command"] = copytext(verbpath.name,2) + else + entry["command"] = replacetext(verbpath.name, " ", "-") + var/datum/menu/verb_true_parent = GLOB.menulist[verblist[verbpath]] + var/true_checkbox = verb_true_parent.checkbox + if (true_checkbox != CHECKBOX_NONE) + var/checkedverb = verb_true_parent.Get_checked(C) + if (true_checkbox == CHECKBOX_GROUP) + if (verbpath == checkedverb) + entry["is-checked"] = TRUE + else + entry["is-checked"] = FALSE + else if (true_checkbox == CHECKBOX_TOGGLE) + entry["is-checked"] = checkedverb + + entry["command"] = ".updatemenuchecked \"[verb_true_parent.type]\" \"[verbpath]\"\n[entry["command"]]" + entry["can-check"] = TRUE + entry["group"] = "[verb_true_parent.type]" + .[verbpath] = list2params(entry) + +/datum/menu/proc/Get_checked(client/C) + return C.prefs.menuoptions[type] || default || FALSE + +/datum/menu/proc/Load_checked(client/C) //Loads the checked menu item into a new client. Used by icon menus to invoke the checked item. + return + +/datum/menu/proc/Set_checked(client/C, verbpath) + if (checkbox == CHECKBOX_GROUP) + C.prefs.menuoptions[type] = verbpath + C.prefs.save_preferences() + else if (checkbox == CHECKBOX_TOGGLE) + var/checked = Get_checked(C) + C.prefs.menuoptions[type] = !checked + C.prefs.save_preferences() + winset(C, "[verbpath]", "is-checked = [!checked]") + +/client/verb/updatemenuchecked(menutype as text, verbpath as text) + set name = ".updatemenuchecked" + menutype = text2path(menutype) + verbpath = text2path(verbpath) + if (!menutype || !verbpath) + return + var/datum/menu/M = GLOB.menulist[menutype] + if (!M) + return + if (!(verbpath in typesof("[menutype]/verb"))) + return + M.Set_checked(src, verbpath) + + +/datum/menu/Icon/Load_checked(client/C) //So we can be lazy, we invoke the "checked" menu item on menu load. + var/atom/verb/verbpath = Get_checked(C) + if (!verbpath || !(verbpath in typesof("[type]/verb"))) + return + if (copytext(verbpath.name,1,2) == "@") + winset(C, null, "command = [copytext(verbpath.name,2)]") + else + winset(C, null, "command = [replacetext(verbpath.name, " ", "-")]") + +/datum/menu/Icon/Size + checkbox = CHECKBOX_GROUP + default = /datum/menu/Icon/Size/verb/iconstretchtofit + +/datum/menu/Icon/Size/verb/iconstretchtofit() + set name = "@.winset \"mapwindow.map.icon-size=0\"" + set desc = "&Auto (stretch-to-fit)" + +/datum/menu/Icon/Size/verb/icon96() + set name = "@.winset \"mapwindow.map.icon-size=96\"" + set desc = "&96x96 (3x)" + +/datum/menu/Icon/Size/verb/icon64() + set name = "@.winset \"mapwindow.map.icon-size=64\"" + set desc = "&64x64 (2x)" + +/datum/menu/Icon/Size/verb/icon48() + set name = "@.winset \"mapwindow.map.icon-size=48\"" + set desc = "&48x48 (1.5x)" + +/datum/menu/Icon/Size/verb/icon32() + set name = "@.winset \"mapwindow.map.icon-size=32\"" + set desc = "&32x32 (1x)" + + +/datum/menu/Icon/Scaling + checkbox = CHECKBOX_GROUP + name = "Scaling Mode" + default = /datum/menu/Icon/Scaling/verb/NN + +/datum/menu/Icon/Scaling/verb/NN() + set name = "@.winset \"mapwindow.map.zoom-mode=distort\"" + set desc = "Nearest Neighbor" + +/datum/menu/Icon/Scaling/verb/PS() + set name = "@.winset \"mapwindow.map.zoom-mode=normal\"" + set desc = "Point Sampling" + +/datum/menu/Icon/Scaling/verb/BL() + set name = "@.winset \"mapwindow.map.zoom-mode=blur\"" + set desc = "Bilinear" + diff --git a/interface/skin.dmf b/interface/skin.dmf index cad5be8b685..a596cd77076 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -1038,60 +1038,6 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem - name = "&Icons" - command = "" - category = "" - is-checked = false - can-check = false - group = "" - is-disabled = false - saved-params = "is-checked" - elem "auto" - name = "&Auto (stretch-to-fit)" - command = ".winset \"mapwindow.map.icon-size=0\"" - category = "&Icons" - is-checked = true - can-check = true - group = "size" - is-disabled = false - saved-params = "is-checked" - elem "icon96" - name = "&96x96 (3x)" - command = ".winset \"mapwindow.map.icon-size=96\"" - category = "&Icons" - is-checked = false - can-check = true - group = "size" - is-disabled = false - saved-params = "is-checked" - elem "icon64" - name = "&64x64 (2x)" - command = ".winset \"mapwindow.map.icon-size=64\"" - category = "&Icons" - is-checked = false - can-check = true - group = "size" - is-disabled = false - saved-params = "is-checked" - elem "icon48" - name = "&48x48 (1.5x)" - command = ".winset \"mapwindow.map.icon-size=48\"" - category = "&Icons" - is-checked = false - can-check = true - group = "size" - is-disabled = false - saved-params = "is-checked" - elem "icon32" - name = "&32x32" - command = ".winset \"mapwindow.map.icon-size=32\"" - category = "&Icons" - is-checked = false - can-check = true - group = "size" - is-disabled = false - saved-params = "is-checked" elem name = "&Help" command = "" @@ -1359,6 +1305,7 @@ window "mapwindow" on-show = "" on-hide = "" style = "" + zoom-mode = "distort" window "infowindow" elem "infowindow" diff --git a/sound/misc/highlander.ogg b/sound/misc/highlander.ogg index 2116f8a9724..01148b55dbf 100644 Binary files a/sound/misc/highlander.ogg and b/sound/misc/highlander.ogg differ diff --git a/sound/misc/highlander_delayed.ogg b/sound/misc/highlander_delayed.ogg index d1cce707811..26453496628 100644 Binary files a/sound/misc/highlander_delayed.ogg and b/sound/misc/highlander_delayed.ogg differ diff --git a/sound/misc/highlander_only_one.ogg b/sound/misc/highlander_only_one.ogg index 3b69d26ade5..6458d10ab65 100644 Binary files a/sound/misc/highlander_only_one.ogg and b/sound/misc/highlander_only_one.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 4988a657435..c1c85b3dd23 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -45,6 +45,7 @@ #include "code\__DEFINES\maps.dm" #include "code\__DEFINES\math.dm" #include "code\__DEFINES\MC.dm" +#include "code\__DEFINES\menu.dm" #include "code\__DEFINES\misc.dm" #include "code\__DEFINES\mobs.dm" #include "code\__DEFINES\monkeys.dm" @@ -967,6 +968,7 @@ #include "code\modules\admin\admin_investigate.dm" #include "code\modules\admin\admin_ranks.dm" #include "code\modules\admin\admin_verbs.dm" +#include "code\modules\admin\adminmenu.dm" #include "code\modules\admin\banjob.dm" #include "code\modules\admin\create_mob.dm" #include "code\modules\admin\create_object.dm" @@ -1383,7 +1385,8 @@ #include "code\modules\language\language_menu.dm" #include "code\modules\language\machine.dm" #include "code\modules\language\monkey.dm" -#include "code\modules\language\ratvar.dm" +#include "code\modules\language\narsian.dm" +#include "code\modules\language\ratvarian.dm" #include "code\modules\language\slime.dm" #include "code\modules\language\swarmer.dm" #include "code\modules\language\xenocommon.dm" @@ -1666,6 +1669,7 @@ #include "code\modules\mob\living\simple_animal\hostile\hivebot.dm" #include "code\modules\mob\living\simple_animal\hostile\hostile.dm" #include "code\modules\mob\living\simple_animal\hostile\illusion.dm" +#include "code\modules\mob\living\simple_animal\hostile\jungle_mobs.dm" #include "code\modules\mob\living\simple_animal\hostile\killertomato.dm" #include "code\modules\mob\living\simple_animal\hostile\mecha_pilot.dm" #include "code\modules\mob\living\simple_animal\hostile\mimic.dm" @@ -2092,6 +2096,7 @@ #include "code\modules\zombie\items.dm" #include "code\modules\zombie\organs.dm" #include "interface\interface.dm" +#include "interface\menu.dm" #include "interface\stylesheet.dm" #include "interface\skin.dmf" // END_INCLUDE