diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 47df198e5b8..edd52324c14 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -5115,7 +5115,7 @@ "bUs" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 9; icon_state = "whitehall"},/area/medical/research{name = "Research Division"}) "bUt" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall/r_wall,/area/crew_quarters/hor) "bUu" = (/obj/machinery/power/apc{dir = 8; name = "RD Office APC"; pixel_x = -25},/obj/structure/cable,/obj/machinery/light_switch{pixel_y = -23},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/structure/flora/kirbyplants,/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) -"bUv" = (/obj/machinery/hologram/holopad,/obj/machinery/keycard_auth{pixel_x = 0; pixel_y = -24},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/light,/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/photocopier/faxmachine{department = "Research Director's Office"},/obj/structure/table/glass,/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) +"bUv" = (/obj/machinery/keycard_auth{pixel_x = 0; pixel_y = -24},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/light,/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/photocopier/faxmachine{department = "Research Director's Office"},/obj/structure/table/glass,/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) "bUw" = (/obj/item/weapon/cartridge/signal/toxins,/obj/item/weapon/cartridge/signal/toxins{pixel_x = -4; pixel_y = 2},/obj/item/weapon/cartridge/signal/toxins{pixel_x = 4; pixel_y = 6},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/camera{c_tag = "Research Director's Office"; dir = 1; network = list("Research","SS13")},/obj/item/clothing/glasses/welding/superior,/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/table/glass,/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) "bUx" = (/obj/structure/closet/secure_closet/RD,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) "bUy" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 8},/turf/simulated/floor/plasteel{dir = 2; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/crew_quarters/hor) @@ -7232,7 +7232,7 @@ "cJd" = (/obj/machinery/computer/station_alert,/turf/simulated/floor/plasteel,/area/engine/engineering) "cJe" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel,/area/engine/engineering) "cJf" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/engine/hardsuitstorage) -"cJg" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area/engine/hardsuitstorage) +"cJg" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_engineering{name = "Storage"; req_access_txt = "11"; req_one_access_txt = null},/turf/simulated/floor/plasteel,/area/engine/hardsuitstorage) "cJh" = (/obj/structure/sink{icon_state = "sink"; dir = 8; pixel_x = -12; pixel_y = 2},/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22; pixel_y = 0},/turf/simulated/floor/plasteel{tag = "icon-whitegreen (WEST)"; icon_state = "whitegreen"; dir = 8},/area/medical/virology) "cJi" = (/obj/machinery/camera{c_tag = "Engineering Chief Engineer's Office"; dir = 4; network = list("SS13")},/obj/item/device/radio/intercom{name = "station intercom (General)"; pixel_x = -28; pixel_y = 0},/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) "cJj" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) @@ -7337,7 +7337,6 @@ "cLe" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/asmaint2) "cLf" = (/obj/structure/closet/crate,/obj/item/clothing/under/color/lightpurple,/obj/item/weapon/spacecash/c200,/turf/simulated/floor/plating,/area/maintenance/asmaint2) "cLg" = (/obj/effect/spawner/window,/turf/simulated/floor/plating,/area/maintenance/asmaint) -"cLh" = (/obj/machinery/door/firedoor,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/airlock/glass_engineering{name = "Storage"; req_access_txt = "11"; req_one_access_txt = null},/turf/simulated/floor/plasteel,/area/engine/hardsuitstorage) "cLi" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/disposalpipe/segment,/obj/structure/cable,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/turf/simulated/floor/plating,/area/toxins/xenobiology) "cLj" = (/obj/machinery/door/window/southright{name = "Containment Pen"; req_access_txt = "55"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/turf/simulated/floor/engine,/area/toxins/xenobiology) "cLk" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/obj/structure/cable,/turf/simulated/floor/plating,/area/toxins/xenobiology) @@ -8921,7 +8920,7 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikafxaabcFscFtcFtcFucFvcFwcFwcFwcFvcFwcFwcFwcFvcFwcFwcFxcFtcFtcFtcFtcFtcFycFzcFAcFBcFCcFDcFEcFFcFGcfRcwWcFHcDfcvKcvKcvKcFIcEBcECcFJcFKcFLcyrcFNcDucFPcFOcFQcFScFTcSpcFVcFWcFXcFScFYcFZcDwcGacDzcDzcDzcGbcBCcGccGccDFcGdcGecGfcGgcGhcGicGjcGkcGlcGmcGncDOcGocDQcGpcDTcDTcCKcHBcoDcEhclUcyMcyLcyNcFfclUcnkclTcFfclUcyQcyScyRcyTcyTclUcusbGycJOcoAbikckPcxOcxPcxOcGAcxRcqUcGBcJPcJJcqUdlWcGDcwAcwAcwAckPbikbikaabaabbikbikbikbikbikbwocyKcvzbwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGbikaabbikaabaabcGFaabbikaabcGFaabbikaabcGFaabbikbikbikbikbikbikbikbikcDccDccDccGGcGHcFMcDdcGJcfRcGKcExcExcExcExcGLcExcFGcECcGMcGNcGOcGPcGQcGRcGScGTcGUcGVcGWcGXcGYcGZcHacHbcFYcELcDwcHccHdcDzcDzcHecBCcHfcHgcDFcHhcCAcHicHjcHkcHlcHmcHncHocHpcHocHqaabcCKcCKcCKcCKcCKcHBcoAcEhclUcIJcyVcyYcyXcEecEccEgcEfcHwcGucHZczVcIRcIQclUcusbGycJRcoAbikckPcxOcxOcxOcFjcHEcHFcHGcJScHIcCZcCZcCZcHJcHKcHLcHMbikbikbikaabaabbikbikbikbikbwobwocvzbwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGacGafxaabaabczocHOczqbikczocHOczqbikczocHOczqaabbikbikbikbikbikbikbikaabaabcDccDdcDdcDdcDdcHPcHQcHRcfRcHScfRcfRcEBcHTcfRcECcHUcHVcGOcHWcFNcHXcHYcIacIacIbcIccIdcIedmabRFcIbcIhcIicIjcIkcIlcImcIncIocIpcIqcGfcIrcIscItcIucIvcIwcIxcIycIzcIAcIBcICcIDcDPcDQcIEcIFcIFcCKcHBcoAcEhclUclUclUclUclUcJhcANcBRcJQcMccBScMecMdcMCcBVclUcuscGqcGrcGrcGrcJTcJTcJTcJTcJTcJUcKTcKbcKUcIUczbcIVczbcIWczbcIXcHMbikbikbikbikaabaabbikbikbikbikbwocvzbwoaabaabaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikczocHOczqaabczocHOczqbikczocHOczqbikbikbikaabbikbikbikbikaabaabaabbikbikaabaabcJbcJbcJbcJbcJbcJbcJbcJccJbcJbcECcJdcJecGOcHWcFNcJfcFNcJgcLhcDtcJicJjcFWcJkcFRcDtcJmcDzcDwcJncJocJpcIncJqcJrcJscJtcJucJvcJwcJtcJxcJycJzcJAcDFcJBcJCcJDcJEaabcEVcJFcJGcJHcCKcHBcoDcKWcKVcKVcKVcKXclUcFacyLcCLcFecyScCMcyTcyTcyScCNclUcuscGvbVibGycKYcKZcoAbikbikckPcJVcJWcJXcJYcJVcJWcJZcKacJVcJWcLackPaabaabaabaabaabaabaabaabaabaabbwocvzbwobwobwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjcbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikczocHOczqaabczocHOczqbikczocHOczqbikbikbikaabbikbikbikbikaabaabaabbikbikaabaabcJbcJbcJbcJbcJbcJbcJbcJccJbcJbcECcJdcJecGOcHWcFNcJfcFNcFNcJgcDtcJicJjcFWcJkcFRcDtcJmcDzcDwcJncJocJpcIncJqcJrcJscJtcJucJvcJwcJtcJxcJycJzcJAcDFcJBcJCcJDcJEaabcEVcJFcJGcJHcCKcHBcoDcKWcKVcKVcKVcKXclUcFacyLcCLcFecyScCMcyTcyTcyScCNclUcuscGvbVibGycKYcKZcoAbikbikckPcJVcJWcJXcJYcJVcJWcJZcKacJVcJWcLackPaabaabaabaabaabaabaabaabaabaabbwocvzbwobwobwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjcbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikafxaabczocHOczqbikczocHOczqbikczocHOczqaabbikbikbikbikbikbikbikaabaabbikbikaabaabaabcJbcKjcKjcKkcGIcKmcKmcKncKocKocKpcKqcKrcGOcHWcGOcKscGOcGOcGOcDtcKtcKucKvcKwcKxcKycKzcKAcKBcKCcKCcKCcKDcKEcKFcKGcKHcKIcHhcCAcKJcKKcKLcKMcKNcDFcJBcKOcKPcKQcKRcDQcKScIFcIFcCKcHBcoDcEhbVibVibVibYDclUcFgcCOcDXcNDcyScPocPMcyTcPVcPQclUcuscGvbVibGycyHbGycoAbikbikckPcLicLjcLkcwAcLlcLmcLncwAcLocLpcLqckPaabaabbikbikbikbikbikbikbikbikbwocvzbxXbxXbwoaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikafxaabczocHOczqbikczocHOczqaabczocHOczqaabaabaabbikaabbikbikaabaabbikbikbikaabbikbikcJbcKjcKjcKkcLscLscLscLtcLucLvcECcLwcLxcLycLzcLAcLBcLCcLDcLDcLEcLFcLGcGOcGOcGOcLHcLIcLJcLKcLLcLMcLNcLOcLPcECcLQcLQcLRcHhcCAcLScLTcLUcLVcLWcDFcLXcLYcLZcMacMbcCKcCKcCKcCKcCKcHBcoDcEhcLbbGybGybYDclUcNEczVczVcOtcDZcQMcRwcyTdbkcYuclUcuscGvczhbGychCcITcoAbikbikckPcMpcxOcxOcwAcMpcxOcxOcwAcMpcxOcxOckPbikaabaabbikbikbikbikbikbikbikbwocLccyJbxXbwobwobwocJNcJNaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikagiaabczocMqczqbikczocMqczqbikczocMqczqaabafxaabaabaabaabaabaabbikbikbikbikbikbikaabcJbcMrcMscLscLscLscMtcMucMucMucMucMucMucMucMvcMwcMxcMycMzcMzcMzcMAcMBdcpdcodcvcMzcMBcMDcMEcMFcLMcMGcLOcLPcMHcMIcMJcMKcMLcMMcMNcMOcKNcMPcMQcMRcMScMTcMUcIDcMVcDQcMWcMXcMXcCKcHBcoAcEhbVicozcLdbYDclUcOBczVcQgcPYcySdcydczcyTdcBdcAclUcuscGvbVibGybVibVicoAaabaabckPcNncBZcxOcwAcNncBZcxOcwAcNncBZcxOckPbikbikaabaabbikbikbikbikbikbikbwocvzcyJcLecyJcLfbwoaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index edc45b22e23..adb9d60ab1f 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -16,6 +16,7 @@ Pipelines + Other Objects -> Pipe network idle_power_usage = 0 active_power_usage = 0 power_channel = ENVIRON + on_blueprints = TRUE var/nodealert = 0 var/can_unwrench = 0 diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm index 3e2f13ccab1..8ce7b1ce0ba 100644 --- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm +++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm @@ -66,3 +66,13 @@ icon_state = "circ-off" return 1 + +/obj/machinery/atmospherics/binary/circulator/attackby(var/obj/item/W as obj, var/mob/user as mob, params) + if(istype(W, /obj/item/weapon/wrench)) + var/turf/T = get_turf(src) + if(!istype(T, /turf/simulated)) + return ..() + anchored = !anchored + to_chat(user, "You [(anchored) ? "fasten" : "loosen"] \the [src] to the floor") + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + else return ..() diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 04a20338c1f..212a19f79e8 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -43,11 +43,11 @@ #define HAS_LIPS 64 #define IS_PLANT 128 #define CAN_BE_FAT 256 -#define IS_RESTRICTED 512 -#define NO_INTORGANS 1024 -#define NO_POISON 2048 -#define RADIMMUNE 4096 -#define ALL_RPARTS 8192 +#define NO_INTORGANS 512 +#define NO_POISON 1024 +#define RADIMMUNE 2048 +#define ALL_RPARTS 4096 +#define NOGUNS 8192 //Species clothing flags #define HAS_UNDERWEAR 1 @@ -66,6 +66,7 @@ #define HAS_MARKINGS 256 #define TAIL_WAGGING 512 #define NO_EYES 1024 +#define HAS_FUR 2048 //Species Diet Flags #define DIET_CARN 1 diff --git a/code/__DEFINES/math.dm b/code/__DEFINES/math.dm index e1d9888126d..d71047fe3d3 100644 --- a/code/__DEFINES/math.dm +++ b/code/__DEFINES/math.dm @@ -10,6 +10,24 @@ #define T20C 293.15 // 20degC #define TCMB 2.7 // -270.3degC -#define Clamp(x, y, z) (x <= y ? y : (x >= z ? z : x)) - -#define CLAMP01(x) (Clamp(x, 0, 1)) +#define Clamp(x, y, z) ((x) <= (y) ? (y) : ((x) >= (z) ? (z) : (x))) +#define CLAMP01(x) (Clamp((x), 0, 1)) +#define SIMPLE_SIGN(X) ((X) < 0 ? -1 : 1) +#define SIGN(X) ((X) ? SIMPLE_SIGN(X) : 0) +#define hypotenuse(Ax, Ay, Bx, By) (sqrt(((Ax) - (Bx))**2 + ((Ay) - (By))**2)) +#define Ceiling(x) (-round(-(x))) +#define Tan(x) (sin(x) / cos(x)) +#define Cot(x) (1 / Tan(x)) +#define Csc(x) (1 / sin(x)) +#define Sec(x) (1 / cos(x)) +#define Floor(x) (round(x)) +#define Inverse(x) (1 / (x)) +#define IsEven(x) ((x) % 2 == 0) +#define IsOdd(x) ((x) % 2 == 1) +#define IsInRange(val, min, max) ((min) <= (val) && (val) <= (max)) +#define IsInteger(x) (Floor(x) == (x)) +#define IsMultiple(x, y) ((x) % (y) == 0) +#define Lcm(a, b) (abs(a) / Gcd((a), (b)) * abs(b)) +#define Root(n, x) ((x) ** (1 / (n))) +#define ToDegrees(radians) ((radians) * 57.2957795) // 180 / Pi +#define ToRadians(degrees) ((degrees) * 0.0174532925) // Pi / 180 \ No newline at end of file diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 7f1a33d0b33..5e31e40a7a6 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -142,6 +142,14 @@ #define STAGE_FIVE 9 #define STAGE_SIX 11 //From supermatter shard +#define in_range(source, user) (get_dist(source, user) <= 1) + +#define RANGE_TURFS(RADIUS, CENTER) \ + block( \ + locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \ + locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \ + ) + #define FOR_DVIEW(type, range, center, invis_flags) \ dview_mob.loc = center; \ dview_mob.see_invisible = invis_flags; \ diff --git a/code/__DEFINES/mob.dm b/code/__DEFINES/mob.dm index 2bdb3432f69..82ca895b42d 100644 --- a/code/__DEFINES/mob.dm +++ b/code/__DEFINES/mob.dm @@ -76,7 +76,11 @@ #define APPEARANCE_FACIAL_HAIR_COLOR 128 #define APPEARANCE_EYE_COLOR 256 #define APPEARANCE_ALL_HAIR APPEARANCE_HAIR|APPEARANCE_HAIR_COLOR|APPEARANCE_FACIAL_HAIR|APPEARANCE_FACIAL_HAIR_COLOR -#define APPEARANCE_ALL 511 +#define APPEARANCE_HEAD_ACCESSORY 512 +#define APPEARANCE_MARKINGS 1024 +#define APPEARANCE_BODY_ACCESSORY 2048 +#define APPEARANCE_ALL_BODY APPEARANCE_ALL_HAIR|APPEARANCE_HEAD_ACCESSORY|APPEARANCE_MARKINGS|APPEARANCE_BODY_ACCESSORY +#define APPEARANCE_ALL 4095 // Intents #define I_HELP "help" @@ -97,4 +101,39 @@ #define CHEM_MOB_SPAWN_INVALID 0 #define CHEM_MOB_SPAWN_HOSTILE 1 -#define CHEM_MOB_SPAWN_FRIENDLY 2 \ No newline at end of file +#define CHEM_MOB_SPAWN_FRIENDLY 2 + +#define isobserver(A) (istype((A), /mob/dead/observer)) +#define isliving(A) (istype((A), /mob/living)) +#define isAutoAnnouncer(A) (istype((A), /mob/living/automatedannouncer)) + +#define iscarbon(A) (istype((A), /mob/living/carbon)) +#define ishuman(A) (istype((A), /mob/living/carbon/human)) +#define isbrain(A) (istype((A), /mob/living/carbon/brain)) +#define isalien(A) (istype((A), /mob/living/carbon/alien)) +#define isalienadult(A) (istype((A), /mob/living/carbon/alien/humanoid)) +#define islarva(A) (istype((A), /mob/living/carbon/alien/larva)) +#define isslime(A) (istype((A), /mob/living/carbon/slime)) + +#define isanimal(A) (istype((A), /mob/living/simple_animal)) +#define iscorgi(A) (istype((A), /mob/living/simple_animal/pet/corgi)) +#define ismouse(A) (istype((A), /mob/living/simple_animal/mouse)) +#define isbot(A) (istype((A), /mob/living/simple_animal/bot)) +#define isswarmer(A) (istype((A), /mob/living/simple_animal/hostile/swarmer)) +#define isguardian(A) (istype((A), /mob/living/simple_animal/hostile/guardian)) + +#define issilicon(A) (istype((A), /mob/living/silicon)) +#define isAI(A) (istype((A), /mob/living/silicon/ai)) +#define isrobot(A) (istype((A), /mob/living/silicon/robot)) +#define ispAI(A) (istype((A), /mob/living/silicon/pai)) + +#define isAIEye(A) (istype((A), /mob/camera/aiEye)) +#define isovermind(A) (istype((A), /mob/camera/blob)) + +#define isSpirit(A) (istype((A), /mob/spirit)) +#define ismask(A) (istype((A), /mob/spirit/mask)) + +#define isorgan(A) (istype((A), /obj/item/organ/external)) +#define hasorgans(A) (ishuman(A)) + +#define is_admin(user) (check_rights(R_ADMIN, 0, (user)) != 0) \ No newline at end of file diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index e6253c1c170..47cee347876 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -1,10 +1,3 @@ -//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a -#define RANGE_TURFS(RADIUS, CENTER) \ - block( \ - locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \ - locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \ - ) - /proc/dopage(src,target) var/href_list var/href @@ -46,13 +39,6 @@ areas |= T.loc return areas - -/proc/in_range(source, user) - if(get_dist(source, user) <= 1) - return 1 - - return 0 //not in range and not telekinetic - // Like view but bypasses luminosity check /proc/hear(var/range, var/atom/source) @@ -65,11 +51,6 @@ return heard -//We used to use linear regression to approximate the answer, but Mloc realized this was actually faster. -//And lo and behold, it is, and it's more accurate to boot. -/proc/cheap_hypotenuse(Ax,Ay,Bx,By) - return sqrt(abs(Ax - Bx)**2 + abs(Ay - By)**2) //A squared + B squared = C squared - /proc/circlerange(center=usr,radius=3) var/turf/centerturf = get_turf(center) @@ -233,53 +214,44 @@ . |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down. return . - -#define SIGN(X) ((X<0)?-1:1) - -proc - inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5) - var/turf/T - if(X1==X2) - if(Y1==Y2) - return 1 //Light cannot be blocked on same tile - else - var/s = SIGN(Y2-Y1) - Y1+=s - while(Y1!=Y2) - T=locate(X1,Y1,Z) - if(T.opacity) - return 0 - Y1+=s +/proc/inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5) + var/turf/T + if(X1==X2) + if(Y1==Y2) + return 1 //Light cannot be blocked on same tile else - var/m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1)) - var/b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles - var/signX = SIGN(X2-X1) - var/signY = SIGN(Y2-Y1) - if(X1= 0 ? a : -a -/proc/Ceiling(x) - return -round(-x) - -//Replaced in /code/__DEFINES/math.dm because holy shit man a define is faster. -/* -/proc/Clamp(val, min, max) - return max(min, min(val, max)) -*/ - -// cotangent -/proc/Cot(x) - return 1 / Tan(x) - -// cosecant -/proc/Csc(x) - return 1 / sin(x) - -/proc/Default(a, b) - return a ? a : b - -/proc/Floor(x) - return round(x) - // Greatest Common Divisor - Euclid's algorithm /proc/Gcd(a, b) return b ? Gcd(b, a % b) : a -/proc/Inverse(x) - return 1 / x - /proc/IsAboutEqual(a, b, deviation = 0.1) return abs(a - b) <= deviation -/proc/IsEven(x) - return x % 2 == 0 - -// Returns true if val is from min to max, inclusive. -/proc/IsInRange(val, min, max) - return min <= val && val <= max - -/proc/IsInteger(x) - return Floor(x) == x - -/proc/IsOdd(x) - return !IsEven(x) - -/proc/IsMultiple(x, y) - return x % y == 0 - -// Least Common Multiple -/proc/Lcm(a, b) - return abs(a) / Gcd(a, b) * abs(b) - // Performs a linear interpolation between a and b. // Note that amount=0 returns a, amount=1 returns b, and // amount=0.5 returns the mean of a and b. @@ -81,15 +29,6 @@ var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, sum += val return sum / values - -// Returns the nth root of x. -/proc/Root(n, x) - return x ** (1 / n) - -// secant -/proc/Sec(x) - return 1 / cos(x) - // The quadratic formula. Returns a list with the solutions, or an empty list // if they are imaginary. /proc/SolveQuadratic(a, b, c) @@ -103,18 +42,6 @@ var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, if(!d) return . += (-b - root) / bottom -// tangent -/proc/Tan(x) - return sin(x) / cos(x) - -/proc/ToDegrees(radians) - // 180 / Pi - return radians * 57.2957795 - -/proc/ToRadians(degrees) - // Pi / 180 - return degrees * 0.0174532925 - // Will filter out extra rotations and negative rotations // E.g: 540 becomes 180. -180 becomes 180. /proc/SimplifyDegrees(degrees) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index f8980d61ddd..3d1648fa77a 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -52,7 +52,7 @@ proc/random_hair_style(var/gender, species = "Human") if(valid_hairstyles.len) h_style = pick(valid_hairstyles) - return h_style + return h_style proc/GetOppositeDir(var/dir) switch(dir) diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index f85e318de76..59784a357e0 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -208,6 +208,14 @@ proc/checkhtml(var/t) t = replacetext(t, char, repl_chars[char]) return t +//Strips the first char and returns it and the new string as a list +/proc/strip_first(t) + return list(copytext(t, 1, 2), copytext(t, 2, 0)) + +//Strips the last char and returns it and the new string as a list +/proc/strip_last(t) + return list(copytext(t, 1, length(t)), copytext(t, length(t))) + //Adds 'u' number of zeros ahead of the text 't' /proc/add_zero(t, u) while (length(t) < u) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 0147bffe195..ff4ee54b2e9 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -185,9 +185,6 @@ Turf and target are seperate in case you want to teleport some distance from a t ///////////////////////////////////////////////////////////////////////// -/proc/sign(x) - return x!=0?x/abs(x):0 - /proc/getline(atom/M,atom/N)//Ultra-Fast Bresenham Line-Drawing Algorithm var/px=M.x //starting x var/py=M.y @@ -196,8 +193,8 @@ Turf and target are seperate in case you want to teleport some distance from a t var/dy=N.y-py var/dxabs=abs(dx)//Absolute value of x distance var/dyabs=abs(dy) - var/sdx=sign(dx) //Sign of x distance (+ or -) - var/sdy=sign(dy) + var/sdx=SIGN(dx) //Sign of x distance (+ or -) + var/sdy=SIGN(dy) var/x=dxabs>>1 //Counters for steps taken, setting to distance/2 var/y=dyabs>>1 //Bit-shifting makes me l33t. It also makes getline() unnessecarrily fast. var/j //Generic integer for counting diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 617a0af3d7d..ec3be384bad 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -30,3 +30,4 @@ var/global/list/beacons = list() var/global/list/shuttle_caller_list = list() //list of all communication consoles and AIs, for automatic shuttle calls when there are none. var/global/list/tracked_implants = list() //list of all current implants that are tracked to work out what sort of trek everyone is on. Sadly not on lavaworld not implemented... var/global/list/abductor_equipment = list() //list of all abductor equipment +var/global/list/global_intercoms = list() //list of all intercomms, across all z-levels \ No newline at end of file diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index 0a891be21f5..233add211f6 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -50,7 +50,8 @@ T.client.screen -= button qdel(button) button = null - T.actions.Remove(src) + if(T.actions) + T.actions.Remove(src) T.update_action_buttons() owner = null return diff --git a/code/controllers/ProcessScheduler/core/processScheduler.dm b/code/controllers/ProcessScheduler/core/processScheduler.dm index 1c6a0c91a28..86e1fc5bbe9 100644 --- a/code/controllers/ProcessScheduler/core/processScheduler.dm +++ b/code/controllers/ProcessScheduler/core/processScheduler.dm @@ -355,16 +355,11 @@ var/global/datum/controller/processScheduler/processScheduler /datum/controller/processScheduler/proc/updateTimeAllowance() // Time allowance goes down linearly with world.cpu. var/tmp/error = cpuAverage - 100 - var/tmp/timeAllowanceDelta = sign(error) * -0.5 * world.tick_lag * max(0, 0.001 * abs(error)) + var/tmp/timeAllowanceDelta = SIMPLE_SIGN(error) * -0.5 * world.tick_lag * max(0, 0.001 * abs(error)) //timeAllowance = world.tick_lag * min(1, 0.5 * ((200/max(1,cpuAverage)) - 1)) timeAllowance = min(timeAllowanceMax, max(0, timeAllowance + timeAllowanceDelta)) -/datum/controller/processScheduler/proc/sign(var/x) - if (x == 0) - return 1 - return x / abs(x) - /datum/controller/processScheduler/proc/statProcesses() if(!isRunning) stat("Processes", "Scheduler not running") diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 9cf42a511fd..f4e795f6c77 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -68,6 +68,8 @@ var/assistantlimit = 0 //enables assistant limiting var/assistantratio = 2 //how many assistants to security members + var/traitor_objectives_amount = 2 + var/max_maint_drones = 5 //This many drones can spawn, var/allow_drone_spawn = 1 //assuming the admin allow them to. var/drone_build_time = 1200 //A drone will become available every X ticks since last drone spawn. Default is 2 minutes. @@ -598,6 +600,8 @@ config.limbs_can_break = value if("shuttle_refuel_delay") config.shuttle_refuel_delay = text2num(value) + if("traitor_objectives_amount") + config.traitor_objectives_amount = text2num(value) if("reactionary_explosions") config.reactionary_explosions = 1 if("bombcap") diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index a70875a7090..d07b6e3eb73 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -126,6 +126,7 @@ proc/get_id_photo(var/mob/living/carbon/human/H) var/icon/preview_icon = null + var/obj/item/organ/external/head/head_organ = H.get_organ("head") var/g = "m" if (H.gender == FEMALE) @@ -170,32 +171,32 @@ proc/get_id_photo(var/mob/living/carbon/human/H) eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD) face_s.Blend(eyes_s, ICON_OVERLAY) - var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] + var/datum/sprite_accessory/hair_style = hair_styles_list[head_organ.h_style] if(hair_style) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") // I'll want to make a species-specific proc for this sooner or later // But this'll do for now - if(H.get_species() == "Slime People") + if(head_organ.species.name == "Slime People") hair_s.Blend(rgb(H.r_skin, H.g_skin, H.b_skin, 160), ICON_ADD) else - hair_s.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) + hair_s.Blend(rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair), ICON_ADD) face_s.Blend(hair_s, ICON_OVERLAY) //Head Accessory - if(H.species.bodyflags & HAS_HEAD_ACCESSORY) - var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[H.ha_style] + if(head_organ.species.bodyflags & HAS_HEAD_ACCESSORY) + var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[head_organ.ha_style] if(head_accessory_style && head_accessory_style.species_allowed) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") - head_accessory_s.Blend(rgb(H.r_headacc, H.g_headacc, H.b_headacc), ICON_ADD) + head_accessory_s.Blend(rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc), ICON_ADD) face_s.Blend(head_accessory_s, ICON_OVERLAY) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[head_organ.f_style] if(facial_hair_style && facial_hair_style.species_allowed) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(H.get_species() == "Slime People") + if(head_organ.species.name == "Slime People") facial_s.Blend(rgb(H.r_skin, H.g_skin, H.b_skin, 160), ICON_ADD) else - facial_s.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) + facial_s.Blend(rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial), ICON_ADD) face_s.Blend(facial_s, ICON_OVERLAY) //Markings diff --git a/code/datums/diseases/advance/symptoms/beard.dm b/code/datums/diseases/advance/symptoms/beard.dm index 1dda9b46f7f..2ce411367f8 100644 --- a/code/datums/diseases/advance/symptoms/beard.dm +++ b/code/datums/diseases/advance/symptoms/beard.dm @@ -30,20 +30,21 @@ BONUS var/mob/living/M = A.affected_mob if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/head_organ = H.get_organ("head") switch(A.stage) if(1, 2) to_chat(H, "Your chin itches.") - if(H.f_style == "Shaved") - H.f_style = "Jensen Beard" - H.update_hair() + if(head_organ.f_style == "Shaved") + head_organ.f_style = "Jensen Beard" + H.update_fhair() if(3, 4) to_chat(H, "You feel tough.") - if(!(H.f_style == "Dwarf Beard") && !(H.f_style == "Very Long Beard") && !(H.f_style == "Full Beard")) - H.f_style = "Full Beard" - H.update_hair() + if(!(head_organ.f_style == "Dwarf Beard") && !(head_organ.f_style == "Very Long Beard") && !(head_organ.f_style == "Full Beard")) + head_organ.f_style = "Full Beard" + H.update_fhair() else to_chat(H, "You feel manly!") - if(!(H.f_style == "Dwarf Beard") && !(H.f_style == "Very Long Beard")) - H.f_style = pick("Dwarf Beard", "Very Long Beard") - H.update_hair() + if(!(head_organ.f_style == "Dwarf Beard") && !(head_organ.f_style == "Very Long Beard")) + head_organ.f_style = pick("Dwarf Beard", "Very Long Beard") + H.update_fhair() return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index b25c4bacf47..99f670c258e 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -31,7 +31,7 @@ Bonus switch(A.stage) if(2) if(M.reagents.get_reagent_amount("oculine")<10) - M.reagents.add_reagent("oculine"=10) + M.reagents.add_reagent("oculine", 10) to_chat(M, "Your hearing feels clearer and crisp.") if(3) if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("oculine") < 10 ) diff --git a/code/datums/diseases/advance/symptoms/shedding.dm b/code/datums/diseases/advance/symptoms/shedding.dm index f7f52984c0b..e79b87d1d4b 100644 --- a/code/datums/diseases/advance/symptoms/shedding.dm +++ b/code/datums/diseases/advance/symptoms/shedding.dm @@ -31,18 +31,20 @@ BONUS to_chat(M, "[pick("Your scalp itches.", "Your skin feels flakey.")]") if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/head_organ = H.get_organ("head") switch(A.stage) if(3, 4) - if(!(H.h_style == "Bald") && !(H.h_style == "Balding Hair")) + if(!(head_organ.h_style == "Bald") && !(head_organ.h_style == "Balding Hair")) to_chat(H, "Your hair starts to fall out in clumps...") spawn(50) - H.h_style = "Balding Hair" + head_organ.h_style = "Balding Hair" H.update_hair() if(5) - if(!(H.f_style == "Shaved") || !(H.h_style == "Bald")) + if(!(head_organ.f_style == "Shaved") || !(head_organ.h_style == "Bald")) to_chat(H, "Your hair starts to fall out in clumps...") spawn(50) - H.f_style = "Shaved" - H.h_style = "Bald" + head_organ.f_style = "Shaved" + head_organ.h_style = "Bald" H.update_hair() + H.update_fhair() return \ No newline at end of file diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index 64079f0fddc..8ba67750c06 100644 --- a/code/datums/diseases/gbs.dm +++ b/code/datums/diseases/gbs.dm @@ -38,4 +38,16 @@ if(prob(50)) affected_mob.gib() else - return \ No newline at end of file + return + +/datum/disease/gbs/curable + name = "Non-Contagious GBS" + stage_prob = 5 + spread_text = "Non-Contagious" + spread_flags = SPECIAL + cure_text = "Cryoxadone" + cures = list("cryoxadone") + cure_chance = 10 + agent = "gibbis" + spread_flags = NON_CONTAGIOUS + disease_flags = CURABLE \ No newline at end of file diff --git a/code/datums/diseases/kuru.dm b/code/datums/diseases/kuru.dm new file mode 100644 index 00000000000..67cfd3e8693 --- /dev/null +++ b/code/datums/diseases/kuru.dm @@ -0,0 +1,51 @@ +/datum/disease/kuru + name = "Space Kuru" + max_stages = 4 + stage_prob = 5 + spread_text = "Non-Contagious" + spread_flags = SPECIAL + cure_text = "Incurable" + agent = "Prions" + viable_mobtypes = list(/mob/living/carbon/human) + desc = "Uncontrollable laughing." + severity = BIOHAZARD + spread_flags = NON_CONTAGIOUS + +/datum/disease/kuru/stage_act() + ..() + switch(stage) + if(1) + if(prob(50)) + affected_mob.emote("laugh") + if(prob(50)) + affected_mob.Jitter(25) + if(2) + if (prob(50)) + affected_mob.visible_message("[affected_mob] laughs uncontrollably!") + affected_mob.Stun(10) + affected_mob.Weaken(10) + affected_mob.Jitter(250) + affected_mob.drop_l_hand() + affected_mob.drop_r_hand() + if(3) + if(prob(25)) + to_chat(affected_mob, "You feel like you are about to drop dead!") + to_chat(affected_mob, "Your body convulses painfully!") + affected_mob.drop_l_hand() + affected_mob.drop_r_hand() + affected_mob.adjustBruteLoss(5) + affected_mob.adjustOxyLoss(5) + affected_mob.Stun(10) + affected_mob.Weaken(10) + affected_mob.Jitter(250) + affected_mob.visible_message("[affected_mob] laughs uncontrollably!") + if(4) + if(prob(25)) + to_chat(affected_mob, "You feel like you are going to die!") + affected_mob.adjustOxyLoss(75) + affected_mob.adjustBruteLoss(75) + affected_mob.drop_l_hand() + affected_mob.drop_r_hand() + affected_mob.Stun(10) + affected_mob.Weaken(10) + affected_mob.visible_message("[affected_mob] laughs uncontrollably!") \ No newline at end of file diff --git a/code/datums/diseases/vampire.dm b/code/datums/diseases/vampire.dm new file mode 100644 index 00000000000..dbcc9bbb3c0 --- /dev/null +++ b/code/datums/diseases/vampire.dm @@ -0,0 +1,34 @@ +/datum/disease/vampire + name = "Grave Fever" + max_stages = 3 + stage_prob = 5 + spread_text = "Non-Contagious" + spread_flags = SPECIAL + cure_text = "Antibiotics" + cures = list("spaceacillin") + agent = "Grave Dust" + cure_chance = 20 + viable_mobtypes = list(/mob/living/carbon/human) + severity = DANGEROUS + disease_flags = CURABLE + spread_flags = NON_CONTAGIOUS + +/datum/disease/vampire/stage_act() + ..() + var/toxdamage = stage * 2 + var/stuntime = stage * 2 + + if(prob(10)) + affected_mob.emote(pick("cough","groan", "gasp")) + affected_mob.losebreath++ + + if(prob(15)) + if(prob(33)) + to_chat(affected_mob, "You feel sickly and weak.") + affected_mob.slowed += 3 + affected_mob.adjustToxLoss(toxdamage) + + if(prob(5)) + to_chat(affected_mob, "Your joints ache horribly!") + affected_mob.Weaken(stuntime) + affected_mob.Stun(stuntime) \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index b6c8365c577..3173c201e12 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -485,13 +485,13 @@ if(!def_value)//If it's a custom objective, it will be an empty string. def_value = "custom" - var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "blood", "debrain", "protect", "prevent", "harm", "brig", "hijack", "escape", "survive", "steal", "download", "nuclear", "capture", "absorb", "destroy", "maroon", "identity theft", "custom") + var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "blood", "debrain", "protect", "prevent", "brig", "hijack", "escape", "survive", "steal", "download", "nuclear", "capture", "absorb", "destroy", "maroon", "identity theft", "custom") if (!new_obj_type) return var/datum/objective/new_objective = null switch (new_obj_type) - if ("assassinate","protect","debrain", "harm", "brig", "maroon") + if ("assassinate","protect","debrain", "brig", "maroon") //To determine what to name the objective in explanation text. var/objective_type_capital = uppertext(copytext(new_obj_type, 1,2))//Capitalize first letter. var/objective_type_text = copytext(new_obj_type, 2)//Leave the rest of the text. diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index f6295599199..327ac67c801 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -54,8 +54,13 @@ var/list/uplink_items = list() var/list/excludefrom = list() //Empty list does nothing. Place the name of gamemode you don't want this item to be available in here. This is so you dont have to list EVERY mode to exclude something. var/list/job = null var/surplus = 100 //Chance of being included in the surplus crate (when pick() selects it) + var/hijack_only = 0 //can this item be purchased only during hijackings? /datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/device/uplink/U) + if(hijack_only) + if(!(locate(/datum/objective/hijack) in usr.mind.objectives)) + to_chat(usr, "The Syndicate lacks resources to provide you with this item.") + return if(item) U.uses -= max(cost, 0) U.used_TC += cost @@ -89,15 +94,16 @@ var/list/uplink_items = list() var/obj/I = spawn_item(get_turf(user), U) - if(ishuman(user)) - var/mob/living/carbon/human/A = user - A.put_in_any_hand_if_possible(I) + if(I) + if(ishuman(user)) + var/mob/living/carbon/human/A = user + A.put_in_any_hand_if_possible(I) - if(istype(I,/obj/item/weapon/storage/box/) && I.contents.len>0) - for(var/atom/o in I) - U.purchase_log += "\icon[o]" - else - U.purchase_log += "\icon[I]" + if(istype(I,/obj/item/weapon/storage/box/) && I.contents.len>0) + for(var/atom/o in I) + U.purchase_log += "\icon[o]" + else + U.purchase_log += "\icon[I]" //U.interact(user) return 1 @@ -174,6 +180,16 @@ var/list/uplink_items = list() cost = 13 job = list("Chaplain") +/datum/uplink_item/jobspecific/artistic_toolbox + name = "Artistic Toolbox" + desc = "An accursed toolbox that grants its followers extreme power at the cost of requiring repeated sacrifices to it. If sacrifices are not provided, it will turn on its follower." + reference = "HGAT" + item = /obj/item/weapon/storage/toolbox/green/memetic + cost = 20 + job = list("Chaplain") + surplus = 0 //No lucky chances from the crate; if you get this, this is ALL you're getting + hijack_only = 1 //This is a murderbone weapon, as such, it should only be available in those scenarios. + //Janitor /datum/uplink_item/jobspecific/cautionsign @@ -235,6 +251,16 @@ var/list/uplink_items = list() cost = 5 job = list("Barber") +//Botanist + +/datum/uplink_item/jobspecific/bee_briefcase + name = "Briefcase Full of Bees" + desc = "A seemingly innocent briefcase full of not-so-innocent Syndicate-bred bees. Inject the case with blood to train the bees to ignore the donor(s). It also wirelessly taps into station intercomms to broadcast a message of TERROR." + reference = "BEE" + item = /obj/item/weapon/bee_briefcase + cost = 10 + job = list("Botanist") + //Engineer /datum/uplink_item/jobspecific/powergloves @@ -302,7 +328,7 @@ var/list/uplink_items = list() reference = "TPB" item = /obj/item/weapon/reagent_containers/glass/bottle/traitor cost = 2 - job = list("Scientist","Research Director","Chief Medical Officer","Medical Doctor","Psychiatrist","Chemist","Paramedic","Virologist","Bartender") + job = list("Research Director","Chief Medical Officer","Medical Doctor","Psychiatrist","Paramedic","Virologist","Bartender") // DANGEROUS WEAPONS @@ -618,7 +644,7 @@ var/list/uplink_items = list() /datum/uplink_item/stealthy_weapons/sleepy_pen name = "Sleepy Pen" - desc = "A syringe disguised as a functional pen. It's filled with a potent anaesthetic. \The pen holds two doses of the mixture. The pen can be refilled." + desc = "A syringe disguised as a functional pen. It's filled with a potent anaesthetic. \ The pen holds two doses of the mixture. The pen can be refilled." reference = "SP" item = /obj/item/weapon/pen/sleepy cost = 8 @@ -673,7 +699,7 @@ var/list/uplink_items = list() /datum/uplink_item/stealthy_weapons/dehy_carp name = "Dehydrated Space Carp" - desc = "Just add water to make your very own hostile to everything space carp. It looks just like a plushie." + desc = "Just add water to make your very own hostile to everything space carp. It looks just like a plushie. The first person to squeeze it will be registered as its owner, who it will not attack. If no owner is registered, it'll just attack everyone." reference = "DSC" item = /obj/item/toy/carpplushie/dehy_carp cost = 3 diff --git a/code/defines/procs/AStar.dm b/code/defines/procs/AStar.dm index 1750814c228..1ec4f4eb7fc 100644 --- a/code/defines/procs/AStar.dm +++ b/code/defines/procs/AStar.dm @@ -157,7 +157,7 @@ Actual Adjacent procs : for(var/dir in cardinal) T = get_step(src,dir) - if(simulated_only && !istype(T)) + if(!T || (simulated_only && !istype(T))) continue if(!T.density && !LinkBlockedWithAccess(T,caller, ID)) L.Add(T) diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 868d0e901a7..1706763b824 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -2327,6 +2327,7 @@ area/security/podbay /area/awaymission name = "\improper Strange Location" icon_state = "away" + report_alerts = 0 /area/awaymission/example name = "\improper Strange Station" diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index a15170a3956..93d7cc473dc 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -133,19 +133,20 @@ var/global/list/bad_blocks[0] ResetUI(1) // Hair // FIXME: Species-specific defaults pls - if(!character.h_style) - character.h_style = "Skinhead" - var/hair = hair_styles_list.Find(character.h_style) + var/obj/item/organ/external/head/H = character.get_organ("head") + if(!H.h_style) + H.h_style = "Skinhead" + var/hair = hair_styles_list.Find(H.h_style) // Facial Hair - if(!character.f_style) - character.f_style = "Shaved" - var/beard = facial_hair_styles_list.Find(character.f_style) + if(!H.f_style) + H.f_style = "Shaved" + var/beard = facial_hair_styles_list.Find(H.f_style) // Head Accessory - if(!character.ha_style) - character.ha_style = "None" - var/headacc = head_accessory_styles_list.Find(character.ha_style) + if(!H.ha_style) + H.ha_style = "None" + var/headacc = head_accessory_styles_list.Find(H.ha_style) /*// Body Accessory if(!character.body_accessory) @@ -157,13 +158,13 @@ var/global/list/bad_blocks[0] character.m_style = "None" var/marks = marking_styles_list.Find(character.m_style) - SetUIValueRange(DNA_UI_HAIR_R, character.r_hair, 255, 1) - SetUIValueRange(DNA_UI_HAIR_G, character.g_hair, 255, 1) - SetUIValueRange(DNA_UI_HAIR_B, character.b_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_R, H.r_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_G, H.g_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_B, H.b_hair, 255, 1) - SetUIValueRange(DNA_UI_BEARD_R, character.r_facial, 255, 1) - SetUIValueRange(DNA_UI_BEARD_G, character.g_facial, 255, 1) - SetUIValueRange(DNA_UI_BEARD_B, character.b_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_R, H.r_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_G, H.g_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_B, H.b_facial, 255, 1) SetUIValueRange(DNA_UI_EYES_R, character.r_eyes, 255, 1) SetUIValueRange(DNA_UI_EYES_G, character.g_eyes, 255, 1) @@ -173,9 +174,9 @@ var/global/list/bad_blocks[0] SetUIValueRange(DNA_UI_SKIN_G, character.g_skin, 255, 1) SetUIValueRange(DNA_UI_SKIN_B, character.b_skin, 255, 1) - SetUIValueRange(DNA_UI_HACC_R, character.r_headacc, 255, 1) - SetUIValueRange(DNA_UI_HACC_G, character.g_headacc, 255, 1) - SetUIValueRange(DNA_UI_HACC_B, character.b_headacc, 255, 1) + SetUIValueRange(DNA_UI_HACC_R, H.r_headacc, 255, 1) + SetUIValueRange(DNA_UI_HACC_G, H.g_headacc, 255, 1) + SetUIValueRange(DNA_UI_HACC_B, H.b_headacc, 255, 1) SetUIValueRange(DNA_UI_MARK_R, character.r_markings, 255, 1) SetUIValueRange(DNA_UI_MARK_G, character.g_markings, 255, 1) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 781c3a1d230..53f248d1e91 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -131,13 +131,14 @@ src.dna.UpdateUI() dna.check_integrity() var/mob/living/carbon/human/H = src - H.r_hair = dna.GetUIValueRange(DNA_UI_HAIR_R, 255) - H.g_hair = dna.GetUIValueRange(DNA_UI_HAIR_G, 255) - H.b_hair = dna.GetUIValueRange(DNA_UI_HAIR_B, 255) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + head_organ.r_hair = dna.GetUIValueRange(DNA_UI_HAIR_R, 255) + head_organ.g_hair = dna.GetUIValueRange(DNA_UI_HAIR_G, 255) + head_organ.b_hair = dna.GetUIValueRange(DNA_UI_HAIR_B, 255) - H.r_facial = dna.GetUIValueRange(DNA_UI_BEARD_R, 255) - H.g_facial = dna.GetUIValueRange(DNA_UI_BEARD_G, 255) - H.b_facial = dna.GetUIValueRange(DNA_UI_BEARD_B, 255) + head_organ.r_facial = dna.GetUIValueRange(DNA_UI_BEARD_R, 255) + head_organ.g_facial = dna.GetUIValueRange(DNA_UI_BEARD_G, 255) + head_organ.b_facial = dna.GetUIValueRange(DNA_UI_BEARD_B, 255) H.r_skin = dna.GetUIValueRange(DNA_UI_SKIN_R, 255) H.g_skin = dna.GetUIValueRange(DNA_UI_SKIN_G, 255) @@ -147,9 +148,9 @@ H.g_eyes = dna.GetUIValueRange(DNA_UI_EYES_G, 255) H.b_eyes = dna.GetUIValueRange(DNA_UI_EYES_B, 255) - H.r_headacc = dna.GetUIValueRange(DNA_UI_HACC_R, 255) - H.g_headacc = dna.GetUIValueRange(DNA_UI_HACC_G, 255) - H.b_headacc = dna.GetUIValueRange(DNA_UI_HACC_B, 255) + head_organ.r_headacc = dna.GetUIValueRange(DNA_UI_HACC_R, 255) + head_organ.g_headacc = dna.GetUIValueRange(DNA_UI_HACC_G, 255) + head_organ.b_headacc = dna.GetUIValueRange(DNA_UI_HACC_B, 255) H.r_markings = dna.GetUIValueRange(DNA_UI_MARK_R, 255) H.g_markings = dna.GetUIValueRange(DNA_UI_MARK_G, 255) @@ -168,17 +169,17 @@ //Hair var/hair = dna.GetUIValueRange(DNA_UI_HAIR_STYLE,hair_styles_list.len) if((0 < hair) && (hair <= hair_styles_list.len)) - H.h_style = hair_styles_list[hair] + head_organ.h_style = hair_styles_list[hair] //Facial Hair var/beard = dna.GetUIValueRange(DNA_UI_BEARD_STYLE,facial_hair_styles_list.len) if((0 < beard) && (beard <= facial_hair_styles_list.len)) - H.f_style = facial_hair_styles_list[beard] + head_organ.f_style = facial_hair_styles_list[beard] //Head Accessories var/headacc = dna.GetUIValueRange(DNA_UI_HACC_STYLE,head_accessory_styles_list.len) if((0 < headacc) && (headacc <= head_accessory_styles_list.len)) - H.ha_style = head_accessory_styles_list[headacc] + head_organ.ha_style = head_accessory_styles_list[headacc] //Markings var/marks = dna.GetUIValueRange(DNA_UI_MARK_STYLE,marking_styles_list.len) diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index 2aca5878f83..eb33cef7ccf 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -144,8 +144,8 @@ /datum/dna/gene/basic/tk name="Telekenesis" - activation_messages=list("You feel smarter.") - deactivation_messages=("You feel dumber.") + activation_messages = list("You feel smarter.") + deactivation_messages = list("You feel dumber.") mutation=TK activation_prob=10 diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 8a854c7980d..13f334c010b 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -37,61 +37,7 @@ to_chat(usr, "\red You can't change your appearance right now!") return var/mob/living/carbon/human/M=usr - - var/new_facial = input("Please select facial hair color.", "Character Generation",rgb(M.r_facial,M.g_facial,M.b_facial)) as null|color - if(new_facial) - M.r_facial = hex2num(copytext(new_facial, 2, 4)) - M.g_facial = hex2num(copytext(new_facial, 4, 6)) - M.b_facial = hex2num(copytext(new_facial, 6, 8)) - - var/new_hair = input("Please select hair color.", "Character Generation",rgb(M.r_hair,M.g_hair,M.b_hair)) as null|color - if(new_facial) - M.r_hair = hex2num(copytext(new_hair, 2, 4)) - M.g_hair = hex2num(copytext(new_hair, 4, 6)) - M.b_hair = hex2num(copytext(new_hair, 6, 8)) - - var/new_eyes = input("Please select eye color.", "Character Generation",rgb(M.r_eyes,M.g_eyes,M.b_eyes)) as null|color - if(new_eyes) - M.r_eyes = hex2num(copytext(new_eyes, 2, 4)) - M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) - M.b_eyes = hex2num(copytext(new_eyes, 6, 8)) - - var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[35-M.s_tone]") as null|text - - if (!new_tone) - new_tone = 35 - M.s_tone = max(min(round(text2num(new_tone)), 220), 1) - M.s_tone = -M.s_tone + 35 - - // hair - var/list/all_hairs = subtypesof(/datum/sprite_accessory/hair) - var/list/hairs = list() - - // loop through potential hairs - for(var/x in all_hairs) - var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x - hairs.Add(H.name) // add hair name to hairs - qdel(H) // delete the hair after it's all done - - var/new_style = input("Please select hair style", "Character Generation",M.h_style) as null|anything in hairs - - // if new style selected (not cancel) - if (new_style) - M.h_style = new_style - - // facial hair - var/list/all_fhairs = subtypesof(/datum/sprite_accessory/facial_hair) - var/list/fhairs = list() - - for(var/x in all_fhairs) - var/datum/sprite_accessory/facial_hair/H = new x - fhairs.Add(H.name) - qdel(H) - - new_style = input("Please select facial style", "Character Generation",M.f_style) as null|anything in fhairs - - if(new_style) - M.f_style = new_style + var/obj/item/organ/external/head/head_organ = M.get_organ("head") var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") if (new_gender) @@ -99,8 +45,93 @@ M.change_gender(MALE) else M.change_gender(FEMALE) + + var/new_eyes = input("Please select eye color.", "Character Generation", rgb(M.r_eyes,M.g_eyes,M.b_eyes)) as null|color + if(new_eyes) + M.r_eyes = hex2num(copytext(new_eyes, 2, 4)) + M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) + M.b_eyes = hex2num(copytext(new_eyes, 6, 8)) + M.change_eye_color(M.r_eyes, M.g_eyes, M.b_eyes) + + // hair + var/list/valid_hairstyles = M.generate_valid_hairstyles() + var/new_style = input("Please select hair style", "Character Generation", head_organ.h_style) as null|anything in valid_hairstyles + + // if new style selected (not cancel) + if (new_style) + head_organ.h_style = new_style + + var/new_hair = input("Please select hair color.", "Character Generation", rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair)) as null|color + if(new_hair) + head_organ.r_hair = hex2num(copytext(new_hair, 2, 4)) + head_organ.g_hair = hex2num(copytext(new_hair, 4, 6)) + head_organ.b_hair = hex2num(copytext(new_hair, 6, 8)) + + // facial hair + var/list/valid_facial_hairstyles = M.generate_valid_facial_hairstyles() + new_style = input("Please select facial style", "Character Generation", head_organ.f_style) as null|anything in valid_facial_hairstyles + + if(new_style) + head_organ.f_style = new_style + + var/new_facial = input("Please select facial hair color.", "Character Generation", rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial)) as null|color + if(new_facial) + head_organ.r_facial = hex2num(copytext(new_facial, 2, 4)) + head_organ.g_facial = hex2num(copytext(new_facial, 4, 6)) + head_organ.b_facial = hex2num(copytext(new_facial, 6, 8)) + + //Head accessory. + if(head_organ.species.bodyflags & HAS_HEAD_ACCESSORY) + var/list/valid_head_accessories = M.generate_valid_head_accessories() + var/new_head_accessory = input("Please select head accessory style", "Character Generation", head_organ.ha_style) as null|anything in valid_head_accessories + if(new_head_accessory) + head_organ.ha_style = new_head_accessory + + var/new_head_accessory_colour = input("Please select head accessory colour.", "Character Generation", rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc)) as null|color + if(new_head_accessory_colour) + head_organ.r_headacc = hex2num(copytext(new_head_accessory_colour, 2, 4)) + head_organ.g_headacc = hex2num(copytext(new_head_accessory_colour, 4, 6)) + head_organ.b_headacc = hex2num(copytext(new_head_accessory_colour, 6, 8)) + + //Body markings. + if(M.species.bodyflags & HAS_MARKINGS) + var/list/valid_markings = M.generate_valid_markings() + var/new_marking = input("Please select marking style", "Character Generation", M.m_style) as null|anything in valid_markings + if(new_marking) + M.m_style = new_marking + + var/new_marking_colour = input("Please select marking colour.", "Character Generation", rgb(M.r_markings, M.g_markings, M.b_markings)) as null|color + if(new_marking_colour) + M.r_markings = hex2num(copytext(new_marking_colour, 2, 4)) + M.g_markings = hex2num(copytext(new_marking_colour, 4, 6)) + M.b_markings = hex2num(copytext(new_marking_colour, 6, 8)) + + //Body accessory. + if(M.species.tail && M.species.bodyflags & HAS_TAIL) + var/list/valid_body_accessories = M.generate_valid_body_accessories() + if(valid_body_accessories.len > 1) //By default valid_body_accessories will always have at the very least a 'none' entry populating the list, even if the user's species is not present in any of the list items. + var/new_body_accessory = input("Please select body accessory style", "Character Generation", M.body_accessory) as null|anything in valid_body_accessories + if(new_body_accessory) + M.body_accessory = body_accessory_by_name[new_body_accessory] + + //Skin tone. + if(M.species.bodyflags & HAS_SKIN_TONE) + var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[M.s_tone]") as null|text + if (!new_tone) + new_tone = 35 + M.s_tone = 35 - max(min(round(text2num(new_tone)), 220), 1) + + //Skin colour. + if(M.species.bodyflags & HAS_SKIN_COLOR) + var/new_body_colour = input("Please select body colour.", "Character Generation", rgb(M.r_skin, M.g_skin, M.b_skin)) as null|color + if(new_body_colour) + M.r_skin = hex2num(copytext(new_body_colour, 2, 4)) + M.g_skin = hex2num(copytext(new_body_colour, 4, 6)) + M.b_skin = hex2num(copytext(new_body_colour, 6, 8)) + + M.force_update_limbs() M.regenerate_icons() - M.check_dna() + M.update_dna() M.visible_message("\blue \The [src] morphs and changes [M.get_visible_gender() == MALE ? "his" : M.get_visible_gender() == FEMALE ? "her" : "their"] appearance!", "\blue You change your appearance!", "\red Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index a35505470fa..229b35660a3 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -68,6 +68,7 @@ ..() /mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(var/mob/living/carbon/human/H) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") is_zombie = 1 if(H.wear_suit) var/obj/item/clothing/suit/armor/A = H.wear_suit @@ -82,7 +83,7 @@ icon = H.icon speak_emote = list("groans") icon_state = "zombie2_s" - H.h_style = null + head_organ.h_style = null H.update_hair() human_overlays = H.overlays update_icons() diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 28ebdeae677..952b43d5f37 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -94,6 +94,7 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) var/mob/living/carbon/human/vox = newraider.current + var/obj/item/organ/external/head/head_organ = vox.get_organ("head") vox.real_name = capitalize(newname) vox.name = vox.real_name @@ -105,8 +106,8 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' vox.add_language("Vox-pidgin") vox.add_language("Galactic Common") vox.add_language("Tradeband") - vox.h_style = "Short Vox Quills" - vox.f_style = "Shaved" + head_organ.h_style = "Short Vox Quills" + head_organ.f_style = "Shaved" for(var/obj/item/organ/external/limb in vox.organs) limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index 44b37ed22e5..8adf07a60ba 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -43,12 +43,28 @@ experimentUI(user) +/obj/machinery/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H) + var/icon/I = icon(H.stand_icon) + + var/icon/splat = icon(H.species.damage_overlays, "30") + splat.Blend(icon(H.species.damage_mask, "torso"), ICON_MULTIPLY) + splat.Blend(H.species.blood_color, ICON_MULTIPLY) + I.Blend(splat, ICON_OVERLAY) + + return I + /obj/machinery/abductor/experiment/proc/experimentUI(mob/user) var/dat dat += "

Experiment

" if(occupant) - dat += "
" - dat += "" + var/icon/H = icon(dissection_icon(occupant), dir = SOUTH) + if(H) + user << browse_rsc(H, "dissection_img.png") + dat += "
" + dat += "" + dat += "" + else + dat += "ERR: Unable to retrieve image data for occupant." dat += "Probe
" dat += "Dissect
" dat += "Analyze
" diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 9e25a50a811..1a0d7770a1a 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -80,6 +80,7 @@ density = 0 pass_flags = PASSTABLE ventcrawler = 2 + 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) var/talk_inside_host = 0 // So that borers don't accidentally give themselves away on a botched message var/used_dominate diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index ccd498bb97f..8c4a2685e04 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -97,8 +97,7 @@ /mob/living/simple_animal/hostile/swarmer/emp_act() if(health > 1) - health = 1 - return + adjustHealth(health-1) else death() @@ -156,30 +155,17 @@ S.DisIntegrate(src) toggle_cam(S, 0) -/obj/machinery/particle_accelerator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) +/obj/structure/particle_accelerator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") -/obj/structure/particle_accelerator/fuel_chamber/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) +/obj/machinery/particle_accelerator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) // Since the console is still parented to this to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") -/obj/structure/particle_accelerator/particle_emitter/center/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) - to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") - -/obj/structure/particle_accelerator/particle_emitter/left/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) - to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") - -/obj/structure/particle_accelerator/particle_emitter/right/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) - to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") - -/obj/structure/particle_accelerator/particle_emitter/end_cap/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) - to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") - -/obj/structure/particle_accelerator/particle_emitter/power_box/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) - to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") - - /obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) - S.DisIntegrate(src) + if(!active) + S.DisIntegrate(src) + return + to_chat(S, "An inhospitable area may be created as a result of destroying this object. Aborting.") /obj/machinery/gravity_generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) S.DisIntegrate(src) @@ -234,7 +220,7 @@ /turf/simulated/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) for(var/turf/T in range(1, src)) - if(istype(T, /turf/space) || istype(T.loc, /area/space)) + if(istype(T, /turf/space) || istype(T.loc, /area/space) || istype(T, /turf/simulated/floor/plating/airless)) to_chat(S, "Destroying this object has the potential to cause a hull breach. Aborting.") return ..() @@ -515,7 +501,7 @@ return to_chat(src, "Attempting to repair damage to our body, stand by...") if(do_mob(src, src, 100)) - adjustBruteLoss(-100) + adjustHealth(-100) to_chat(src, "We successfully repaired ourselves.") /mob/living/simple_animal/hostile/swarmer/proc/ToggleLight() diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index 2108e1c3147..dbb56523e4e 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -86,7 +86,7 @@ hud_used.guardianhealthdisplay.maptext = "
[resulthealth]%
" -/mob/living/simple_animal/hostile/guardian/adjustBruteLoss(amount) //The spirit is invincible, but passes on damage to the summoner +/mob/living/simple_animal/hostile/guardian/adjustHealth(amount) //The spirit is invincible, but passes on damage to the summoner var/damage = amount * damage_transfer if (summoner) if(loc == summoner) diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index dbbf561b609..780abb8854f 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -162,7 +162,7 @@ if(L.stat == DEAD) if(do_after(src, 30, target = L)) if(eat(L)) - heal_overall_damage(50,50) + adjustHealth(-50) return else if(istype(target,/obj/item)) // Eat items just to be annoying var/obj/item/I = target diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index 0e048b85df0..7fddc8c3c56 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -81,7 +81,7 @@ /mob/living/simple_animal/revenant/narsie_act() return //most humans will now be either bones or harvesters, but we're still un-alive. -/mob/living/simple_animal/revenant/adjustBruteLoss(amount) +/mob/living/simple_animal/revenant/adjustHealth(amount) if(!revealed) return essence = max(0, essence-amount) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index e10dce617fa..0268133a5d1 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -133,6 +133,8 @@ proc/issyndicate(mob/living/M as mob) /datum/game_mode/proc/create_syndicate(var/datum/mind/synd_mind) // So we don't have inferior species as ops - randomize a human var/mob/living/carbon/human/M = synd_mind.current + var/obj/item/organ/external/head/head_organ = M.get_organ("head") + M.set_species("Human",1) M.dna.ready_dna(M) // Quadriplegic Nuke Ops won't be participating in the paralympics @@ -149,18 +151,18 @@ proc/issyndicate(mob/living/M as mob) if(prob(5)) facial_hair_style = pick(facial_hair_styles_list) - M.r_facial = hex2num(copytext(hair_c, 2, 4)) - M.g_facial = hex2num(copytext(hair_c, 4, 6)) - M.b_facial = hex2num(copytext(hair_c, 6, 8)) - M.r_hair = hex2num(copytext(hair_c, 2, 4)) - M.g_hair = hex2num(copytext(hair_c, 4, 6)) - M.b_hair = hex2num(copytext(hair_c, 6, 8)) + head_organ.r_facial = hex2num(copytext(hair_c, 2, 4)) + head_organ.g_facial = hex2num(copytext(hair_c, 4, 6)) + head_organ.b_facial = hex2num(copytext(hair_c, 6, 8)) + head_organ.r_hair = hex2num(copytext(hair_c, 2, 4)) + head_organ.g_hair = hex2num(copytext(hair_c, 4, 6)) + head_organ.b_hair = hex2num(copytext(hair_c, 6, 8)) M.r_eyes = hex2num(copytext(eye_c, 2, 4)) M.g_eyes = hex2num(copytext(eye_c, 4, 6)) M.b_eyes = hex2num(copytext(eye_c, 6, 8)) M.s_tone = skin_tone - M.h_style = hair_style - M.f_style = facial_hair_style + head_organ.h_style = hair_style + head_organ.f_style = facial_hair_style M.body_accessory = null /datum/game_mode/proc/prepare_syndicate_leader(var/datum/mind/synd_mind, var/nuke_code) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 9544d54560c..25b3727ec3a 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -8,12 +8,13 @@ var/list/potential_theft_objectives=subtypesof(/datum/theft_objective) \ - /datum/theft_objective/number/special \ - /datum/theft_objective/number/coins -datum/objective +/datum/objective var/datum/mind/owner = null //Who owns the objective. var/explanation_text = "Nothing" //What that person is supposed to do. var/datum/mind/target = null //If they are focused on a particular person. var/target_amount = 0 //If they are focused on a particular number. Steal objectives have their own counter. var/completed = 0 //currently only used for custom objectives. + var/martyr_compatible = 0 //If the objective is compatible with martyr objective, i.e. if you can still do it while dead. New(var/text) all_objectives |= src @@ -53,7 +54,9 @@ datum/objective target = pick(possible_targets) -datum/objective/assassinate +/datum/objective/assassinate + martyr_compatible = 1 + find_target() ..() if(target && target.current) @@ -81,7 +84,9 @@ datum/objective/assassinate -datum/objective/mutiny +/datum/objective/mutiny + martyr_compatible = 1 + find_target() ..() if(target && target.current) @@ -109,7 +114,7 @@ datum/objective/mutiny return 0 return 1 -datum/objective/mutiny/rp +/datum/objective/mutiny/rp find_target() ..() if(target && target.current) @@ -144,97 +149,9 @@ datum/objective/mutiny/rp return 0 return rval -datum/objective/anti_revolution/execute - find_target() - ..() - if(target && target.current) - explanation_text = "[target.current.real_name], the [target.assigned_role] has extracted confidential information above their clearance. Execute \him[target.current]." - else - explanation_text = "Free Objective" - return target +/datum/objective/maroon + martyr_compatible = 1 - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "[target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] has extracted confidential information above their clearance. Execute \him[target.current]." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(target && target.current) - if(target.current.stat == DEAD || !ishuman(target.current)) - return 1 - return 0 - return 1 - -datum/objective/anti_revolution/brig - var/already_completed = 0 - - find_target() - ..() - if(target && target.current) - explanation_text = "Brig [target.current.real_name], the [target.assigned_role] for 20 minutes to set an example." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Brig [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] for 20 minutes to set an example." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(already_completed) - return 1 - - if(target && target.current) - if(target.current.stat == DEAD) - return 0 - if(target.is_brigged(10 * 60 * 10)) - already_completed = 1 - return 1 - return 0 - return 0 - -datum/objective/anti_revolution/demote - find_target() - ..() - if(target && target.current) - explanation_text = "[target.current.real_name], the [target.assigned_role] has been classified as harmful to Nanotrasen's goals. Demote \him[target.current] to assistant." - else - explanation_text = "Free Objective" - return target - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "[target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] has been classified as harmful to Nanotrasen's goals. Demote \him[target.current] to assistant." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(target && target.current && istype(target,/mob/living/carbon/human)) - var/obj/item/weapon/card/id/I = target.current:wear_id - if(istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/P = I - I = P.id - - if(!istype(I)) return 1 - - if(I.assignment == "Civilian") - return 1 - else - return 0 - return 1 - -datum/objective/maroon find_target() ..() if(target && target.current) @@ -259,7 +176,9 @@ datum/objective/maroon return 0 return 1 -datum/objective/debrain//I want braaaainssss +/datum/objective/debrain //I want braaaainssss + martyr_compatible = 0 + find_target() ..() if(target && target.current) @@ -292,7 +211,9 @@ datum/objective/debrain//I want braaaainssss return 0 -datum/objective/protect//The opposite of killing a dude. +/datum/objective/protect //The opposite of killing a dude. + martyr_compatible = 1 + find_target() ..() if(target && target.current) @@ -327,7 +248,8 @@ datum/objective/protect//The opposite of killing a dude. return 0 -datum/objective/hijack +/datum/objective/hijack + martyr_compatible = 0 //Technically you won't get both anyway. explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive." check_completion() @@ -358,6 +280,7 @@ datum/objective/hijack /datum/objective/hijackclone explanation_text = "Hijack the emergency shuttle by ensuring only you (or your copies) escape." + martyr_compatible = 0 check_completion() if(!owner.current) @@ -386,8 +309,9 @@ datum/objective/hijack return 1 return 0 -datum/objective/block +/datum/objective/block explanation_text = "Do not allow any organic lifeforms to escape on the shuttle alive." + martyr_compatible = 1 check_completion() if(!istype(owner.current, /mob/living/silicon)) @@ -410,9 +334,7 @@ datum/objective/block return 1 - - -datum/objective/escape +/datum/objective/escape explanation_text = "Escape on the shuttle or an escape pod alive and free." var/escape_areas = list(/area/shuttle/escape, /area/shuttle/escape_pod1/centcom, @@ -447,7 +369,7 @@ datum/objective/escape return 0 -datum/objective/escape/escape_with_identity +/datum/objective/escape/escape_with_identity var/target_real_name // Has to be stored because the target's real_name can change over the course of the round find_target() @@ -477,7 +399,7 @@ datum/objective/escape/escape_with_identity return 1 return 0 -datum/objective/die +/datum/objective/die explanation_text = "Die a glorious death." check_completion() @@ -489,7 +411,7 @@ datum/objective/die -datum/objective/survive +/datum/objective/survive explanation_text = "Stay alive until the end." check_completion() @@ -499,98 +421,15 @@ datum/objective/survive return 0 return 1 -// Similar to the anti-rev objective, but for traitors -datum/objective/brig - var/already_completed = 0 - - find_target() - ..() - if(target && target.current) - explanation_text = "Have [target.current.real_name], the [target.assigned_role] brigged for 10 minutes." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Have [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] brigged for 10 minutes." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(already_completed) - return 1 - - if(target && target.current) - if(target.current.stat == DEAD) - return 0 - // Make the actual required time a bit shorter than the official time - if(target.is_brigged(10 * 60 * 5)) - already_completed = 1 - return 1 - return 0 - return 0 - -// Harm a crew member, making an example of them -datum/objective/harm - var/already_completed = 0 - - find_target() - ..() - if(target && target.current) - explanation_text = "Make an example of [target.current.real_name], the [target.assigned_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Make an example of [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(already_completed) - return 1 - - if(target && target.current && istype(target.current, /mob/living/carbon/human)) - if(target.current.stat == DEAD) - return 0 - - var/mob/living/carbon/human/H = target.current - for(var/obj/item/organ/external/E in H.organs) - if(E.status & ORGAN_BROKEN) - return 1 - for(var/limb_tag in H.species.has_limbs) //todo check prefs for robotic limbs and amputations. - var/list/organ_data = H.species.has_limbs[limb_tag] - var/limb_type = organ_data["path"] - var/found - for(var/obj/item/organ/external/E in H.organs) - if(limb_type == E.type) - found = 1 - break - if(!found) - return 1 - - var/obj/item/organ/external/head/head = H.get_organ("head") - if(head.disfigured) - return 1 - return 0 - - -datum/objective/nuclear +/datum/objective/nuclear explanation_text = "Destroy the station with a nuclear device." + martyr_compatible = 1 -datum/objective/steal +/datum/objective/steal var/datum/theft_objective/steal_target + martyr_compatible = 0 find_target(var/special_only=0) var/loop=50 @@ -638,7 +477,8 @@ datum/objective/steal if(!steal_target) return 1 // Free Objective return steal_target.check_completion(owner) -datum/objective/steal/exchange +/datum/objective/steal/exchange + martyr_compatible = 0 proc/set_faction(var/faction,var/otheragent) target = otheragent @@ -650,7 +490,7 @@ datum/objective/steal/exchange explanation_text = "Acquire [targetinfo.name] held by [target.current.real_name], the [target.assigned_role] and syndicate agent" steal_target = targetinfo -datum/objective/steal/exchange/backstab +/datum/objective/steal/exchange/backstab set_faction(var/faction) var/datum/theft_objective/unique/targetinfo @@ -661,7 +501,7 @@ datum/objective/steal/exchange/backstab explanation_text = "Do not give up or lose [targetinfo.name]." steal_target = targetinfo -datum/objective/download +/datum/objective/download proc/gen_amount_goal() target_amount = rand(10,20) explanation_text = "Download [target_amount] research levels." @@ -673,7 +513,7 @@ datum/objective/download -datum/objective/capture +/datum/objective/capture proc/gen_amount_goal() target_amount = rand(5,10) explanation_text = "Accumulate [target_amount] capture points." @@ -686,7 +526,7 @@ datum/objective/capture -datum/objective/absorb +/datum/objective/absorb proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6) target_amount = rand (lowbound,highbound) if (ticker) @@ -714,8 +554,10 @@ datum/objective/absorb else return 0 -datum/objective/destroy +/datum/objective/destroy + martyr_compatible = 1 var/target_real_name + find_target() var/list/possible_targets = active_ais(1) var/mob/living/silicon/ai/target_ai = pick(possible_targets) @@ -734,71 +576,7 @@ datum/objective/destroy return 0 return 1 -/* Isn't suited for global objectives -/*---------CULTIST----------*/ - - eldergod - explanation_text = "Summon Nar-Sie via the use of an appropriate rune. It will only work if nine cultists stand on and around it." - - check_completion() - if(!eldergod) //global var, defined in rune4.dm - return 1 - return 0 - - survivecult - var/num_cult - var/cult_needed = 4 + round((num_players_started() / 10)) - - explanation_text = "Our knowledge must live on. Make sure at least [cult_needed] acolytes escape on the shuttle to spread their work on an another station." - - check_completion() - if(!emergency_shuttle.returned()) - return 0 - - var/cultists_escaped = 0 - - var/area/shuttle/escape/centcom/C = /area/shuttle/escape/centcom - for(var/turf/T in get_area_turfs(C.type)) - for(var/mob/living/carbon/H in T) - if(iscultist(H)) - cultists_escaped++ - - if(cultists_escaped >= cult_needed) - return 1 - - return 0 - - sacrifice //stolen from traitor target objective - - proc/find_target() //I don't know how to make it work with the rune otherwise, so I'll do it via a global var, sacrifice_target, defined in rune15.dm - var/datum/game_mode/cult/C = ticker.mode - var/list/possible_targets = C.get_unconvertables() - - if(!possible_targets.len) - for(var/mob/living/carbon/human/player in player_list) - if(player.mind && !(player.mind in cult)) - possible_targets += player.mind - - if(possible_targets.len > 0) - sacrifice_target = pick(possible_targets) - - if(sacrifice_target && sacrifice_target.current) - explanation_text = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (hell join blood) and three acolytes to do so." - else - explanation_text = "Free Objective" - - return sacrifice_target - - check_completion() //again, calling on a global list defined in rune15.dm - if(sacrifice_target in sacrificed) - return 1 - else - return 0 - -/*-------ENDOF CULTIST------*/ -*/ - -datum/objective/blood +/datum/objective/blood proc/gen_amount_goal(low = 150, high = 400) target_amount = rand(low,high) target_amount = round(round(target_amount/5)*5) @@ -812,7 +590,7 @@ datum/objective/blood return 0 // /vg/; Vox Inviolate for humans :V -datum/objective/minimize_casualties +/datum/objective/minimize_casualties explanation_text = "Minimise casualties." check_completion() if(owner.kills.len>5) return 0 @@ -820,11 +598,11 @@ datum/objective/minimize_casualties //Vox heist objectives. -datum/objective/heist +/datum/objective/heist proc/choose_target() return -datum/objective/heist/kidnap +/datum/objective/heist/kidnap choose_target() var/list/roles = list("Chief Engineer","Research Director","Roboticist","Chemist","Station Engineer") var/list/possible_targets = list() @@ -866,7 +644,7 @@ datum/objective/heist/kidnap else return 0 -datum/objective/heist/loot +/datum/objective/heist/loot choose_target() var/loot = "an object" switch(rand(1,8)) @@ -937,7 +715,7 @@ datum/objective/heist/loot return 0 -datum/objective/heist/salvage +/datum/objective/heist/salvage choose_target() switch(rand(1,8)) if(1) @@ -1009,7 +787,7 @@ datum/objective/heist/salvage return 0 -datum/objective/heist/inviolate_crew +/datum/objective/heist/inviolate_crew explanation_text = "Do not leave any Vox behind, alive or dead." check_completion() @@ -1022,7 +800,7 @@ datum/objective/heist/inviolate_crew //Would be nice to use vox-specific kills but is currently not feasible. var/global/vox_kills = 0 //Used to check the Inviolate. -datum/objective/heist/inviolate_death +/datum/objective/heist/inviolate_death explanation_text = "Follow the Inviolate. Minimise death and loss of resources." check_completion() if(vox_kills > MAX_VOX_KILLS) return 0 diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index 7c8100edbc5..24129a6d49f 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -301,7 +301,7 @@ Made by Xhuis blood_color = "#555555" flesh_color = "#222222" - flags = NO_BLOOD | NO_BREATHE | RADIMMUNE + flags = NO_BLOOD | NO_BREATHE | RADIMMUNE | NOGUNS //Can't use guns due to muzzle flash burn_mod = 1.5 //1.5x burn damage, 2x is excessive hot_env_multiplier = 1.5 diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index c0d0edf89e3..c7fcd59dfe4 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -74,101 +74,107 @@ ..() -/datum/game_mode/proc/forge_traitor_objectives(var/datum/mind/traitor) +/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor) if(istype(traitor.current, /mob/living/silicon)) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective + var/objective_count = 0 + + if(prob(30)) + var/special_pick = rand(1,2) + switch(special_pick) + if(1) + var/datum/objective/block/block_objective = new + block_objective.owner = traitor + traitor.objectives += block_objective + objective_count++ + if(2) //Protect and strand a target + var/datum/objective/protect/yandere_one = new + yandere_one.owner = traitor + traitor.objectives += yandere_one + yandere_one.find_target() + objective_count++ + var/datum/objective/maroon/yandere_two = new + yandere_two.owner = traitor + yandere_two.target = yandere_one.target + traitor.objectives += yandere_two + objective_count++ + + for(var/i = objective_count, i < config.traitor_objectives_amount, i++) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective var/datum/objective/survive/survive_objective = new survive_objective.owner = traitor traitor.objectives += survive_objective - if(prob(10)) - var/datum/objective/block/block_objective = new - block_objective.owner = traitor - traitor.objectives += block_objective - else - if(!exchange_blue && traitors.len >= 5 && name != "AutoTraitor") //Set up an exchange if there are enough traitors, turned off during autotraitor temporarily due to bugs. + var/is_hijacker = prob(10) + var/martyr_chance = prob(20) + var/objective_count = is_hijacker //Hijacking counts towards number of objectives + if(!exchange_blue && traitors.len >= 8) //Set up an exchange if there are enough traitors if(!exchange_red) exchange_red = traitor else exchange_blue = traitor assign_exchange_role(exchange_red) assign_exchange_role(exchange_blue) - else - var/list/active_ais = active_ais() - if(active_ais.len && prob(4)) // Leaving this at a flat chance for now, problems with the num_players() proc due to latejoin antags. - var/datum/objective/destroy/destroy_objective = new - destroy_objective.owner = traitor - destroy_objective.find_target() - traitor.objectives += destroy_objective - else - switch(rand(1,100)) - if(1 to 30) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - if(31 to 40) - var/datum/objective/debrain/debrain_objective = new - debrain_objective.owner = traitor - debrain_objective.find_target() - traitor.objectives += debrain_objective - if(41 to 50) - var/datum/objective/protect/protect_objective = new - protect_objective.owner = traitor - protect_objective.find_target_with_special_role(null,0) - if (!protect_objective.target) - protect_objective.find_target() //We could not find any traitors, protect somebody - traitor.objectives += protect_objective - if(51 to 61) - var/datum/objective/harm/harm_objective = new - harm_objective.owner = traitor - harm_objective.find_target() - traitor.objectives += harm_objective - else - var/datum/objective/steal/steal_objective = new - steal_objective.owner = traitor - steal_objective.find_target() - traitor.objectives += steal_objective - switch(rand(1,100)) - if(1 to 30) // Die glorious death - if (!(locate(/datum/objective/die) in traitor.objectives) && !(locate(/datum/objective/steal) in traitor.objectives) && !(locate(/datum/objective/steal/exchange) in traitor.objectives) && !(locate(/datum/objective/steal/exchange/backstab) in traitor.objectives)) - var/datum/objective/die/die_objective = new - die_objective.owner = traitor - traitor.objectives += die_objective + objective_count += 1 //Exchange counts towards number of objectives + var/list/active_ais = active_ais() + for(var/i = objective_count, i < config.traitor_objectives_amount, i++) + if(prob(50)) + if(active_ais.len && prob(100/player_list.len)) + var/datum/objective/destroy/destroy_objective = new + destroy_objective.owner = traitor + destroy_objective.find_target() + traitor.objectives += destroy_objective + else if(prob(5)) + var/datum/objective/debrain/debrain_objective = new + debrain_objective.owner = traitor + debrain_objective.find_target() + traitor.objectives += debrain_objective + else if(prob(30)) + var/datum/objective/maroon/maroon_objective = new + maroon_objective.owner = traitor + maroon_objective.find_target() + traitor.objectives += maroon_objective else - if(prob(85)) - if (!(locate(/datum/objective/escape) in traitor.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - else - if(prob(50)) - if (!(locate(/datum/objective/hijack) in traitor.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = traitor - traitor.objectives += hijack_objective - else - if (!(locate(/datum/objective/minimize_casualties) in traitor.objectives)) - var/datum/objective/minimize_casualties/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - if(31 to 85) - if (!(locate(/datum/objective/escape) in traitor.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective else - if (!(locate(/datum/objective/hijack) in traitor.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = traitor - traitor.objectives += hijack_objective + var/datum/objective/steal/steal_objective = new + steal_objective.owner = traitor + steal_objective.find_target() + traitor.objectives += steal_objective - return + if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount + if (!(locate(/datum/objective/hijack) in traitor.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = traitor + traitor.objectives += hijack_objective + return + + + var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. + for(var/datum/objective/O in traitor.objectives) + if(!O.martyr_compatible) + martyr_compatibility = 0 + break + + if(martyr_compatibility && martyr_chance) + var/datum/objective/die/martyr_objective = new + martyr_objective.owner = traitor + traitor.objectives += martyr_objective + return + + else + if(!(locate(/datum/objective/escape) in traitor.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = traitor + traitor.objectives += escape_objective + return /datum/game_mode/proc/greet_traitor(var/datum/mind/traitor) diff --git a/code/game/gamemodes/vampire/traitor_vamp.dm b/code/game/gamemodes/vampire/traitor_vamp.dm index e94fbfeb199..9d4cb42b545 100644 --- a/code/game/gamemodes/vampire/traitor_vamp.dm +++ b/code/game/gamemodes/vampire/traitor_vamp.dm @@ -7,6 +7,7 @@ required_enemies = 1 // how many of each type are required recommended_enemies = 3 var/protected_species_vampire = list("Machine") + var/special_job_protection = list("Chaplain") //this must exist or else Chaplain can role for Vampire. That said, we don't want to rule out him getting traitor, either /datum/game_mode/traitor/vampire/announce() to_chat(world, "The current game mode is - Traitor+Vampire!") @@ -22,6 +23,8 @@ for(var/mob/new_player/player in player_list) if((player.mind in possible_vampires) && (player.client.prefs.species in protected_species_vampire)) possible_vampires -= player.mind + if((player.mind in possible_vampires) && (player.mind.assigned_role in special_job_protection)) + possible_vampires -= player.mind if(possible_vampires.len > 0) var/datum/mind/vampire = pick(possible_vampires) diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index a7e470ef056..bc7ba9276f5 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -192,8 +192,8 @@ /obj/effect/proc_holder/spell/vampire/targetted/disease name = "Diseased Touch (100)" - desc = "Touches your victim with infected blood giving them appendicitis, which will, left untreated, cause a slow death by poison." - gain_desc = "You have gained the Diseased Touch ability which causes those you touch to die unless treated medically." + desc = "Touches your victim with infected blood giving them Grave Fever, which will, left untreated, causes toxic building and frequent collapsing." + gain_desc = "You have gained the Diseased Touch ability which causes those you touch to become weak unless treated medically." action_icon_state = "vampire_disease" required_blood = 100 @@ -204,7 +204,7 @@ if(!affects(target)) to_chat(usr, "They seem to be unaffected.") continue - var/datum/disease/D = new /datum/disease/appendicitis //someone should probably make a better virus for this + var/datum/disease/D = new /datum/disease/vampire target.ForceContractDisease(D) /obj/effect/proc_holder/spell/vampire/mob_aoe/glare diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm index d371af38ea5..32feaede2e1 100644 --- a/code/game/gamemodes/wizard/raginmages.dm +++ b/code/game/gamemodes/wizard/raginmages.dm @@ -118,8 +118,6 @@ if(making_mage || shuttle_master.emergency.mode >= SHUTTLE_ESCAPE) return 0 - if(mages_made >= max_mages) - return 0 making_mage = 1 var/list/candidates = list() var/mob/dead/observer/harry = null diff --git a/code/game/jobs/job/support_chaplain.dm b/code/game/jobs/job/support_chaplain.dm index 29a0375b849..0df72eaf9d5 100644 --- a/code/game/jobs/job/support_chaplain.dm +++ b/code/game/jobs/job/support_chaplain.dm @@ -79,7 +79,7 @@ while(!accepted) if(!B) break // prevents possible runtime errors - new_book_style = input(H,"Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "the bible melts", "Necronomicon") + new_book_style = input(H,"Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "the bible melts", "Necronomicon", "Greentext") switch(new_book_style) if("Koran") B.icon_state = "koran" @@ -129,6 +129,9 @@ if("Necronomicon") B.icon_state = "necronomicon" B.item_state = "necronomicon" + if("Greentext") + B.icon_state = "greentext" + B.item_state = "greentext" else // if christian bible, revert to default B.icon_state = "bible" diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 6b13dbe95e3..4c820d26857 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -698,6 +698,17 @@ obj/item/weapon/circuitboard/rdserver /obj/item/weapon/stock_parts/capacitor = 2, /obj/item/weapon/stock_parts/console_screen = 1) +/obj/item/weapon/circuitboard/teleporter_perma + name = "circuit board (Permanent Teleporter)" + build_path = /obj/machinery/teleport/perma + board_type = "machine" + origin_tech = "programming=3;engineering=5;bluespace=5;materials=4" + frame_desc = "Requires 3 Bluespace Crystals and 1 Matter Bin." + req_components = list( + /obj/item/weapon/ore/bluespace_crystal = 3, + /obj/item/weapon/stock_parts/matter_bin = 1) + var/target + /obj/item/weapon/circuitboard/telesci_pad name = "Circuit board (Telepad)" build_path = /obj/machinery/telepad diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index dedcd52164a..68ff1bf64c1 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -489,6 +489,7 @@ to_chat(M, "If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.") occupant = M + name = "[name] ([occupant.name])" time_entered = world.time if(findtext("[M.key]","@",1,2)) @@ -581,6 +582,7 @@ to_chat(L, "[on_enter_occupant_message]") to_chat(L, "If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.") occupant = L + name = "[name] ([occupant.name])" time_entered = world.time if(findtext("[L.key]","@",1,2)) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 8029b136cee..095cd23498a 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -800,6 +800,7 @@ About the new airlock wires panel: else return else if(istype(C, /obj/item/weapon/screwdriver)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 25, 1) src.p_open = !( src.p_open ) src.update_icon() else if(istype(C, /obj/item/weapon/wirecutters)) @@ -1067,4 +1068,4 @@ About the new airlock wires panel: src.unlock() src.open() src.lock() - return \ No newline at end of file + return diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 15b8b621b0c..5d6aa95b56f 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -621,7 +621,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept //#### Sending the signal to all subspace receivers ####// for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) + spawn(0) + R.receive_signal(signal) if(do_sleep) sleep(rand(10,25)) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 6dd9954046b..3052d5a28ce 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -319,17 +319,18 @@ /obj/machinery/teleport/hub/Bumped(M as mob|obj) if(z == ZLEVEL_CENTCOMM) to_chat(M, "You can't use this here.") + return if(power_station && power_station.engaged && !panel_open) //--FalseIncarnate //Prevents AI cores from using the teleporter, prints out failure messages for clarity if(istype(M, /mob/living/silicon/ai) || istype(M, /obj/structure/AIcore)) - visible_message("\red The teleporter rejects the AI unit.") + visible_message("The teleporter rejects the AI unit.") if(istype(M, /mob/living/silicon/ai)) var/mob/living/silicon/ai/T = M - var/list/TPError = list("\red Firmware instructions dictate you must remain on your assigned station!", - "\red You cannot interface with this technology and get rejected!", - "\red External firewalls prevent you from utilizing this machine!", - "\red Your AI core's anti-bluespace failsafes trigger and prevent teleportation!") + var/list/TPError = list("Firmware instructions dictate you must remain on your assigned station!", + "You cannot interface with this technology and get rejected!", + "External firewalls prevent you from utilizing this machine!", + "Your AI core's anti-bluespace failsafes trigger and prevent teleportation!") to_chat(T, "[pick(TPError)]") return else @@ -370,6 +371,71 @@ else icon_state = "tele0" +/obj/machinery/teleport/perma + name = "permanent teleporter" + desc = "A teleporter with the target pre-set on the circuit board." + icon_state = "tele0" + var/recalibrating = 0 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 2000 + + var/target + var/tele_delay = 50 + +/obj/machinery/teleport/perma/RefreshParts() + for(var/obj/item/weapon/circuitboard/teleporter_perma/C in component_parts) + target = C.target + var/A = 40 + for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) + A -= M.rating * 10 + tele_delay = max(A, 0) + update_icon() + +/obj/machinery/teleport/perma/Bumped(M as mob|obj) + if(stat & (BROKEN|NOPOWER)) + return + if(z == ZLEVEL_CENTCOMM) + to_chat(M, "You can't use this here.") + return + if(target && !recalibrating && !panel_open) + //--FalseIncarnate + //Prevents AI cores from using the teleporter, prints out failure messages for clarity + if(istype(M, /mob/living/silicon/ai) || istype(M, /obj/structure/AIcore)) + visible_message("The teleporter rejects the AI unit.") + if(istype(M, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/T = M + var/list/TPError = list("Firmware instructions dictate you must remain on your assigned station!", + "You cannot interface with this technology and get rejected!", + "External firewalls prevent you from utilizing this machine!", + "Your AI core's anti-bluespace failsafes trigger and prevent teleportation!") + to_chat(T, "[pick(TPError)]") + return + else + do_teleport(M, target) + use_power(5000) + + if(tele_delay) + recalibrating = 1 + update_icon() + spawn(tele_delay) + recalibrating = 0 + update_icon() + //--FalseIncarnate + return + +/obj/machinery/teleport/perma/power_change() + ..() + update_icon() + +/obj/machinery/teleport/perma/update_icon() + if(panel_open) + icon_state = "tele-o" + else if(target && !recalibrating && !(stat & (BROKEN|NOPOWER))) + icon_state = "tele1" + else + icon_state = "tele0" + /obj/machinery/teleport/station name = "station" desc = "The power control station for a bluespace teleporter." @@ -457,6 +523,11 @@ link_console_and_hub() to_chat(user, "You reconnect the station to nearby machinery.") return + if(istype(W, /obj/item/weapon/circuitboard/teleporter_perma)) + var/obj/item/weapon/circuitboard/teleporter_perma/C = W + C.target = teleporter_console.target + to_chat(user, "You copy the targeting information from \the [src] to \the [W]") + return /obj/machinery/teleport/station/attack_ai() src.attack_hand() diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index 7a01a53a8b9..4eae22d7646 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -22,7 +22,7 @@ recharging_mecha = null return ..() -/turf/simulated/floor/mech_bay_recharge_floor/Entered(var/obj/mecha/mecha) +/turf/simulated/floor/mech_bay_recharge_floor/Entered(var/obj/mecha/mecha, atom/OL, ignoreRest = 0) . = ..() if(istype(mecha)) mecha.occupant_message("Initializing power control devices.") diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 562e30d834d..a88d1c49bad 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -9,9 +9,6 @@ idle_power_usage = 20 active_power_usage = 5000 var/time_coeff = 1 - var/resource_coeff = 1 - var/time_coeff_tech = 1 - var/resource_coeff_tech = 1 var/list/resources = list( MAT_METAL=0, MAT_GLASS=0, @@ -80,12 +77,6 @@ T += M.rating res_max_amount = (187000+(T * 37500)) - //ressources adjustment coefficient (1 -> 0.88 -> 0.75) - T = -1 - for(var/obj/item/weapon/stock_parts/micro_laser/Ma in component_parts) - T += Ma.rating - resource_coeff = round(initial(resource_coeff) - (initial(resource_coeff)*(T))/8,0.01) - //building time adjustment coefficient (1 -> 0.8 -> 0.6) T = -1 for(var/obj/item/weapon/stock_parts/manipulator/Ml in component_parts) @@ -230,29 +221,6 @@ output += "\[Process queue | Clear queue\]" return output -/obj/machinery/mecha_part_fabricator/proc/update_tech() - if(!files) - return - var/output - for(var/datum/tech/T in files.known_tech) - if(T && T.level > 1) - var/diff - switch(T.id) - if("materials") - //one materials level is 1/32, so that max level is 0.75 coefficient - diff = round(initial(resource_coeff_tech) - (initial(resource_coeff_tech)*(T.level-1))/32,0.01) - if(resource_coeff_tech>diff) - resource_coeff_tech = diff - output+="Production efficiency increased.
" - if("programming") - //one materials level is 1/40, so that max level is 0.8 coefficient - diff = round(initial(time_coeff_tech) - (initial(time_coeff_tech)*(T.level-1))/40,0.1) - if(time_coeff_tech>diff) - time_coeff_tech = diff - output+="Production routines updated.
" - return output - - /obj/machinery/mecha_part_fabricator/proc/sync() temp = "Updating local R&D database..." updateUsrDialog() @@ -269,7 +237,6 @@ files.RefreshResearch() temp = "Processed equipment designs.
" //check if the tech coefficients have changed - temp += update_tech() temp += "Return" updateUsrDialog() @@ -281,10 +248,10 @@ return /obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, resource, roundto = 1) - return round(D.materials[resource]*resource_coeff*resource_coeff_tech, roundto) + return round(D.materials[resource], roundto) /obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran - return round(initial(D.construction_time)*time_coeff*time_coeff_tech, roundto) + return round(initial(D.construction_time)*time_coeff, roundto) /obj/machinery/mecha_part_fabricator/attack_ghost(mob/user) interact(user) diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 744edcd7711..d73edde1525 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -916,6 +916,8 @@ steam.start() -- spawns the effect /obj/effect/effect/foam/New(loc, var/ismetal=0) ..(loc) icon_state = "[ismetal ? "m":""]foam" + if(!ismetal && reagents) + color = mix_color_from_reagents(reagents.reagent_list) metal = ismetal playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) spawn(3 + metal*3) @@ -944,10 +946,13 @@ steam.start() -- spawns the effect // on delete, transfer any reagents to the floor /obj/effect/effect/foam/Destroy() if(!metal && reagents) - for(var/atom/A in oview(0,src)) + reagents.handle_reactions() + for(var/atom/A in oview(1, src)) if(A == src) continue - reagents.reaction(A, 1, 1) + if(reagents.total_volume) + var/fraction = 5 / reagents.total_volume + reagents.reaction(A, TOUCH, fraction) return ..() /obj/effect/effect/foam/process() @@ -969,13 +974,14 @@ steam.start() -- spawns the effect if(F) continue - F = new(T, metal) + F = new /obj/effect/effect/foam(T, metal) F.amount = amount if(!metal) - F.create_reagents(10) - if (reagents) + F.create_reagents(15) + if(reagents) for(var/datum/reagent/R in reagents.reagent_list) - F.reagents.add_reagent(R.id,1) + F.reagents.add_reagent(R.id, min(R.volume, 3), R.data, reagents.chem_temp) + F.color = mix_color_from_reagents(reagents.reagent_list) // foam disolves when heated // except metal foams @@ -993,16 +999,26 @@ steam.start() -- spawns the effect if (istype(AM, /mob/living/carbon)) var/mob/living/carbon/M = AM - M.slip("foam", 5, 2) + if(M.slip("foam", 5, 2)) + if(reagents) + for(var/reagent_id in reagents.reagent_list) + var/amount = M.reagents.get_reagent_amount(reagent_id) + if(amount < 25) + M.reagents.add_reagent(reagent_id, min(round(amount / 2), 15)) + if(reagents.total_volume) + var/fraction = 5 / reagents.total_volume + reagents.reaction(M, TOUCH, fraction) /datum/effect/system/foam_spread var/amount = 5 // the size of the foam spread. var/list/carried_reagents // the IDs of reagents present when the foam was mixed var/metal = 0 // 0=foam, 1=metalfoam, 2=ironfoam + var/temperature = T0C + var/list/banned_reagents = list("smoke_powder", "fluorosurfactant", "stimulants") /datum/effect/system/foam_spread/set_up(amt=5, loca, var/datum/reagents/carry = null, var/metalfoam = 0) - amount = round(sqrt(amt / 3), 1) + amount = min(round(amt/5, 1), 7) if(istype(loca, /turf/)) location = loca else @@ -1010,35 +1026,40 @@ steam.start() -- spawns the effect carried_reagents = list() metal = metalfoam - + temperature = carry.chem_temp // bit of a hack here. Foam carries along any reagent also present in the glass it is mixed // with (defaults to water if none is present). Rather than actually transfer the reagents, // this makes a list of the reagent ids and spawns 1 unit of that reagent when the foam disolves. - if(carry && !metal) for(var/datum/reagent/R in carry.reagent_list) - carried_reagents += R.id + carried_reagents[R.id] = R.volume /datum/effect/system/foam_spread/start() spawn(0) var/obj/effect/effect/foam/F = locate() in location if(F) F.amount += amount + F.amount = min(F.amount, 27) return - F = new(src.location, metal) + F = new /obj/effect/effect/foam(location, metal) F.amount = amount if(!metal) // don't carry other chemicals if a metal foam - F.create_reagents(10) + F.create_reagents(15) if(carried_reagents) for(var/id in carried_reagents) - F.reagents.add_reagent(id,1) + if(banned_reagents.Find("[id]")) + continue + var/datum/reagent/reagent_volume = carried_reagents[id] + F.reagents.add_reagent(id, min(reagent_volume, 3), null, temperature) + F.color = mix_color_from_reagents(F.reagents.reagent_list) else - F.reagents.add_reagent("water", 1) + F.reagents.add_reagent("cleaner", 1) + F.color = mix_color_from_reagents(F.reagents.reagent_list) // wall formed by metal foams // dense and opaque, but easy to break diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index c03652a1126..bdec24c7902 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -89,7 +89,7 @@ var/turf/T = A if(!T) continue - var/dist = cheap_hypotenuse(T.x, T.y, x0, y0) + var/dist = hypotenuse(T.x, T.y, x0, y0) if(config.reactionary_explosions) var/turf/Trajectory = T @@ -206,7 +206,7 @@ var/list/wipe_colours = list() for(var/turf/T in spiral_range_turfs(max_range, epicenter)) wipe_colours += T - var/dist = cheap_hypotenuse(T.x, T.y, x0, y0) + var/dist = hypotenuse(T.x, T.y, x0, y0) if(newmode == "Yes") var/turf/TT = T diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index 6dd269176b3..70ede0a075d 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -41,7 +41,7 @@ if(href_list["create_area"]) if(get_area_type()==AREA_SPACE) create_area() - updateUsrDialog() + //One-use area creation permits. @@ -77,6 +77,12 @@ icon_state = "blueprints" fluffnotice = "Property of Nanotrasen. For heads of staff only. Store in high-secure storage." w_class = 3 + var/list/showing = list() + var/client/viewing + +/obj/item/areaeditor/blueprints/Destroy() + clear_viewer() + return ..() /obj/item/areaeditor/blueprints/attack_self(mob/user as mob) @@ -85,6 +91,11 @@ if(get_area_type() == AREA_STATION) . += "

According to the [src], you are now in \"[sanitize(A.name)]\".

" . += "

You may move an amendment to the drawing.

" + if(!viewing) + . += "

View structural data

" + else + . += "

Refresh structural data

" + . += "

Hide structural data

" var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500) popup.set_content(.) popup.open() @@ -97,8 +108,43 @@ if(get_area_type()!=AREA_STATION) return edit_area() - updateUsrDialog() + if(href_list["view_blueprints"]) + set_viewer(usr, "You flip the blueprints over to view the complex information diagram.") + if(href_list["hide_blueprints"]) + clear_viewer(usr, "You flip the blueprints over to view the simple information diagram.") + if(href_list["refresh"]) + clear_viewer(usr) + set_viewer(usr) + attack_self(usr) +/obj/item/areaeditor/blueprints/proc/get_images(turf/T, viewsize) + . = list() + for(var/tt in RANGE_TURFS(viewsize, T)) + var/turf/TT = tt + if(TT.blueprint_data) + . += TT.blueprint_data + +/obj/item/areaeditor/blueprints/proc/set_viewer(mob/user, message = "") + if(user && user.client) + if(viewing) + clear_viewer() + viewing = user.client + showing = get_images(get_turf(user), viewing.view) + viewing.images |= showing + if(message) + to_chat(user, message) + +/obj/item/areaeditor/blueprints/proc/clear_viewer(mob/user, message = "") + if(viewing) + viewing.images -= showing + viewing = null + showing.Cut() + if(message) + to_chat(user, message) + +/obj/item/areaeditor/blueprints/dropped(mob/user) + ..() + clear_viewer() /obj/item/areaeditor/proc/get_area() var/turf/T = get_turf(usr) diff --git a/code/game/objects/items/contraband.dm b/code/game/objects/items/contraband.dm index 22eb55e150e..8bc5b265466 100644 --- a/code/game/objects/items/contraband.dm +++ b/code/game/objects/items/contraband.dm @@ -29,35 +29,35 @@ new /obj/item/weapon/reagent_containers/food/pill/zoom( src ) new /obj/item/weapon/reagent_containers/food/pill/zoom( src ) - /obj/item/weapon/reagent_containers/food/pill/random_drugs name = "pill" - desc = "" + desc = "A cocktail of illicit designer drugs, who knows what might be in here." /obj/item/weapon/reagent_containers/food/pill/random_drugs/New() ..() icon_state = "pill" + pick("2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20") - name = pick("lunar","vorpal","hardcore","willow", "void","loopy","electro", "cyber","heavy", "ninja", "hydro", "blue", "red", "green", "purple", "strong", "divine","carp" ,"deadly","dead","vicious" ,"wild" ,"demon", "chill", "solid", "liquid", "crazy", "super", "hyper", "space", "wizard", "rainbow", "star", "turbo", "prism", "sticky") + " " + pick("jack","zero","null","beat","nip","bubbles" ,"ice","medicine","venom","shock","solar" ,"spice" ,"shredder", "heart" , "heat", "pill","hopper","scum","fruit", "bolt", "deck", "butter", "runoff", "grease", "flair", "sweat", "zone", "blast") + name = "[pick_list("chemistry_tools.json", "CYBERPUNK_drug_prefixes")] [pick_list("chemistry_tools.json", "CYBERPUNK_drug_suffixes")]" - reagents.add_reagent(pick("pancuronium","neurotoxin","frostoil", "toxin","morphine", "carpotoxin", "hippiesdelight","methamphetamine","haloperidol" , "hydrocodone", "psilocybin", "lsd", "capsaicin", "space_drugs" , "epinephrine", "serotrotium"), pick(5,7,10,13,15)) - reagents.add_reagent(pick("pancuronium","neurotoxin","frostoil", "toxin","morphine", "carpotoxin", "hippiesdelight","methamphetamine","haloperidol" ,"hydrocodone", "psilocybin", "lsd", "capsaicin", "space_drugs" , "epinephrine", "serotrotium"), pick(5,7,10,13,15)) - reagents.add_reagent(pick("pancuronium","neurotoxin","frostoil", "toxin","morphine", "carpotoxin", "hippiesdelight","methamphetamine","haloperidol" , "hydrocodone", "psilocybin", "lsd", "capsaicin", "space_drugs" , "epinephrine", "serotrotium"), pick(5,7,10,13,15)) + var/primaries = rand(1,3) + var/adulterants = rand(2,4) + + while(primaries > 0) + primaries-- + reagents.add_reagent(pick_list("chemistry_tools.json", "CYBERPUNK_drug_primaries"), 6) + while(adulterants > 0) + adulterants-- + reagents.add_reagent(pick_list("chemistry_tools.json", "CYBERPUNK_drug_adulterants"), 3) /obj/item/weapon/storage/pill_bottle/random_drug_bottle - name = "odd pill bottle" - desc = "You're not sure if you trust the contents of this bottle..." + name = "pill bottle (???)" + desc = "Huh." /obj/item/weapon/storage/pill_bottle/random_drug_bottle/New() ..() - new /obj/item/weapon/reagent_containers/food/pill/random_drugs( src ) - new /obj/item/weapon/reagent_containers/food/pill/random_drugs( src ) - new /obj/item/weapon/reagent_containers/food/pill/random_drugs( src ) - new /obj/item/weapon/reagent_containers/food/pill/random_drugs( src ) - new /obj/item/weapon/reagent_containers/food/pill/random_drugs( src ) - new /obj/item/weapon/reagent_containers/food/pill/random_drugs( src ) - new /obj/item/weapon/reagent_containers/food/pill/random_drugs( src ) + for(var/i in 1 to 5) + new /obj/item/weapon/reagent_containers/food/pill/random_drugs(src) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 48e477cc258..ba49f4a9e4c 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -77,6 +77,11 @@ if (!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") return + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if((HULK in H.mutations) || (H.species.flags & NOGUNS)) + user << "Your fingers can't press the button!" + return add_fingerprint(user) diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index fba22decc42..f1eb48e06d7 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -56,6 +56,7 @@ dir=ndir b_stat=1 on = 0 + global_intercoms.Add(src) update_icon() /obj/item/device/radio/intercom/department/medbay/New() @@ -104,6 +105,7 @@ /obj/item/device/radio/intercom/Destroy() processing_objects.Remove(src) + global_intercoms.Remove(src) return ..() /obj/item/device/radio/intercom/attack_ai(mob/user as mob) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 741ecfa7fa2..1f86a35c497 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -422,11 +422,13 @@ var/global/list/default_medbay_channels = list( //#### Sending the signal to all subspace receivers ####// for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) + spawn(0) + R.receive_signal(signal) // Allinone can act as receivers. for(var/obj/machinery/telecomms/allinone/R in telecomms_list) - R.receive_signal(signal) + spawn(0) + R.receive_signal(signal) // Receiving code can be located in Telecommunications.dm return signal.data["done"] && position.z in signal.data["level"] @@ -475,7 +477,8 @@ var/global/list/default_medbay_channels = list( signal.frequency = connection.frequency // Quick frequency set for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) + spawn(0) + R.receive_signal(signal) sleep(rand(10,25)) // wait a little... @@ -520,7 +523,7 @@ var/global/list/default_medbay_channels = list( // what the range is in which mobs will hear the radio // returns: -1 if can't receive, range otherwise - if (wires.IsIndexCut(WIRE_RECEIVE)) + if (!wires || wires.IsIndexCut(WIRE_RECEIVE)) return -1 if(!listening) return -1 diff --git a/code/game/objects/items/flag.dm b/code/game/objects/items/flag.dm index 12594ff0310..97b2dfd6cfc 100644 --- a/code/game/objects/items/flag.dm +++ b/code/game/objects/items/flag.dm @@ -161,6 +161,11 @@ desc = "A flag proudly proclaiming the superior heritage of Vulpkanin." icon_state = "vulpflag" +/obj/item/flag/species/drask + name = "Drask flag" + desc = "A flag proudly proclaiming the superior heritage of Drask." + icon_state = "draskflag" + //Department Flags /obj/item/flag/cargo diff --git a/code/game/objects/items/policetape.dm b/code/game/objects/items/policetape.dm index bd222c52dbb..9b1f27dea1b 100644 --- a/code/game/objects/items/policetape.dm +++ b/code/game/objects/items/policetape.dm @@ -166,7 +166,7 @@ var/list/tape_roll_applications = list() /obj/item/tape/attack_hand(mob/user as mob) if (user.a_intent == I_HELP && src.allowed(user)) - user.show_viewers("\blue [user] lifts [src], allowing passage.") + user.visible_message("[user] lifts [src], allowing passage.", "You lift [src], allowing passage.") src.density = 0 spawn(200) src.density = 1 @@ -180,7 +180,7 @@ var/list/tape_roll_applications = list() if(user.a_intent == I_HELP && ((!can_puncture(W) && src.allowed(user)))) to_chat(user, "You can't break the [src] with that!") return - user.show_viewers("\blue [user] breaks the [src]!") + user.visible_message("[user] breaks the [src]!", "You break the [src]!") var/dir[2] var/icon_dir = src.icon_state diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 6a863bcc60f..25ade73eb38 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -949,6 +949,9 @@ obj/item/toy/cards/deck/syndicate/black /obj/item/toy/plushie/attack(mob/M as mob, mob/user as mob) playsound(loc, poof_sound, 20, 1) // Play the whoosh sound in local area + if(iscarbon(M)) + if(prob(10)) + M.reagents.add_reagent("hugs", 10) return ..() /obj/item/toy/plushie/attack_self(mob/user as mob) diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index e573215dcaa..159b4014bf4 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -7,62 +7,85 @@ w_class = 1.0 desc = "This is rubbish." - raisins +/obj/item/trash/raisins name = "4no raisins" icon_state= "4no_raisins" - candy + +/obj/item/trash/candy name = "Candy" icon_state= "candy" - cheesie + +/obj/item/trash/cheesie name = "Cheesie honkers" icon_state = "cheesie_honkers" - chips + +/obj/item/trash/chips name = "Chips" icon_state = "chips" - popcorn + +/obj/item/trash/popcorn name = "Popcorn" icon_state = "popcorn" - sosjerky + +/obj/item/trash/sosjerky name = "Scaredy's Private Reserve Beef Jerky" icon_state = "sosjerky" - syndi_cakes + +/obj/item/trash/syndi_cakes name = "Syndi cakes" icon_state = "syndi_cakes" - waffles + +/obj/item/trash/waffles name = "Waffles" icon_state = "waffles" - plate + +/obj/item/trash/plate name = "Plate" icon_state = "plate" - snack_bowl + +/obj/item/trash/snack_bowl name = "Snack bowl" icon_state = "snack_bowl" - pistachios + +/obj/item/trash/pistachios name = "Pistachios pack" icon_state = "pistachios_pack" - semki + +/obj/item/trash/semki name = "Semki pack" icon_state = "semki_pack" - tray + +/obj/item/trash/tray name = "Tray" icon_state = "tray" - candle + +/obj/item/trash/candle name = "candle" icon = 'icons/obj/candle.dmi' icon_state = "candle4" - liquidfood + +/obj/item/trash/liquidfood name = "\improper \"LiquidFood\" ration" icon_state = "liquidfood" - can + +/obj/item/trash/can name = "crushed can" icon_state = "cola" - gum + +/obj/item/trash/gum name = "chewed gum" desc = "NOT free candy." icon_state = "gum" - tastybread + +/obj/item/trash/tastybread name = "bread tube" icon_state = "tastybread" +/obj/item/trash/tapetrash + name = "old duct tape" + icon_state = "tape" + desc = "Not sticky anymore." + throw_range = 1 + /obj/item/trash/attack(mob/M as mob, mob/living/user as mob) return diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 7bd8f6e1207..5d85ea20e2b 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -74,6 +74,12 @@ RCD src.spark_system.start() return if(3) + mode = 4 + to_chat(user, "Changed mode to 'Windows'") + if(prob(20)) + src.spark_system.start() + return + if(4) mode = 1 to_chat(user, "Changed mode to 'Floor & Walls'") if(prob(20)) @@ -88,7 +94,7 @@ RCD if(!proximity) return if(istype(A,/area/shuttle)||istype(A,/turf/space/transit)) return 0 - if(!(istype(A, /turf) || istype(A, /obj/machinery/door/airlock))) + if(!(istype(A, /turf) || istype(A, /obj/machinery/door/airlock) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/window))) return 0 switch(mode) @@ -97,7 +103,8 @@ RCD if(useResource(1, user)) to_chat(user, "Building Floor...") activate() - A:ChangeTurf(/turf/simulated/floor/plating) + var/turf/AT = A + AT.ChangeTurf(/turf/simulated/floor/plating) return 1 return 0 @@ -108,7 +115,8 @@ RCD if(do_after(user, 20, target = A)) if(!useResource(3, user)) return 0 activate() - A:ChangeTurf(/turf/simulated/wall) + var/turf/AT = A + AT.ChangeTurf(/turf/simulated/wall) return 1 return 0 @@ -136,7 +144,8 @@ RCD if(do_after(user, 40, target = A)) if(!useResource(5, user)) return 0 activate() - A:ChangeTurf(/turf/simulated/floor/plating) + var/turf/AT = A + AT.ChangeTurf(/turf/simulated/floor/plating) return 1 return 0 @@ -147,7 +156,8 @@ RCD if(do_after(user, 50, target = A)) if(!useResource(5, user)) return 0 activate() - A:ChangeTurf(/turf/space) + var/turf/AT = A + AT.ChangeTurf(/turf/space) return 1 return 0 @@ -161,7 +171,78 @@ RCD qdel(A) return 1 return 0 + + if(istype(A, /obj/structure/window)) // You mean the grille of course, do you? + A = locate(/obj/structure/grille) in A.loc + + if(istype(A, /obj/structure/grille)) + if(!checkResource(2, user)) + return 0 + to_chat(user, "Deconstructing window...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(!do_after(user, 20, target = A)) + return 0 + if(locate(/obj/structure/window/full/shuttle) in A.contents) + return 0 // Let's not give shuttle-griefers an easy time. + if(!useResource(2, user)) + return 0 + activate() + var/turf/T1 = get_turf(A) + qdel(A) + A = null + for(var/obj/structure/window/W in T1.contents) + W.disassembled = 1 + W.density = 0 + qdel(W) + for(var/cdir in cardinal) + var/turf/T2 = get_step(T1, cdir) + if(locate(/obj/structure/window/full/shuttle) in T2.contents) + continue // Shuttle windows? Nah. We don't need extra windows there. + if(!(locate(/obj/structure/grille) in T2.contents)) + continue + for(var/obj/structure/window/W in T2.contents) + if(W.dir == turn(cdir, 180)) + W.disassembled = 1 + W.density = 0 + qdel(W) + var/obj/structure/window/reinforced/W = new(T2) + W.dir = turn(cdir, 180) + return 1 return 0 + if(4) + if(istype(A, /turf/simulated/floor)) + if(locate(/obj/structure/grille) in contents) + return 0 // We already have window + if(!checkResource(2, user)) + return 0 + to_chat(user, "Constructing window...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(!do_after(user, 20, target = A)) + return 0 + if(locate(/obj/structure/grille) in A.contents) + return 0 // We already have window + if(!useResource(2, user)) + return 0 + activate() + new /obj/structure/grille(A) + for(var/obj/structure/window/W in contents) + W.disassembled = 1 // Prevent that annoying glass breaking sound + W.density = 0 + qdel(W) + for(var/cdir in cardinal) + var/turf/T = get_step(A, cdir) + if(locate(/obj/structure/grille) in T.contents) + for(var/obj/structure/window/W in T.contents) + if(W.dir == turn(cdir, 180)) + W.disassembled = 1 + W.density = 0 + qdel(W) + else // Build a window! + var/obj/structure/window/reinforced/W = new(A) + W.dir = cdir + var/turf/AT = A + AT.ChangeTurf(/turf/simulated/floor/plating) // Platings go under windows. + return 1 else to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.") return 0 diff --git a/code/game/objects/items/weapons/bee_briefcase.dm b/code/game/objects/items/weapons/bee_briefcase.dm new file mode 100644 index 00000000000..5c3e9afff5d --- /dev/null +++ b/code/game/objects/items/weapons/bee_briefcase.dm @@ -0,0 +1,79 @@ + +/obj/item/weapon/bee_briefcase + name = "briefcase" + desc = "This briefcase has easy-release clasps and smells vaguely of honey and blood..." + icon = 'icons/obj/storage.dmi' + icon_state = "briefcase" + item_state = "briefcase" + flags = CONDUCT + hitsound = "swing_hit" + force = 10 + throw_speed = 2 + throw_range = 4 + w_class = 4 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") + var/bees_left = 10 + var/list/blood_list = list() + var/sound_file = 'sound/misc/briefcase_bees.ogg' + var/next_sound = 0 + +/obj/item/weapon/bee_briefcase/examine(mob/user) + ..() + if(loc == user) + if(bees_left) + to_chat(user, "There are [bees_left] bees still inside in briefcase!") + else + to_chat(user, "The bees are gone... Colony collapse disorder?") + +/obj/item/weapon/bee_briefcase/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/weapon/reagent_containers/syringe)) + + var/obj/item/weapon/reagent_containers/syringe/S = I + if(!bees_left) + to_chat(user, "The briefcase is empty, so there is no point in injecting something into it.") + return + if(S.reagents && S.reagents.total_volume) + to_chat(user, "You inject [src] with [S].") + for(var/datum/reagent/A in S.reagents.reagent_list) + if(A.id == "blood") + if(!(A.data["donor"] in blood_list)) + blood_list += A.data["donor"] + if(A.id == "strange_reagent") //RELOAD THE BEES (1 bee per 1 unit, max 15 bees) + if(bees_left < 15) + bees_left = min(15, round((bees_left + A.volume), 1)) //No partial bees, max 15 bees in case at any given time + to_chat(user, "The buzzing inside the briefcase intensifies as new bees form inside.") + else + to_chat(user, "The buzzing inside the briefcase swells momentarily, then returns to normal. Guess it was too cramped...") + S.reagents.clear_reagents() + S.update_icon() + + else if(istype(I, /obj/item/weapon/plantspray)) + var/obj/item/weapon/plantspray/PS = I + user.drop_item(PS) + bees_left = max(0, (bees_left - PS.pest_kill_str)) + to_chat(user, "You spray [PS] into \the [src].") + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + qdel(PS) + +/obj/item/weapon/bee_briefcase/attack_self(mob/user as mob) + if(!bees_left) + to_chat(user, "The lack of all and any bees at this event has been somewhat of a let-down...") + return + else + if(world.time >= next_sound) //This cooldown doesn't prevent us from releasing bees, just stops the sound + next_sound = world.time + 90 + //Play sound through the station intercomms, so everyone knows the doom you have wrought. + for(var/O in global_intercoms) + var/obj/item/device/radio/intercom/I = O + if(I.z != ZLEVEL_STATION) //Only broadcast to the station intercoms + continue + if(!I.on) //Only broadcast to active intercoms (powered, switched on) + continue + playsound(I, sound_file, 35) + + //Release up to 5 bees per use. Without using strange reagent, that means two uses. WITH strange reagent, you can get more if you don't release the last bee + for(var/bee = min(5, bees_left), bee > 0, bee--) + var/mob/living/simple_animal/hostile/poison/bees/syndi/B = new /mob/living/simple_animal/hostile/poison/bees/syndi(null) + B.master_and_friends = blood_list //Doesn't automatically add the person who opens the case, so the bees will attack the user unless they gave their blood + B.forceMove(get_turf(user)) //RELEASE THE BEES! + bees_left -= 5 \ No newline at end of file diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index 2038c4851aa..b3d8a7a19e2 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -39,6 +39,12 @@ //So this is a workaround. This also makes more sense from an IC standpoint. ~Carn if(user.client && (target in user.client.screen)) to_chat(user, "You need to take that [target.name] off before cleaning it.") + else if(target == user && user.a_intent == I_GRAB && ishuman(target)) + var/mob/living/carbon/human/muncher = user + if(muncher && muncher.get_species() == "Drask") + to_chat(user, "You take a bite of the [src.name]. Delicious!") + playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0) + user.nutrition += 2 else if(istype(target,/obj/effect/decal/cleanable)) user.visible_message("[user] begins to scrub \the [target.name] out with [src].") if(do_after(user, src.cleanspeed, target = target) && target) diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 3e2448fa8fe..89a8b52b8da 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -91,16 +91,16 @@ /obj/item/weapon/razor/attack(mob/living/carbon/M as mob, mob/user as mob) if(ishuman(M)) var/mob/living/carbon/human/H = M - var/obj/item/organ/external/head/C = H.organs_by_name["head"] + var/obj/item/organ/external/head/C = H.get_organ("head") var/datum/robolimb/robohead = all_robolimbs[C.model] if(user.zone_sel.selecting == "mouth") if(!get_location_accessible(H, "mouth")) to_chat(user, "The mask is in the way.") return - if((H.species && H.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + if((C.species && C.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... to_chat(user, "You find yourself disappointed at the appalling lack of facial hair.") return - if(H.f_style == "Shaved") + if(C.f_style == "Shaved") to_chat(user, "Already clean-shaven.") return if(H == user) //shaving yourself @@ -109,7 +109,7 @@ if(do_after(user, 50, target = H)) user.visible_message("[user] shaves his facial hair clean with the [src].", \ "You finish shaving with the [src]. Fast and clean!") - H.f_style = "Shaved" + C.f_style = "Shaved" H.update_fhair() playsound(src.loc, 'sound/items/Welder2.ogg', 20, 1) else @@ -121,17 +121,17 @@ if(user_loc == user.loc && H_loc == H.loc) user.visible_message("[user] shaves off [H]'s facial hair with \the [src].", \ "You shave [H]'s facial hair clean off.") - H.f_style = "Shaved" + C.f_style = "Shaved" H.update_fhair() playsound(src.loc, 'sound/items/Welder2.ogg', 20, 1) if(user.zone_sel.selecting == "head") if(!get_location_accessible(H, "head")) to_chat(user, "The headgear is in the way.") return - if((H.species && H.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + if((C.species && C.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... to_chat(user, "You find yourself disappointed at the appalling lack of hair.") return - if(H.h_style == "Bald" || H.h_style == "Balding Hair" || H.h_style == "Skinhead") + if(C.h_style == "Bald" || C.h_style == "Balding Hair" || C.h_style == "Skinhead") to_chat(user, "There is not enough hair left to shave...") return if(H == user) //shaving yourself @@ -140,7 +140,7 @@ if(do_after(user, 50, target = H)) user.visible_message("[user] shaves his head with the [src].", \ "You finish shaving with the [src].") - H.h_style = "Skinhead" + C.h_style = "Skinhead" H.update_hair() playsound(src.loc, 'sound/items/Welder2.ogg', 40, 1) else @@ -152,7 +152,7 @@ if(user_loc == user.loc && H_loc == H.loc) user.visible_message("[user] shaves [H]'s head bald with \the [src]!", \ "You shave [H]'s head bald.") - H.h_style = "Skinhead" + C.h_style = "Skinhead" H.update_hair() playsound(src.loc, 'sound/items/Welder2.ogg', 40, 1) else diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 149cc03a866..a951f1ade8f 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -458,11 +458,11 @@ New() ..() var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) - var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) B1.reagents.add_reagent("fluorosurfactant", 40) - B2.reagents.add_reagent("water", 40) - B2.reagents.add_reagent("cleaner", 60) + B2.reagents.add_reagent("cleaner", 10) + B2.reagents.add_reagent("water", 40) //when you make pre-designed foam reactions that carry the reagents, always add water last beakers += B1 beakers += B2 diff --git a/code/game/objects/items/weapons/scissors.dm b/code/game/objects/items/weapons/scissors.dm index 806c6a5b0e5..9f0c824dead 100644 --- a/code/game/objects/items/weapons/scissors.dm +++ b/code/game/objects/items/weapons/scissors.dm @@ -30,21 +30,21 @@ //this is largely copypasted from there. //handle facial hair (if necessary) var/list/species_facial_hair = list() - var/obj/item/organ/external/head/C = H.organs_by_name["head"] + var/obj/item/organ/external/head/C = H.get_organ("head") var/datum/robolimb/robohead = all_robolimbs[C.model] if(H.gender == MALE || H.get_species() == "Vulpkanin") - if(H.species) + if(C.species) for(var/i in facial_hair_styles_list) var/datum/sprite_accessory/facial_hair/tmp_facial = facial_hair_styles_list[i] - if(H.species.name in tmp_facial.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human hair styles. - if(H.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. + if(C.species.name in tmp_facial.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human hair styles. + if(C.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. if(robohead.is_monitor) to_chat(user, "You are unable to find anything on [H]'s face worth cutting. How disappointing.") return continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. species_facial_hair += i else - if(H.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. + if(C.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. if(!robohead.is_monitor) if("Human" in tmp_facial.species_allowed) species_facial_hair += i @@ -56,18 +56,18 @@ var/f_new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair //handle normal hair var/list/species_hair = list() - if(H.species) + if(C.species) for(var/i in hair_styles_list) var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i] - if(H.species.name in tmp_hair.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human facial hair styles. - if(H.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. + if(C.species.name in tmp_hair.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human facial hair styles. + if(C.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. if(robohead.is_monitor) to_chat(user, "You are unable to find anything on [H]'s head worth cutting. How disappointing.") return continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. species_hair += i else - if(H.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. + if(C.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. if(!robohead.is_monitor) if("Human" in tmp_hair.species_allowed) species_hair += i @@ -84,11 +84,12 @@ user.visible_message("[user] stops cutting [M]'s hair.", "You stop cutting [M]'s hair.") return if(f_new_style) - H.f_style = f_new_style + C.f_style = f_new_style if(h_new_style) - H.h_style = h_new_style + C.h_style = h_new_style H.update_hair() + H.update_fhair() user.visible_message("[user] finishes cutting [M]'s hair!") /obj/item/weapon/scissors/safety //Totally safe, I assure you. diff --git a/code/game/objects/items/weapons/storage/artistic_toolbox.dm b/code/game/objects/items/weapons/storage/artistic_toolbox.dm new file mode 100644 index 00000000000..1b9be2bec62 --- /dev/null +++ b/code/game/objects/items/weapons/storage/artistic_toolbox.dm @@ -0,0 +1,183 @@ +/obj/item/weapon/storage/toolbox/green + name = "artistic toolbox" + desc = "A metal container designed to hold various tools. This variety holds art supplies." + icon_state = "green" + item_state = "toolbox_green" + icon = 'icons/goonstation/objects/objects.dmi' + lefthand_file = 'icons/goonstation/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/goonstation/mob/inhands/items_righthand.dmi' + +/obj/item/weapon/storage/toolbox/green/memetic + name = "artistic toolbox" + desc = "His Grace." + force = 5 + throwforce = 10 + var/list/servantlinks = list() + var/hunger = 0 + var/hunger_message_level = 0 + var/original_owner = null + var/activated = 0 + var/mindless_override = 0 + +/obj/item/weapon/storage/toolbox/green/memetic/attack_hand(mob/living/carbon/user) + if(!activated) + if(ishuman(user) && !user.HasDisease(new /datum/disease/memetic_madness(0))) + activated = 1 + user.ForceContractDisease(new /datum/disease/memetic_madness(0)) + for(var/datum/disease/memetic_madness/DD in user.viruses) + DD.progenitor = src + servantlinks.Add(DD) + break + force += 4 + throwforce += 4 + user << 'sound/goonstation/effects/screech.ogg' + shake_camera(user, 20, 1) + to_chat(user, "His Grace accepts thee, spread His will! All who look close to the Enlightened may share His gifts.") + original_owner = user + return + ..() + +/obj/item/weapon/storage/toolbox/green/memetic/attackby(obj/item/I, mob/user) + if(activated) + if(istype(I, /obj/item/weapon/grab/)) + var/obj/item/weapon/grab/G = I + if(!G.affecting) + return + if(!user.HasDisease(new /datum/disease/memetic_madness(0))) + to_chat(user, "You can't seem to find the latch to open this.") + return + if(!ishuman(G.affecting) || issmall(G.affecting)) + to_chat(user, "His Grace will not accept such a meager offering!") + return + if(!mindless_override) + if(G.affecting.mind == null && G.affecting.ckey == null) + to_chat(user, "His Grace will not accept a soulless shell for an offering!") + return + if(!G.affecting.stat && !G.affecting.restrained() && !G.affecting.weakened) + to_chat(user, "They're moving too much to feed to His Grace!") + return + user.visible_message("[user] is trying to feed [G.affecting] to [src]!") + if(!do_mob(user, G.affecting, 30)) + return + G.affecting.forceMove(src) + user.visible_message("[user] has fed [G.affecting] to [src]!") + + consume(G.affecting) + qdel(G) + + to_chat(user, "You have done well...") + force += 5 + throwforce += 5 + return + + ..() + +/obj/item/weapon/storage/toolbox/green/memetic/proc/consume(mob/M) + if (!M) + return + hunger = 0 + hunger_message_level = 0 + playsound(src.loc, 'sound/goonstation/misc/burp_alien.ogg', 50, 0) + M.emote("scream") + M.death() + M.ghostize() + if(M == original_owner) + qdel(M) + var/obj/item/weapon/storage/toolbox/green/fake_toolbox = new(get_turf(src)) + fake_toolbox.desc = "It looks a lot duller than it used to." + qdel(src) + +/obj/item/weapon/storage/toolbox/green/memetic/Destroy() + for(var/mob/living/carbon/human/H in src) + H.forceMove(get_turf(src)) + visible_message("[H] bursts out of [src]!") + + for(var/A in servantlinks) + var/datum/disease/memetic_madness/D = A + if(D) + D.cure() + break + + if(servantlinks) + servantlinks.Cut() + servantlinks = null + original_owner = null + visible_message("[src] screams!") + playsound(src.loc, 'sound/goonstation/effects/screech.ogg', 100, 1) + return ..() + +/datum/disease/memetic_madness + name = "Memetic Kill Agent" + max_stages = 4 + stage_prob = 8 + spread_text = "Non-Contagious" + spread_flags = SPECIAL + cure_text = "Unknown" + viable_mobtypes = list(/mob/living/carbon/human) + severity = BIOHAZARD + disease_flags = CURABLE + spread_flags = NON_CONTAGIOUS + var/obj/item/weapon/storage/toolbox/green/memetic/progenitor = null + +/datum/disease/memetic_madness/Destroy() + progenitor = null + if(affected_mob) + affected_mob.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE + return ..() + +/datum/disease/memetic_madness/stage_act() + ..() + if(!progenitor) //if someone admin spawns this, cure it right away; this should only ever be given directly from the toolbox itself. + cure() + return + if(progenitor in affected_mob.contents) + affected_mob.adjustOxyLoss(-5) + affected_mob.adjustBruteLoss(-12) + affected_mob.adjustFireLoss(-12) + affected_mob.adjustToxLoss(-5) + var/status = CANSTUN | CANWEAKEN | CANPARALYSE + affected_mob.status_flags &= ~status + affected_mob.dizziness = max(0, affected_mob.dizziness-10) + affected_mob.drowsyness = max(0, affected_mob.drowsyness-10) + affected_mob.SetSleeping(0) + stage = 1 + switch(progenitor.hunger) + if(10 to 60) + if(progenitor.hunger_message_level < 1) + progenitor.hunger_message_level = 1 + to_chat(affected_mob, "Feed Me the unclean ones...They will be purified...") + if(61 to 120) + if(progenitor.hunger_message_level < 2) + progenitor.hunger_message_level = 2 + to_chat(affected_mob, "I hunger for the flesh of the impure...") + if(121 to 210) + if(prob(10) && progenitor.hunger_message_level < 3) + progenitor.hunger_message_level = 3 + to_chat(affected_mob, "The hunger of your Master grows with every passing moment. Feed Me at once.") + if(211 to 399) + if(progenitor.hunger_message_level < 4) + progenitor.hunger_message_level = 4 + to_chat(affected_mob, "His Grace starves in your hands. Feed Me the unclean or suffer.") + if(400 to INFINITY) + affected_mob.visible_message("[progenitor] consumes [affected_mob] whole!") + progenitor.consume(affected_mob) + return + + progenitor.hunger += min(max((progenitor.force / 10), 1), 10) + + else + affected_mob.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE + + if(stage == 4) + if(get_dist(get_turf(progenitor), get_turf(affected_mob)) <= 7) + stage = 1 + return + if(prob(4)) + to_chat(affected_mob, "You are too far from His Grace...") + affected_mob.adjustToxLoss(5) + else if(prob(6)) + to_chat(affected_mob, "You feel weak.") + affected_mob.adjustBruteLoss(5) + + if(ismob(progenitor.loc)) + progenitor.hunger++ \ No newline at end of file diff --git a/code/game/objects/items/weapons/table_rack_parts.dm b/code/game/objects/items/weapons/table_rack_parts.dm index 61c58ce9aa5..4f5db94d4af 100644 --- a/code/game/objects/items/weapons/table_rack_parts.dm +++ b/code/game/objects/items/weapons/table_rack_parts.dm @@ -15,6 +15,11 @@ materials = list(MAT_METAL=4000) flags = CONDUCT attack_verb = list("slammed", "bashed", "battered", "bludgeoned", "thrashed", "whacked") + var/upgradable = 1 + var/result = /obj/structure/table + var/parts = list( + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/metal) /obj/item/weapon/table_parts/reinforced name = "reinforced table parts" @@ -23,18 +28,33 @@ icon_state = "reinf_tableparts" materials = list(MAT_METAL=8000) flags = CONDUCT + upgradable = 0 + result = /obj/structure/table/reinforced + parts = list( + /obj/item/stack/sheet/metal, + /obj/item/stack/rods) /obj/item/weapon/table_parts/wood name = "wooden table parts" desc = "Keep away from fire." icon_state = "wood_tableparts" flags = null + upgradable = 0 + result = /obj/structure/table/woodentable + parts = list( + /obj/item/stack/sheet/wood, + /obj/item/stack/sheet/wood) /obj/item/weapon/table_parts/glass name = "glass table parts" desc = "fragile!" icon_state = "glass_tableparts" flags = null + upgradable = 0 + result = /obj/structure/glasstable_frame + parts = list( + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/metal) /obj/item/weapon/rack_parts name = "rack parts" @@ -49,71 +69,27 @@ */ /obj/item/weapon/table_parts/attackby(obj/item/weapon/W as obj, mob/user as mob, params) ..() - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/metal( user.loc ) - new /obj/item/stack/sheet/metal( user.loc ) - //SN src = null + if(istype(W, /obj/item/weapon/wrench)) + for(var/p in parts) + new p(user.loc) qdel(src) - if (istype(W, /obj/item/stack/rods)) - if (W:amount >= 4) - new /obj/item/weapon/table_parts/reinforced( user.loc ) - to_chat(user, "\blue You reinforce the [name].") - W:use(4) + else if(upgradable && istype(W, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = W + if(R.amount >= 4) + new /obj/item/weapon/table_parts/reinforced(user.loc) + to_chat(user, "You reinforce the [name].") + R.use(4) qdel(src) - else if (W:amount < 4) - to_chat(user, "\red You need at least four rods to do this.") + else + to_chat(user, "You need at least four rods to do this.") /obj/item/weapon/table_parts/attack_self(mob/user as mob) - new /obj/structure/table( user.loc ) + for(var/obj/structure/table/T in user.loc) + to_chat(user, "You can't build tables on top of tables!") + return + new result(user.loc) user.drop_item() qdel(src) - return - - -/* - * Reinforced Table Parts - */ -/obj/item/weapon/table_parts/reinforced/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/metal( user.loc ) - new /obj/item/stack/rods( user.loc ) - qdel(src) - -/obj/item/weapon/table_parts/reinforced/attack_self(mob/user as mob) - new /obj/structure/table/reinforced( user.loc ) - user.drop_item() - qdel(src) - return - -/* - * Wooden Table Parts - */ -/obj/item/weapon/table_parts/wood/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) - qdel(src) - -/obj/item/weapon/table_parts/wood/attack_self(mob/user as mob) - new /obj/structure/table/woodentable( user.loc ) - user.drop_item() - qdel(src) - return - -/* - * Glass Table Parts - */ -/obj/item/weapon/table_parts/glass/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/metal( user.loc ) - new /obj/item/stack/sheet/metal( user.loc ) - qdel(src) - -/obj/item/weapon/table_parts/glass/attack_self(mob/user as mob) - new /obj/structure/glasstable_frame( user.loc ) - user.drop_item() - qdel(src) - return /* * Rack Parts @@ -121,14 +97,11 @@ /obj/item/weapon/rack_parts/attackby(obj/item/weapon/W as obj, mob/user as mob, params) ..() if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/metal( user.loc ) + new /obj/item/stack/sheet/metal(user.loc) qdel(src) - return - return /obj/item/weapon/rack_parts/attack_self(mob/user as mob) - var/obj/structure/rack/R = new /obj/structure/rack( user.loc ) + var/obj/structure/rack/R = new /obj/structure/rack(user.loc) R.add_fingerprint(user) user.drop_item() - qdel(src) - return \ No newline at end of file + qdel(src) \ No newline at end of file diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm index a6c7841e020..067bacaef4b 100644 --- a/code/game/objects/items/weapons/tape.dm +++ b/code/game/objects/items/weapons/tape.dm @@ -12,6 +12,35 @@ update_icon() +/obj/item/stack/tape_roll/attack(mob/living/carbon/human/M as mob, mob/living/user as mob) + if(M.wear_mask) + to_chat(user, "Remove their mask first!") + else if(amount < 2) + to_chat(user, "You'll need more tape for this!") + else if(!M.check_has_mouth()) + to_chat(user, "They have no mouth to tape over!") + else + if(M == user) + to_chat(user, "You try to tape your own mouth shut.") + else + to_chat(user, "You try to tape [M]'s mouth shut.") + M.visible_message("[user] tries to tape [M]'s mouth closed!") + if(do_after(user, 50, target = M)) + if(M == user) + to_chat(user, "You cover your own mouth with a piece of duct tape.") + else + to_chat(user, "You cover [M]'s mouth with a piece of duct tape. That will shut them up!") + M.visible_message("[user] tapes [M]'s mouth shut!") + var/obj/item/clothing/mask/muzzle/G = new /obj/item/clothing/mask/muzzle/tapegag + M.equip_to_slot(G, slot_wear_mask) + G.add_fingerprint(user) + amount = amount - 2 + if(amount <= 0) + user.unEquip(src, 1) + qdel(src) + + + /* -- Disabled for now until it has a use -- /obj/item/stack/tape_roll/attack_self(mob/user as mob) to_chat(user, "You remove a length of tape from [src].") @@ -110,4 +139,4 @@ if(dir_offset & NORTH) pixel_y += 32 else if(dir_offset & SOUTH) - pixel_y -= 32 \ No newline at end of file + pixel_y -= 32 diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 9f6688b69f6..a8579613604 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -23,6 +23,19 @@ // Reagent ID => friendly name var/list/reagents_to_log=list() + var/on_blueprints = FALSE //Are we visible on the station blueprints at roundstart? + var/force_blueprints = FALSE //forces the obj to be on the blueprints, regardless of when it was created. + +/obj/New() + . = ..() + + if(on_blueprints && isturf(loc)) + var/turf/T = loc + if(force_blueprints) + T.add_blueprints(src) + else + T.add_blueprints_preround(src) + /obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = default_state) // Calling Topic without a corresponding window open causes runtime errors if(!nowindow && ..()) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index a6b19ebbea5..42a2541f0bf 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -320,7 +320,7 @@ return step_towards(O, src.loc) if(user != O) - user.show_viewers("[user] stuffs [O] into [src]!") + user.visible_message("[user] stuffs [O] into [src]!", "You stuff [O] into [src]!") src.add_fingerprint(user) /obj/structure/closet/attack_ai(mob/user) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm index fc7563e6b3a..fe1e33d0999 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm @@ -58,6 +58,7 @@ return if(src.allowed(user)) src.locked = !src.locked + playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) for(var/mob/O in viewers(user, 3)) if((O.client && !( O.blinded ))) to_chat(O, "The locker has been [locked ? null : "un"]locked by [user].") @@ -172,4 +173,4 @@ if(istype(src.loc, /obj/structure/bigDelivery)) //Do this to prevent contents from being opened into nullspace (read: bluespace) var/obj/structure/bigDelivery/BD = src.loc BD.attack_hand(usr) - open() \ No newline at end of file + open() diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 699f5ac85aa..d0e8d4c9c85 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -17,6 +17,7 @@ if(!AC) AC = new(src, user) AC.name = "SalonPro Nano-Mirror™" + AC.flags = APPEARANCE_ALL_BODY ui_users[user] = AC AC.ui_interact(user) diff --git a/code/game/response_team.dm b/code/game/response_team.dm index 14bf44ff7b5..241e317c24b 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -148,6 +148,7 @@ var/send_emergency_team /client/proc/create_response_team(obj/spawn_location) var/mob/living/carbon/human/M = new(null) + var/obj/item/organ/external/head/head_organ = M.get_organ("head") response_team_members |= M var/new_gender = alert(usr, "Please select your gender.", "Character Generation", "Male", "Female") @@ -173,18 +174,18 @@ var/send_emergency_team if(prob(5)) facial_hair_style = pick(facial_hair_styles_list) - M.r_facial = hex2num(copytext(hair_c, 2, 4)) - M.g_facial = hex2num(copytext(hair_c, 4, 6)) - M.b_facial = hex2num(copytext(hair_c, 6, 8)) - M.r_hair = hex2num(copytext(hair_c, 2, 4)) - M.g_hair = hex2num(copytext(hair_c, 4, 6)) - M.b_hair = hex2num(copytext(hair_c, 6, 8)) + head_organ.r_facial = hex2num(copytext(hair_c, 2, 4)) + head_organ.g_facial = hex2num(copytext(hair_c, 4, 6)) + head_organ.b_facial = hex2num(copytext(hair_c, 6, 8)) + head_organ.r_hair = hex2num(copytext(hair_c, 2, 4)) + head_organ.g_hair = hex2num(copytext(hair_c, 4, 6)) + head_organ.b_hair = hex2num(copytext(hair_c, 6, 8)) M.r_eyes = hex2num(copytext(eye_c, 2, 4)) M.g_eyes = hex2num(copytext(eye_c, 4, 6)) M.b_eyes = hex2num(copytext(eye_c, 6, 8)) M.s_tone = skin_tone - M.h_style = hair_style - M.f_style = facial_hair_style + head_organ.h_style = hair_style + head_organ.f_style = facial_hair_style M.real_name = "[pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant First Class", "Master Sergeant", "Sergeant Major")] [pick(last_names)]" M.name = M.real_name diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 58f6e4a41d9..efe3bdb6e55 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -67,7 +67,7 @@ else to_chat(user, "The plating is going to need some support! Place metal rods first.") -/turf/space/Entered(atom/movable/A as mob|obj) +/turf/space/Entered(atom/movable/A as mob|obj, atom/OL, ignoreRest = 0) ..() if(destination_z && A && (src in A.locs)) diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index 73398077df2..1b7c9343ca2 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -85,7 +85,7 @@ /turf/space/transit/horizontal dir = WEST -/turf/space/transit/Entered(atom/movable/AM, atom/OldLoc) +/turf/space/transit/Entered(atom/movable/AM, atom/OldLoc, ignoreRest = 0) if(!AM) return if(istype(AM, /obj/docking_port) || !AM.simulated) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 7c0035cc445..8541a638040 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -29,6 +29,8 @@ var/image/obscured //camerachunks + var/list/blueprint_data //for the station blueprints, images of objects eg: pipes + var/list/footstep_sounds = list() var/shoe_running_volume = 50 var/shoe_walking_volume = 20 @@ -119,7 +121,7 @@ return 1 //Nothing found to block so return success! -/turf/Entered(atom/movable/M) +/turf/Entered(atom/movable/M, atom/OL, ignoreRest = 0) if(ismob(M)) var/mob/O = M if(!O.lastarea) @@ -161,6 +163,7 @@ var/old_dynamic_lighting = dynamic_lighting var/list/old_affecting_lights = affecting_lights var/old_lighting_overlay = lighting_overlay + var/old_blueprint_data = blueprint_data if(air_master) air_master.remove_from_active(src) @@ -170,6 +173,7 @@ if(istype(W, /turf/simulated)) W:Assimilate_Air() W.RemoveLattice() + W.blueprint_data = old_blueprint_data for(var/turf/space/S in range(W,1)) S.update_starlight() @@ -384,4 +388,20 @@ return 1 /turf/proc/can_lay_cable() - return can_have_cabling() & !intact \ No newline at end of file + return can_have_cabling() & !intact + +/turf/proc/add_blueprints(atom/movable/AM) + var/image/I = new + I.appearance = AM.appearance + I.appearance_flags = RESET_COLOR|RESET_ALPHA|RESET_TRANSFORM + I.loc = src + I.dir = AM.dir + I.alpha = 128 + + if(!blueprint_data) + blueprint_data = list() + blueprint_data += I + +/turf/proc/add_blueprints_preround(atom/movable/AM) + if(!ticker || ticker.current_state != GAME_STATE_PLAYING) + add_blueprints(AM) \ No newline at end of file diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 6e4f58c5ab2..d7e79934389 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -142,6 +142,11 @@ var/global/nologevent = 0 if(istype(M, /mob/dead/observer)) body += "Re-incarnate | " + if(ispAI(M)) + body += "Is a pAI " + else + body += "Make pAI | " + // DNA2 - Admin Hax if(M.dna && iscarbon(M)) body += "

" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 9ba05c8e483..b1c4e387907 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1142,6 +1142,28 @@ message_admins("\blue [key_name_admin(usr)] attempting to corgize [key_name_admin(H)]", 1) H.corgize() + else if(href_list["makePAI"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makePAI"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + var/painame = "Default" + var/name = "" + if(alert(usr, "Do you want to set their name or let them choose their own name?", "Name Choice", "Set Name", "Let them choose") == "Set Name") + name = sanitize(copytext(input(usr, "Enter a name for the new pAI. Default name is [painame].", "pAI Name", painame),1,MAX_NAME_LEN)) + else + name = sanitize(copytext(input(H, "An admin wants to make you into a pAI. Choose a name. Default is [painame].", "pAI Name", painame),1,MAX_NAME_LEN)) + + if(!name) + name = painame + + log_admin("[key_name(usr)] attempting to pAIze [key_name(H)]") + message_admins("\blue [key_name_admin(usr)] attempting to pAIze [key_name_admin(H)]", 1) + H.paize(name) + else if(href_list["forcespeech"]) if(!check_rights(R_SERVER|R_EVENT)) return diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index b47014b3859..e28174b40d0 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -497,6 +497,7 @@ client/proc/one_click_antag() /datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0) var/mob/living/carbon/human/new_vox = new(spawn_location.loc, "Vox") + var/obj/item/organ/external/head/head_organ = new_vox.get_organ("head") var/sounds = rand(2,8) var/i = 0 @@ -515,8 +516,8 @@ client/proc/one_click_antag() new_vox.add_language("Vox-pidgin") new_vox.add_language("Galactic Common") new_vox.add_language("Tradeband") - new_vox.h_style = "Short Vox Quills" - new_vox.f_style = "Shaved" + head_organ.h_style = "Short Vox Quills" + head_organ.f_style = "Shaved" for(var/obj/item/organ/external/limb in new_vox.organs) limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) @@ -557,7 +558,9 @@ client/proc/one_click_antag() for(var/i = 0, i= 1 && inputvol <= 70) cvol = inputvol - var/list/intercomms = list() + //Allows for override to utilize intercomms on all z-levels + var/B = alert("Do you want to play through intercomms on ALL Z-levels, or just the station?", "Override", "All", "Station") + var/ignore_z = 0 + if(B == "All") + ignore_z = 1 - for(var/obj/item/device/radio/intercom/I in world) - if(I.z != ZLEVEL_STATION) continue - intercomms += I + //Allows for override to utilize incomplete and unpowered intercomms + var/C = alert("Do you want to play through unpowered / incomplete intercomms, so the crew can't silence it?", "Override", "Yep", "Nope") + var/ignore_power = 0 + if(C == "Yep") + ignore_power = 1 - if(intercomms.len) - for(var/obj/item/device/radio/intercom/I in intercomms) - playsound(I, melody, cvol) + for(var/O in global_intercoms) + var/obj/item/device/radio/intercom/I = O + if(I.z != ZLEVEL_STATION && !ignore_z) + continue + if(!I.on && !ignore_power) + continue + playsound(I, melody, cvol) /* /client/proc/cuban_pete() diff --git a/code/modules/awaymissions/mission_code/stationCollision.dm b/code/modules/awaymissions/mission_code/stationCollision.dm index cf006d848c6..7e4fcc03453 100644 --- a/code/modules/awaymissions/mission_code/stationCollision.dm +++ b/code/modules/awaymissions/mission_code/stationCollision.dm @@ -19,9 +19,6 @@ * Areas */ //Gateroom gets its own APC specifically for the gate - /area/awaymission - report_alerts = 0 - /area/awaymission/gateroom //Library, medbay, storage room diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index e53af9a5014..8b222116995 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -63,6 +63,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts #define MAX_SAVE_SLOTS 20 // Save slots for regular players #define MAX_SAVE_SLOTS_MEMBER 20 // Save slots for BYOND members +#define TAB_CHAR 0 +#define TAB_GAME 1 + /datum/preferences //doohickeys for savefiles // var/path @@ -174,7 +177,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/nanotrasen_relation = "Neutral" // 0 = character settings, 1 = game preferences - var/current_tab = 0 + var/current_tab = TAB_CHAR // OOC Metadata: var/metadata = "" @@ -207,229 +210,198 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts save_preferences(C) save_character(C) //let's save this new random character so it doesn't keep generating new ones. +/datum/preferences/proc/color_square(r, g, b) + return "___" // Hello I am a proc full of snowflake species checks how are you /datum/preferences/proc/ShowChoices(mob/user) - if(!user || !user.client) return + if(!user || !user.client) + return update_preview_icon() user << browse_rsc(preview_icon_front, "previewicon.png") user << browse_rsc(preview_icon_side, "previewicon2.png") - var/dat = "
" - dat += "Character Settings" - dat += "Game Preferences" + var/dat = "" + dat += "
" + dat += "Character Settings" + dat += "Game Preferences" dat += "
" dat += "
" switch(current_tab) - if (0) // Character Settings# + if(TAB_CHAR) // Character Settings + dat += "
" + dat += "
" + dat += "Name: " + dat += "[real_name]" + dat += "(Randomize)" + dat += "(Always Randomize)
" + dat += "
" dat += "
" dat += "Slot [slot_name] - " dat += "Load slot - " dat += "Save slot - " dat += "Reload slot" dat += "
" - dat += "

Occupation Choices

" - dat += "Set Occupation Preferences
" + dat += "
" + dat += "
" dat += "

Identity

" - dat += "
" if(appearance_isbanned(user)) - dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.
" - dat += "Name: " - dat += "[real_name]
" - dat += "(Random Name) " - dat += "(Always Random Name: [be_random_name ? "Yes" : "No"])" - dat += "
" - dat += "Gender: [gender == MALE ? "Male" : "Female"]
" - dat += "Age: [age]" - //dat += "Spawn Point: [spawnpoint]" - dat += "
Body " - dat += "(®)" - dat += "
" - dat += "Species: [species]
" - if(species == "Vox")//oldvox code, sucks I know - dat += "N2 Tank: [speciesprefs ? "Large N2 Tank" : "Specialized N2 Tank"]
" - dat += "Secondary Language:
[language]
" - dat += "Blood Type: [b_type]
" + dat += "You are banned from using custom names and appearances. \ + You can continue to adjust your characters, but you will be randomised once you join the game.\ +
" + dat += "Gender: [gender == MALE ? "Male" : "Female"]
" + dat += "Age: [age]
" + dat += "Body: (®)
" + dat += "Species: [species]
" + if(species == "Vox") + dat += "N2 Tank: [speciesprefs ? "Large N2 Tank" : "Specialized N2 Tank"]
" + dat += "Secondary Language: [language]
" + dat += "Blood Type: [b_type]
" if(species in list("Human", "Drask")) - dat += "Skin Tone: [-s_tone + 35]/220
" + dat += "Skin Tone: [-s_tone + 35]/220
" + dat += "Disabilities: \[Set\]
" + dat += "Nanotrasen Relation: [nanotrasen_relation]
" + dat += "Set Flavor Text
" + if(lentext(flavor_text) <= 40) + if(!lentext(flavor_text)) dat += "\[...\]
" + else dat += "[flavor_text]
" + else dat += "[TextPreview(flavor_text)]...
" - // dat += "Skin pattern: Adjust
" - dat += "
Handicaps
" - dat += "\t\[Set Disabilities\]
" - dat += "Limbs and Parts: Adjust
" + dat += "

Hair & Accessories

" + + if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species that have head accessories. + var/headaccessoryname = "Head Accessory: " + if(species == "Unathi") + headaccessoryname = "Horns: " + dat += "[headaccessoryname]" + dat += "[ha_style] " + dat += "Color [color_square(r_headacc, g_headacc, b_headacc)]
" + + if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species that have body markings. + dat += "Body Markings: " + dat += "[m_style]" + dat += "Color [color_square(r_markings, g_markings, b_markings)]
" + + dat += "Hair: " + dat += "[h_style]" + dat += "Color [color_square(r_hair, g_hair, b_hair)]
" + + dat += "Facial Hair: " + dat += "[f_style ? "[f_style]" : "Shaved"]" + dat += "Color [color_square(r_facial, g_facial, b_facial)]
" + + if(species != "Machine") + dat += "Eyes: " + dat += "Color [color_square(r_eyes, g_eyes, b_eyes)]
" + + if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins + dat += "Body Color: " + dat += "Color [color_square(r_skin, g_skin, b_skin)]
" + + if(body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) + dat += "Body Accessory: " + dat += "[body_accessory ? "[body_accessory]" : "None"]
" + + dat += "
" + dat += "

Occupation Choices

" + dat += "Set Occupation Preferences
" + if(jobban_isbanned(user, "Records")) + dat += "You are banned from using character records.
" + else + dat += "Character Records
" + + dat += "

Limbs

" + dat += "Limbs and Parts: Adjust
" if(species != "Slime People" && species != "Machine") - dat += "Internal Organs: Adjust
" + dat += "Internal Organs: Adjust
" //display limbs below var/ind = 0 for(var/name in organ_data) -// to_chat(world, "[ind] \ [organ_data.len]") var/status = organ_data[name] var/organ_name = null switch(name) - if("chest") - organ_name = "torso" - if("groin") - organ_name = "lower body" - if("head") - organ_name = "head" - if("l_arm") - organ_name = "left arm" - if("r_arm") - organ_name = "right arm" - if("l_leg") - organ_name = "left leg" - if("r_leg") - organ_name = "right leg" - if("l_foot") - organ_name = "left foot" - if("r_foot") - organ_name = "right foot" - if("l_hand") - organ_name = "left hand" - if("r_hand") - organ_name = "right hand" - if("heart") - organ_name = "heart" - if("eyes") - organ_name = "eyes" + if("chest") organ_name = "torso" + if("groin") organ_name = "lower body" + if("head") organ_name = "head" + if("l_arm") organ_name = "left arm" + if("r_arm") organ_name = "right arm" + if("l_leg") organ_name = "left leg" + if("r_leg") organ_name = "right leg" + if("l_foot") organ_name = "left foot" + if("r_foot") organ_name = "right foot" + if("l_hand") organ_name = "left hand" + if("r_hand") organ_name = "right hand" + if("heart") organ_name = "heart" + if("eyes") organ_name = "eyes" - if(status == "cyborg") + if(status in list("cyborg", "amputated", "mechanical", "assisted")) ++ind - if(ind > 1) - dat += ", " - var/datum/robolimb/R - if(rlimb_data[name] && all_robolimbs[rlimb_data[name]]) - R = all_robolimbs[rlimb_data[name]] - else - R = basic_robolimb - dat += "\t[R.company] [organ_name] prosthesis" + if(ind > 1) dat += ", " - - else if(status == "amputated") - ++ind - if(ind > 1) - dat += ", " - dat += "\tAmputated [organ_name]" - - else if(status == "mechanical") - ++ind - if(ind > 1) - dat += ", " - dat += "\tMechanical [organ_name]" - - else if(status == "assisted") - ++ind - if(ind > 1) - dat += ", " - switch(organ_name) - if("heart") - dat += "\tPacemaker-assisted [organ_name]" - if("voicebox") //on adding voiceboxes for speaking skrell/similar replacements - dat += "\tSurgically altered [organ_name]" - if("eyes") - dat += "\tRetinal overlayed [organ_name]" + switch(status) + if("cyborg") + var/datum/robolimb/R + if(rlimb_data[name] && all_robolimbs[rlimb_data[name]]) + R = all_robolimbs[rlimb_data[name]] else - dat += "\tMechanically assisted [organ_name]" - if(!ind) - dat += "\[...\]

" - else - dat += "

" - dat += "Underwear:
[underwear]
" - dat += "Undershirt:
[undershirt]
" - dat += "Socks:
[socks]
" - dat += "Backpack Type:
[backbaglist[backbag]]
" - dat += "Nanotrasen Relation:
[nanotrasen_relation]
" - dat += "
Preview
" - dat += "
" + R = basic_robolimb + dat += "\t[R.company] [organ_name] prosthesis" + if("amputated") dat += "\tAmputated [organ_name]" + if("mechanical") dat += "\tMechanical [organ_name]" + if("assisted") + switch(organ_name) + if("heart") dat += "\tPacemaker-assisted [organ_name]" + if("voicebox") dat += "\tSurgically altered [organ_name]" + if("eyes") dat += "\tRetinal overlayed [organ_name]" + else dat += "\tMechanically assisted [organ_name]" + if(!ind) dat += "\[...\]
" + else dat += "
" - if(jobban_isbanned(user, "Records")) - dat += "You are banned from using character records.
" - else - dat += "Character Records
" - dat += "Set Flavor Text
" - if(lentext(flavor_text) <= 40) - if(!lentext(flavor_text)) - dat += "\[...\]" - else - dat += "[flavor_text]" - else - dat += "[TextPreview(flavor_text)]...
" - dat += "
" + dat += "

Clothing

" + dat += "Underwear: [underwear]
" + dat += "Undershirt: [undershirt]
" + dat += "Socks: [socks]
" + dat += "Backpack Type: [backbaglist[backbag]]
" - if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species that have head accessories. - var/headaccessoryname = "Head Accessory" - if(species == "Unathi") - headaccessoryname = "Horns" - dat += "
[headaccessoryname]
" - dat += "Change Color
__
" - dat += "Style: [ha_style]
" + dat += "
" - if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species that have body markings. - dat += "
Body Markings
" - dat += "Change Color
__
" - dat += "
Style: [m_style]
" - - dat += "
Hair
" - dat += "Change Color
__
" - dat += "
Style: [h_style]
" - - dat += "
Facial Hair
" - dat += "Change Color
__
" - dat += "
Style: [f_style ? "[f_style]" : "Shaved"]
" - - if(species != "Machine") - dat += "
Eyes
" - dat += "Change Color
__

" - - if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins - dat += "
Body Color
" - dat += "Change Color
__
" - - if(body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) - dat += "
Body Accessory
" - dat += "Accessory: [body_accessory ? "[body_accessory]" : "None"]
" - - dat += "

" - - if (1) // General Preferences + if(TAB_GAME) // General Preferences dat += "
" dat += "

General Settings

" - dat += "UI Style: [UI_style]
" dat += "Fancy NanoUI: [(nanoui_fancy) ? "Yes" : "No"]
" dat += "Ghost-Item Attack Animation: [(show_ghostitem_attack) ? "Yes" : "No"]
" dat += "Custom UI settings:
" - dat += "Color: [UI_style_color]
__

" - dat += "Alpha (transparency): [UI_style_alpha]
" + dat += " - UI Style: [UI_style]
" + dat += " - Color: [UI_style_color]
__

" + dat += " - Alpha (transparency): [UI_style_alpha]
" + dat += "
" dat += "Play admin midis: [(sound & SOUND_MIDI) ? "Yes" : "No"]
" dat += "Play lobby music: [(sound & SOUND_LOBBY) ? "Yes" : "No"]
" + if(user.client.holder) + dat += "Adminhelp sound: " + dat += "[(sound & SOUND_ADMINHELP)?"On":"Off"]
" + + if(check_rights(R_ADMIN,0)) + dat += "OOC:     Change
" + if(config.allow_Metadata) + dat += "OOC notes: Edit
" + if(unlock_content) + dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" + dat += "Randomized character slot: [randomslot ? "Yes" : "No"]
" dat += "Ghost ears: [(toggles & CHAT_GHOSTEARS) ? "Nearest Creatures" : "All Speech"]
" dat += "Ghost sight: [(toggles & CHAT_GHOSTSIGHT) ? "Nearest Creatures" : "All Emotes"]
" dat += "Ghost radio: [(toggles & CHAT_GHOSTRADIO) ? "Nearest Speakers" : "All Chatter"]
" - if(config.allow_Metadata) - dat += "OOC notes: Edit
" - - if(user.client) - if(user.client.holder) - dat += "Adminhelp sound: " - dat += "[(sound & SOUND_ADMINHELP)?"On":"Off"]
" - - if(check_rights(R_ADMIN,0)) - dat += "OOC:     Change
" - - if(unlock_content) - dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" dat += "
" dat += "

Special Role Settings

" -// dat += "

" if(jobban_isbanned(user, "Syndicate")) dat += "You are banned from special roles." - src.be_special = list() + be_special = list() else - for (var/i in special_roles) + for(var/i in special_roles) if(jobban_isbanned(user, i)) dat += "Be [capitalize(i)]: \[BANNED]
" else if(!player_old_enough_antag(user.client,i)) @@ -437,17 +409,17 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "Be [capitalize(i)]: \[IN [(available_in_days_antag)] DAYS]
" else dat += "Be [capitalize(i)]: [(i in src.be_special) ? "Yes" : "No"]
" - dat += "

" - + dat += "
" + + dat += "
" if(!IsGuestKey(user.key)) dat += "Undo - " dat += "Save Setup - " dat += "Reset Setup" - dat += "
" + dat += "" -// user << browse(dat, "window=preferences;size=560x580") - var/datum/browser/popup = new(user, "preferences", "
Character Setup
", 640, 810) + var/datum/browser/popup = new(user, "preferences", "
Character Setup
", 820, 640) popup.set_content(dat) popup.open(0) @@ -1631,7 +1603,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("nanoui") nanoui_fancy = !nanoui_fancy - if("ghost_att_anim") + if("ghost_att_anim") show_ghostitem_attack = !show_ghostitem_attack if("UIcolor") @@ -1701,6 +1673,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("open_load_dialog") if(!IsGuestKey(user.key)) open_load_dialog(user) + return 1 if("close_load_dialog") close_load_dialog(user) @@ -1753,13 +1726,19 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.g_eyes = g_eyes character.b_eyes = b_eyes - character.r_hair = r_hair - character.g_hair = g_hair - character.b_hair = b_hair + //Head-specific + var/obj/item/organ/external/head/H = character.get_organ("head") + H.r_hair = r_hair + H.g_hair = g_hair + H.b_hair = b_hair - character.r_facial = r_facial - character.g_facial = g_facial - character.b_facial = b_facial + H.r_facial = r_facial + H.g_facial = g_facial + H.b_facial = b_facial + + H.h_style = h_style + H.f_style = f_style + //End of head-specific. character.r_skin = r_skin character.g_skin = g_skin @@ -1767,9 +1746,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.s_tone = s_tone - character.h_style = h_style - character.f_style = f_style - // Destroy/cyborgize organs for(var/name in organ_data) @@ -1846,10 +1822,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.socks = socks if(character.species.bodyflags & HAS_HEAD_ACCESSORY) - character.r_headacc = r_headacc - character.g_headacc = g_headacc - character.b_headacc = b_headacc - character.ha_style = ha_style + H.r_headacc = r_headacc + H.g_headacc = g_headacc + H.b_headacc = b_headacc + H.ha_style = ha_style if(character.species.bodyflags & HAS_MARKINGS) character.r_markings = r_markings character.g_markings = g_markings diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 071c6032722..13b7a948119 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -176,9 +176,11 @@ /obj/item/clothing/head/kitty/update_icon(var/mob/living/carbon/human/user) if(!istype(user)) return + var/obj/item/organ/external/head/head_organ = user.get_organ("head") + mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty") // mob2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty2") - Commented out because it seemingly does nothing. - mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) + mob.Blend(rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair), ICON_ADD) // mob2.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) - Commented out because it seemingly does nothing. var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner") @@ -201,8 +203,9 @@ /obj/item/clothing/head/kitty/mouse/update_icon(var/mob/living/carbon/human/user) if(!istype(user)) return + var/obj/item/organ/external/head/head_organ = user.get_organ("head") mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "mousey") - mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) + mob.Blend(rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair), ICON_ADD) var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "mouseyinner") mob.Blend(earbit, ICON_OVERLAY) diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 93e8dc6cd79..d9817add99f 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -7,6 +7,8 @@ w_class = 2 gas_transfer_coefficient = 0.90 put_on_delay = 20 + var/resist_time = 0 //deciseconds of how long you need to gnaw to get rid of the gag, 0 to make it impossible to remove + var/mute = 1 // 1 - completely mutes you, 0 - muffles everything you say "MHHPHHMMM!!!" species_fit = list("Vox") sprite_sheets = list( "Vox" = 'icons/mob/species/vox/mask.dmi' @@ -24,6 +26,34 @@ icon_state = "gag" w_class = 1 +/obj/item/clothing/mask/muzzle/tapegag + name = "tape gag" + desc = "MHPMHHH!" + icon_state = "tapegag" + item_state = null + w_class = 1 + resist_time = 150 + mute = 0 + species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/mask.dmi', + "Unathi" = 'icons/mob/species/unathi/mask.dmi', + "Tajaran" = 'icons/mob/species/tajaran/mask.dmi', + "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi' + ) + +/obj/item/clothing/mask/muzzle/tapegag/dropped(mob/living/carbon/human/user) + var/atom/movable/R = new /obj/item/trash/tapetrash + if(user.species.bodyflags & HAS_FUR) + R.desc += " Is that...fur?" + var/turf/T = get_turf(src) + R.loc = T + transfer_fingerprints_to(R) + playsound(src,'sound/items/poster_ripped.ogg',40,1) + spawn(0) // Because of how dropping is done, if the muzzle gets deleted now, icons won't properly update and the whole unEquip() proc will break stuff. + qdel(src) // This makes sure it gets deleted AFTER all that has to be done is done. + user.emote("scream") + /obj/item/clothing/mask/surgical name = "sterile mask" desc = "A sterile mask designed to help prevent the spread of diseases." @@ -244,4 +274,4 @@ obj/item/clothing/mask/bandana/purple name = "black bandana" icon_state = "bandblack" item_color = "black" - desc = "It's a black bandana." \ No newline at end of file + desc = "It's a black bandana." diff --git a/code/modules/food/recipes_candy.dm b/code/modules/food/recipes_candy.dm index 794fcb649e2..8067820786f 100644 --- a/code/modules/food/recipes_candy.dm +++ b/code/modules/food/recipes_candy.dm @@ -25,8 +25,37 @@ items = list() result = /obj/item/weapon/reagent_containers/food/snacks/chocolatebar +/datum/recipe/candy/fudge_peanut + reagents = list("sugar" = 5, "milk" = 5) + items = list(/obj/item/weapon/reagent_containers/food/snacks/chocolatebar) + fruit = list("peanuts" = 3) + result = /obj/item/weapon/reagent_containers/food/snacks/candy/fudge/peanut + +/datum/recipe/candy/fudge_cherry + reagents = list("sugar" = 5, "milk" = 5) + items = list(/obj/item/weapon/reagent_containers/food/snacks/chocolatebar) + fruit = list("cherries" = 3) + result = /obj/item/weapon/reagent_containers/food/snacks/candy/fudge/cherry + +/datum/recipe/candy/fudge_cookies_n_cream + reagents = list("sugar" = 5, "milk" = 5, "cream" = 5) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, + /obj/item/weapon/reagent_containers/food/snacks/cookie, + ) + result = /obj/item/weapon/reagent_containers/food/snacks/candy/fudge/cookies_n_cream + +/datum/recipe/candy/fudge_turtle + reagents = list("sugar" = 5, "milk" = 5) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, + /obj/item/weapon/reagent_containers/food/snacks/candy/caramel, + ) + fruit = list("peanuts" = 1) + result = /obj/item/weapon/reagent_containers/food/snacks/candy/fudge/turtle + /datum/recipe/candy/fudge - reagents = list("sugar" = 5, "cream" = 5) + reagents = list("sugar" = 5, "milk" = 5) items = list(/obj/item/weapon/reagent_containers/food/snacks/chocolatebar) result = /obj/item/weapon/reagent_containers/food/snacks/candy/fudge diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm index d3d9cb0f3dc..150528d4c66 100644 --- a/code/modules/hydroponics/beekeeping/beebox.dm +++ b/code/modules/hydroponics/beekeeping/beebox.dm @@ -109,7 +109,7 @@ if((bee_resources >= BEE_RESOURCE_NEW_BEE_COST && prob(BEE_PROB_NEW_BEE)) || freebee) if(!freebee) bee_resources = max(bee_resources - BEE_RESOURCE_NEW_BEE_COST, 0) - var/mob/living/simple_animal/hostile/poison/bees/B = new(src) + var/mob/living/simple_animal/hostile/poison/bees/worker/B = new(src) B.beehome = src B.assign_reagent(queen_bee.beegent) bees += B @@ -180,7 +180,7 @@ visible_message("[user] sets [qb] down inside the apiary, making it their new home.") var/relocated = 0 for(var/b in bees) - var/mob/living/simple_animal/hostile/poison/bees/B = b + var/mob/living/simple_animal/hostile/poison/bees/worker/B = b if(B.reagent_incompatible(queen_bee)) bees -= B B.beehome = null diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index f40887f845a..372e3df9a98 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -40,7 +40,7 @@ seed_name = "ghost pepper" display_name = "ghost pepper plants" mutants = null - chems = list("capsaicin" = list(8,2), "condensedcapsaicin" = list(4,4), "plantmatter" = list(1,50)) + chems = list("capsaicin" = list(8,2), "condensedcapsaicin" = list(4,4), "ghostchilijuice" = list(4,4), "plantmatter" = list(1,50)) kitchen_tag = "ghostchili" preset_icon = "ghostchilipepper" @@ -899,6 +899,7 @@ seed_name = "peanut" display_name = "peanut vines" chems = list("plantmatter" = list(1,10)) + kitchen_tag = "peanuts" preset_icon = "peanuts" /datum/seed/peanuts/New() diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm index 25358df5af2..9102af9e0ab 100644 --- a/code/modules/mining/abandonedcrates.dm +++ b/code/modules/mining/abandonedcrates.dm @@ -11,7 +11,7 @@ /obj/structure/closet/crate/secure/loot/New() ..() - var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "z") + var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") code = "" for(var/i = 0, i < codelen, i++) var/dig = pick(digits) @@ -165,7 +165,7 @@ to_chat(user, "You leave the crate alone.") else to_chat(user, "A red light flashes.") - lastattempt = replacetext(input, 0, "z") + lastattempt = input attempts-- if(attempts == 0) boom(user) @@ -186,19 +186,27 @@ else to_chat(user, "* Anti-Tamper Bomb will activate after [src.attempts] failed access attempts.") if(lastattempt != null) - var/list/guess = list() + var/guess = lastattempt var/bulls = 0 var/cows = 0 - for(var/i = 1, i < codelen + 1, i++) - var/a = copytext(lastattempt, i, i+1) //Stuff the code into the list - guess += a - guess[a] = i - for(var/i in guess) //Go through list and count matches - var/a = findtext(code, i) - if(a == guess[i]) - ++bulls - else if(a) - ++cows + var/list/banned = list() + for(var/i; i <= length(lastattempt); i++) + var/list/a = strip_first(guess) + if(a[1] in banned) + continue + if(findtext(a[2], a[1])) + if(findtext(code, a[1], i, i+1)) + ++bulls + banned += a[1] + else + var/g = findtext(code, a[1]) + if(g) + if(g == i) + ++bulls + else + ++cows + guess = a[2] + to_chat(user, "Last code attempt had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions.") else ..() else ..() diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm index c94bfcd0ce8..140cdc8b85b 100644 --- a/code/modules/mining/equipment_locker.dm +++ b/code/modules/mining/equipment_locker.dm @@ -49,11 +49,11 @@ var/point_upgrade_temp = 1 var/sheet_per_ore_temp = 1 for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) - sheet_per_ore_temp = B.rating + sheet_per_ore_temp = 0.65 + (0.35 * B.rating) for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) ore_pickup_rate_temp = 15 * M.rating for(var/obj/item/weapon/stock_parts/micro_laser/L in component_parts) - point_upgrade_temp = L.rating + point_upgrade_temp = 0.65 + (0.35 * L.rating) ore_pickup_rate = ore_pickup_rate_temp point_upgrade = point_upgrade_temp sheet_per_ore = sheet_per_ore_temp @@ -225,7 +225,7 @@ var/obj/item/stack/sheet/inp = stack_list[text2path(href_list["release"])] var/obj/item/stack/sheet/out = new inp.type() var/desired = input("How much?", "How much to eject?", 1) as num - out.amount = min(desired,50,inp.amount) + out.amount = round(min(desired,50,inp.amount)) if(out.amount >= 1) inp.amount -= out.amount unload_mineral(out) @@ -242,7 +242,7 @@ var/desired = input("How much?", "How much would you like to smelt?", 1) as num var/obj/item/stack/sheet/plasteel/plasteelout = new - plasteelout.amount = min(desired,50,metalstack.amount,plasmastack.amount) + plasteelout.amount = round(min(desired,50,metalstack.amount,plasmastack.amount)) if(plasteelout.amount >= 1) metalstack.amount -= plasteelout.amount plasmastack.amount -= plasteelout.amount @@ -258,7 +258,7 @@ var/desired = input("How much?", "How much would you like to smelt?", 1) as num var/obj/item/stack/sheet/plasmaglass/plasglassout = new - plasglassout.amount = min(desired, 50, glassstack.amount, plasmastack.amount) + plasglassout.amount = round(min(desired, 50, glassstack.amount, plasmastack.amount)) if(plasglassout.amount >= 1) glassstack.amount -= plasglassout.amount plasmastack.amount -= plasglassout.amount @@ -811,7 +811,7 @@ O.forceMove(loc) return -/mob/living/simple_animal/hostile/mining_drone/adjustBruteLoss() +/mob/living/simple_animal/hostile/mining_drone/adjustHealth() if(search_objects) SetOffenseBehavior() ..() diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index a1368665132..9b3bcd38a98 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -192,7 +192,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return 0 /mob/dead/observer/can_use_hands() return 0 -/mob/dead/observer/is_active() return 0 /mob/dead/observer/Stat() ..() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 7a8e608c224..8d68373e3f4 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -124,7 +124,6 @@ I.dropped(src) if(I) I.layer = initial(I.layer) - return 1 @@ -173,4 +172,4 @@ return l_hand if(slot_r_hand) return r_hand - return null \ No newline at end of file + return null diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm index caf3cc4e5ad..c20cc155f37 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm @@ -8,7 +8,7 @@ // if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' // act = copytext(act,1,length(act)) //seriously who the fuck wrote this var/muzzled = is_muzzled() - + act = lowertext(act) switch(act) if("sign") if(!restrained()) diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm index b617a1fc883..dc7a66f7018 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/larva/emote.dm @@ -8,7 +8,7 @@ if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' act = copytext(act,1,length(act)) var/muzzled = is_muzzled() - + act = lowertext(act) switch(act) if ("me") if(silent) diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 6ad6a672b43..ec0791d9e09 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -44,14 +44,15 @@ user.drop_item() B.forceMove(src) held_brain = B - if(istype(O,/obj/item/organ/internal/brain/xeno)) // I'm not sure how well this will work now, since I don't think you can actually get xeno brains + if(istype(O,/obj/item/organ/internal/brain/xeno)) // kept the type check, as it still does other weird stuff name = "Man-Machine Interface: Alien - [brainmob.real_name]" icon = 'icons/mob/alien.dmi' icon_state = "AlienMMI" alien = 1 else name = "Man-Machine Interface: [brainmob.real_name]" - icon_state = "mmi_full" + icon = B.mmi_icon + icon_state = "[B.mmi_icon_state]" alien = 0 feedback_inc("cyborg_mmis_filled",1) diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index e10b3d257d3..92c04ca0066 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -15,6 +15,8 @@ parent_organ = "head" slot = "brain" vital = 1 + var/mmi_icon = 'icons/obj/assemblies.dmi' + var/mmi_icon_state = "mmi_full" /obj/item/organ/internal/brain/surgeryize() if(!owner) @@ -27,6 +29,8 @@ desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?" icon_state = "brain-x" origin_tech = "biotech=7" + mmi_icon = 'icons/mob/alien.dmi' + mmi_icon_state = "AlienMMI" /obj/item/organ/internal/brain/New() ..() @@ -107,6 +111,7 @@ desc = "A complex, organic knot of jelly and crystalline particles." icon = 'icons/mob/slimes.dmi' icon_state = "green slime extract" + mmi_icon_state = "slime_mmi" // parent_organ = "chest" Hello I am from the ministry of rubber forehead aliens how are you /obj/item/organ/brain/slime/take_damage(var/amount, var/silent = 1) diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm index fd2a4879c9d..16cf01e4266 100644 --- a/code/modules/mob/living/carbon/brain/emote.dm +++ b/code/modules/mob/living/carbon/brain/emote.dm @@ -11,6 +11,7 @@ if(src.stat == DEAD) return + act = lowertext(act) switch(act) if ("alarm") diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 70a1d635ff1..5a641a81689 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -746,6 +746,8 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, spintime -= speed /mob/living/carbon/resist_buckle() + spawn(0) + resist_muzzle() if(restrained()) changeNext_move(CLICK_CD_BREAKOUT) last_special = world.time + CLICK_CD_BREAKOUT @@ -776,6 +778,8 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/carbon/resist_restraints() + spawn(0) + resist_muzzle() var/obj/item/I = null if(handcuffed) I = handcuffed @@ -786,6 +790,21 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, last_special = world.time + CLICK_CD_BREAKOUT cuff_resist(I) +/mob/living/carbon/resist_muzzle() + if(!istype(wear_mask, /obj/item/clothing/mask/muzzle)) + return + var/obj/item/clothing/mask/muzzle/I = wear_mask + var/time = I.resist_time + if(I.resist_time == 0)//if it's 0, you can't get out of it + to_chat(src, "[I] is too well made, you'll need hands for this one!") + else + visible_message("[src] gnaws on [I], trying to remove it!") + to_chat(src, "You attempt to remove [I]... (This will take around [time/10] seconds and you need to stand still.)") + if(do_after(src, time, 0, target = src)) + visible_message("[src] removes [I]!") + to_chat(src, "You get rid of [I]!") + unEquip(I) + /mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0) breakouttime = I.breakouttime diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 8264db804fd..52488051f50 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -18,16 +18,17 @@ return 1 /mob/living/carbon/human/proc/change_gender(var/gender, var/update_dna = 1) + var/obj/item/organ/external/head/H = organs_by_name["head"] if(src.gender == gender) return src.gender = gender - var/datum/sprite_accessory/hair/current_hair = hair_styles_list[h_style] + var/datum/sprite_accessory/hair/current_hair = hair_styles_list[H.h_style] if(current_hair.gender != NEUTER && current_hair.gender != src.gender) reset_head_hair() - var/datum/sprite_accessory/hair/current_fhair = facial_hair_styles_list[f_style] + var/datum/sprite_accessory/hair/current_fhair = facial_hair_styles_list[H.f_style] if(current_fhair.gender != NEUTER && current_fhair.gender != src.gender) reset_facial_hair() @@ -38,59 +39,137 @@ return 1 /mob/living/carbon/human/proc/change_hair(var/hair_style) + var/obj/item/organ/external/head/H = get_organ("head") if(!hair_style) return - if(h_style == hair_style) + if(H.h_style == hair_style) return if(!(hair_style in hair_styles_list)) return - h_style = hair_style + H.h_style = hair_style update_hair() return 1 /mob/living/carbon/human/proc/change_facial_hair(var/facial_hair_style) + var/obj/item/organ/external/head/H = get_organ("head") if(!facial_hair_style) return - if(f_style == facial_hair_style) + if(H.f_style == facial_hair_style) return if(!(facial_hair_style in facial_hair_styles_list)) return - f_style = facial_hair_style + H.f_style = facial_hair_style update_fhair() return 1 +/mob/living/carbon/human/proc/change_head_accessory(var/head_accessory_style) + var/obj/item/organ/external/head/H = get_organ("head") + if(!head_accessory_style) + return + + if(H.ha_style == head_accessory_style) + return + + if(!(head_accessory_style in head_accessory_styles_list)) + return + + H.ha_style = head_accessory_style + + update_head_accessory() + return 1 + +/mob/living/carbon/human/proc/change_markings(var/marking_style) + if(!marking_style) + return + + if(src.m_style == marking_style) + return + + if(!(marking_style in marking_styles_list)) + return + + src.m_style = marking_style + + update_markings() + return 1 + +/mob/living/carbon/human/proc/change_body_accessory(var/body_accessory_style) + var/found + if(!body_accessory_style) + return + + if(src.body_accessory) + if(src.body_accessory.name == body_accessory_style) + return + + for(var/B in body_accessory_by_name) + if(B == body_accessory_style) + src.body_accessory = body_accessory_by_name[body_accessory_style] + found = 1 + + if(!found) + return + + update_tail_layer() + return 1 + /mob/living/carbon/human/proc/reset_hair() reset_head_hair() reset_facial_hair() + reset_head_accessory() + if(m_style && m_style != "None") //Resets the markings if they were head markings. + var/datum/sprite_accessory/marking_style = marking_styles_list[m_style] + if(marking_style && marking_style.marking_location == "head") + reset_markings() /mob/living/carbon/human/proc/reset_head_hair() + var/obj/item/organ/external/head/H = get_organ("head") var/list/valid_hairstyles = generate_valid_hairstyles() - if(valid_hairstyles.len) - h_style = pick(valid_hairstyles) + H.h_style = pick(valid_hairstyles) else //this shouldn't happen - h_style = "Bald" + H.h_style = "Bald" update_hair() /mob/living/carbon/human/proc/reset_facial_hair() + var/obj/item/organ/external/head/H = get_organ("head") var/list/valid_facial_hairstyles = generate_valid_facial_hairstyles() if(valid_facial_hairstyles.len) - f_style = pick(valid_facial_hairstyles) + H.f_style = pick(valid_facial_hairstyles) else //this shouldn't happen - f_style = "Shaved" + H.f_style = "Shaved" update_fhair() +/mob/living/carbon/human/proc/reset_markings() + var/list/valid_markings = generate_valid_markings() + if(valid_markings.len) + m_style = pick(valid_markings) + else + //this shouldn't happen + m_style = "None" + update_markings() + +/mob/living/carbon/human/proc/reset_head_accessory() + var/obj/item/organ/external/head/H = get_organ("head") + var/list/valid_head_accessories = generate_valid_head_accessories() + if(valid_head_accessories.len) + H.ha_style = pick(valid_head_accessories) + else + //this shouldn't happen + H.ha_style = "None" + update_head_accessory() + /mob/living/carbon/human/proc/change_eye_color(var/red, var/green, var/blue) if(red == r_eyes && green == g_eyes && blue == b_eyes) return @@ -104,27 +183,53 @@ return 1 /mob/living/carbon/human/proc/change_hair_color(var/red, var/green, var/blue) - if(red == r_eyes && green == g_eyes && blue == b_eyes) + var/obj/item/organ/external/head/H = get_organ("head") + if(red == H.r_hair && green == H.g_hair && blue == H.b_hair) return - r_hair = red - g_hair = green - b_hair = blue + H.r_hair = red + H.g_hair = green + H.b_hair = blue update_hair() return 1 /mob/living/carbon/human/proc/change_facial_hair_color(var/red, var/green, var/blue) - if(red == r_facial && green == g_facial && blue == b_facial) + var/obj/item/organ/external/head/H = get_organ("head") + if(red == H.r_facial && green == H.g_facial && blue == H.b_facial) return - r_facial = red - g_facial = green - b_facial = blue + H.r_facial = red + H.g_facial = green + H.b_facial = blue update_fhair() return 1 +/mob/living/carbon/human/proc/change_head_accessory_color(var/red, var/green, var/blue) + var/obj/item/organ/external/head/H = get_organ("head") + if(red == H.r_headacc && green == H.g_headacc && blue == H.b_headacc) + return + + H.r_headacc = red + H.g_headacc = green + H.b_headacc = blue + + update_head_accessory() + return 1 + +/mob/living/carbon/human/proc/change_marking_color(var/red, var/green, var/blue) + if(red == r_markings && green == g_markings && blue == b_markings) + return + + r_markings = red + g_markings = green + b_markings = blue + + update_markings() + return 1 + + /mob/living/carbon/human/proc/change_skin_color(var/red, var/green, var/blue) if(red == r_skin && green == g_skin && blue == b_skin || !(species.bodyflags & HAS_SKIN_COLOR)) return @@ -170,6 +275,7 @@ /mob/living/carbon/human/proc/generate_valid_hairstyles() var/list/valid_hairstyles = new() + var/obj/item/organ/external/head/H = get_organ("head") for(var/hairstyle in hair_styles_list) var/datum/sprite_accessory/S = hair_styles_list[hairstyle] @@ -177,12 +283,11 @@ continue if(gender == FEMALE && S.gender == MALE) continue - if(species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... - var/obj/item/organ/external/head/H = organs_by_name["head"] + if(H.species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/datum/robolimb/robohead = all_robolimbs[H.model] if(!H) return - if(species.name in S.species_allowed) //If this is a hairstyle native to the user's species... + if(H.species.name in S.species_allowed) //If this is a hairstyle native to the user's species... if(robohead.is_monitor && (robohead.company in S.models_allowed)) //Check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_hairstyles += hairstyle //Give them their hairstyles if they do. continue @@ -195,8 +300,8 @@ if("Human" in S.species_allowed) //If the user has a robotic head and the hairstyle can fit humans, let them use it as a wig for their humanoid robot head. valid_hairstyles += hairstyle continue - else - if(!(species.name in S.species_allowed)) //If the user is not a species who can have robotic heads, use the default handling. + else //If the user is not a species who can have robotic heads, use the default handling. + if(!(H.species.name in S.species_allowed)) //If the user's head is not of a species the hair style allows, skip it. Otherwise, add it to the list. continue valid_hairstyles += hairstyle @@ -204,6 +309,7 @@ /mob/living/carbon/human/proc/generate_valid_facial_hairstyles() var/list/valid_facial_hairstyles = new() + var/obj/item/organ/external/head/H = get_organ("head") for(var/facialhairstyle in facial_hair_styles_list) var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] @@ -211,12 +317,11 @@ continue if(gender == FEMALE && S.gender == MALE) continue - if(species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... - var/obj/item/organ/external/head/H = organs_by_name["head"] + if(H.species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/datum/robolimb/robohead = all_robolimbs[H.model] if(!H) continue // No head, no hair - if(species.name in S.species_allowed) //If this is a facial hair style native to the user's species... + if(H.species.name in S.species_allowed) //If this is a facial hair style native to the user's species... if(robohead.is_monitor && (robohead.company in S.models_allowed)) //Check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_facial_hairstyles += facialhairstyle //Give them their facial hair styles if they do. continue @@ -231,8 +336,52 @@ valid_facial_hairstyles += facialhairstyle continue else //If the user is not a species who can have robotic heads, use the default handling. - if(!(species.name in S.species_allowed)) + if(!(H.species.name in S.species_allowed)) //If the user's head is not of a species the facial hair style allows, skip it. Otherwise, add it to the list. continue valid_facial_hairstyles += facialhairstyle return valid_facial_hairstyles + +/mob/living/carbon/human/proc/generate_valid_head_accessories() + var/list/valid_head_accessories = new() + var/obj/item/organ/external/head/H = get_organ("head") + for(var/head_accessory in head_accessory_styles_list) + var/datum/sprite_accessory/S = head_accessory_styles_list[head_accessory] + + if(!(H.species.name in S.species_allowed)) //If the user's head is not of a species the head accessory style allows, skip it. Otherwise, add it to the list. + continue + valid_head_accessories += head_accessory + + return valid_head_accessories + +/mob/living/carbon/human/proc/generate_valid_markings() + var/list/valid_markings = new() + var/obj/item/organ/external/head/H = get_organ("head") + for(var/marking in marking_styles_list) + var/datum/sprite_accessory/S = marking_styles_list[marking] + + if(!(species.name in S.species_allowed)) //If the user's head is not of a species the marking style allows, skip it. Otherwise, add it to the list. + continue + if(H.species.flags & ALL_RPARTS) //If the user is a species that can have a robotic head... + var/datum/robolimb/robohead = all_robolimbs[H.model] + if(!(S.models_allowed && (robohead.company in S.models_allowed))) //Make sure they don't get markings incompatible with their head. + continue + valid_markings += marking + + return valid_markings + +/mob/living/carbon/human/proc/generate_valid_body_accessories() + var/list/valid_body_accessories = new() + for(var/B in body_accessory_by_name) + var/datum/body_accessory/A = body_accessory_by_name[B] + if(check_rights(R_ADMIN, 1, src)) + valid_body_accessories = body_accessory_by_name.Copy() + else + if(!istype(A)) + valid_body_accessories += "None" //The only null entry should be the "None" option. + continue + if(!(species.name in A.allowed_species)) //If the user is not of a species the body accessory style allows, skip it. Otherwise, add it to the list. + continue + valid_body_accessories += B + + return valid_body_accessories diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index aa31c912841..fce12362d73 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -145,12 +145,13 @@ return ..(gibbed) /mob/living/carbon/human/proc/makeSkeleton() + var/obj/item/organ/external/head/H = get_organ("head") if(SKELETON in src.mutations) return - if(f_style) - f_style = "Shaved" - if(h_style) - h_style = "Bald" + if(H.f_style) + H.f_style = "Shaved" + if(H.h_style) + H.h_style = "Bald" update_fhair(0) update_hair(0) @@ -162,12 +163,13 @@ return /mob/living/carbon/human/proc/ChangeToHusk() + var/obj/item/organ/external/head/H = organs_by_name["head"] if(HUSK in mutations) return - if(f_style) - f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE - if(h_style) - h_style = "Bald" + if(H.f_style) + H.f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE + if(H.h_style) + H.h_style = "Bald" update_fhair(0) update_hair(0) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 9f1b41b3ac5..eca554dcb0c 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -25,6 +25,7 @@ //Emote Cooldown System (it's so simple!) // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 + act = lowertext(act) switch(act) //Cooldown-inducing emotes if("ping", "pings", "buzz", "buzzes", "beep", "beeps", "yes", "no") @@ -32,6 +33,11 @@ on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm else //Everyone else fails, skip the emote attempt return + if("drone","drones","hum","hums","rumble","rumbles") + if (species.name == "Drask") //Only Drask can make whale noises + on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm + else + return if("squish", "squishes") var/found_slime_bodypart = 0 @@ -114,6 +120,23 @@ playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) m_type = 2 + if("drone", "drones", "hum", "hums", "rumble", "rumbles") + var/M = null + if(param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if(!M) + param = null + + if (param) + message = "[src] drones at [param]." + else + message = "[src] rumbles." + playsound(src.loc, 'sound/voice/DraskTalk.ogg', 50, 0) + m_type = 2 + if("squish", "squishes") var/M = null if(param) @@ -284,18 +307,28 @@ if (M == src) M = null - if (M) - if(src.lying || src.weakened) + if(M) + if(lying || weakened) message = "[src] flops and flails around on the floor." else message = "[src] flips in [M]'s general direction." - src.SpinAnimation(5,1) + SpinAnimation(5,1) else - if(src.lying || src.weakened) + if(lying || weakened) message = "[src] flops and flails around on the floor." else - message = "[src] does a flip!" - src.SpinAnimation(5,1) + var/obj/item/weapon/grab/G = get_active_hand() + if(G && G.affecting) + var/turf/oldloc = loc + var/turf/newloc = G.affecting.loc + if(isturf(oldloc) && isturf(newloc)) + SpinAnimation(5,1) + forceMove(newloc) + G.affecting.forceMove(oldloc) + message = "[src] flips over [G.affecting]!" + else + message = "[src] does a flip!" + SpinAnimation(5,1) if ("aflap", "aflaps") if (!src.restrained()) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 3e5cb90f380..1556211cb5b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -74,38 +74,30 @@ status_flags = GODMODE|CANPUSH /mob/living/carbon/human/skrell/New(var/new_loc) - h_style = "Skrell Male Tentacles" ..(new_loc, "Skrell") /mob/living/carbon/human/tajaran/New(var/new_loc) - ha_style = "Tajaran Ears" ..(new_loc, "Tajaran") /mob/living/carbon/human/vulpkanin/New(var/new_loc) - h_style = "Bald" ..(new_loc, "Vulpkanin") /mob/living/carbon/human/unathi/New(var/new_loc) - h_style = "Unathi Horns" ..(new_loc, "Unathi") /mob/living/carbon/human/vox/New(var/new_loc) - h_style = "Short Vox Quills" ..(new_loc, "Vox") /mob/living/carbon/human/voxarmalis/New(var/new_loc) - h_style = "Bald" ..(new_loc, "Vox Armalis") /mob/living/carbon/human/skeleton/New(var/new_loc) - h_style = "Bald" ..(new_loc, "Skeleton") /mob/living/carbon/human/kidan/New(var/new_loc) ..(new_loc, "Kidan") /mob/living/carbon/human/plasma/New(var/new_loc) - h_style = "Bald" ..(new_loc, "Plasmaman") /mob/living/carbon/human/slime/New(var/new_loc) @@ -121,31 +113,24 @@ ..(new_loc, "Human") /mob/living/carbon/human/diona/New(var/new_loc) - h_style = "Bald" ..(new_loc, "Diona") /mob/living/carbon/human/machine/New(var/new_loc) - h_style = "blue IPC screen" ..(new_loc, "Machine") /mob/living/carbon/human/shadow/New(var/new_loc) - h_style = "Bald" ..(new_loc, "Shadow") /mob/living/carbon/human/golem/New(var/new_loc) - h_style = "Bald" ..(new_loc, "Golem") /mob/living/carbon/human/wryn/New(var/new_loc) - h_style = "Antennae" ..(new_loc, "Wryn") /mob/living/carbon/human/nucleation/New(var/new_loc) - h_style = "Nucleation Crystals" ..(new_loc, "Nucleation") /mob/living/carbon/human/drask/New(var/new_loc) - h_style = "Bald" ..(new_loc, "Drask") /mob/living/carbon/human/monkey/New(var/new_loc) @@ -1505,6 +1490,15 @@ species.create_organs(src) + //Handle default hair/head accessories for created mobs. + var/obj/item/organ/external/head/H = get_organ("head") + if(species.default_hair) + H.h_style = species.default_hair + if(species.default_fhair) + H.f_style = species.default_fhair + if(species.default_headacc) + H.ha_style = species.default_headacc + if(!dna) dna = new /datum/dna(null) dna.species = species.name @@ -1601,9 +1595,8 @@ return if(species.flags & ALL_RPARTS) //If they can have a fully cybernetic body... - var/obj/item/organ/external/head/H = organs_by_name["head"] - var/datum/robolimb/robohead = all_robolimbs[H.model] - if(!H) + var/datum/robolimb/robohead = all_robolimbs[head_organ.model] + if(!head_organ) return if(!robohead.is_monitor) //If they've got a prosthetic head and it isn't a monitor, they've no screen to adjust. Instead, let them change the colour of their optics! var/optic_colour = input(src, "Select optic colour", rgb(r_markings, g_markings, b_markings)) as color|null @@ -1620,15 +1613,15 @@ var/list/hair = list() for(var/i in hair_styles_list) var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i] - if((species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. + if((head_organ.species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. hair += i - var/new_style = input(src, "Select a monitor display", "Monitor Display", h_style) as null|anything in hair + var/new_style = input(src, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair if(incapacitated()) to_chat(src, "You were interrupted while changing your monitor display.") return if(new_style) - h_style = new_style + head_organ.h_style = new_style update_hair() @@ -1930,3 +1923,6 @@ if(U.accessories) for(var/obj/item/clothing/accessory/A in U.accessories) . |= A.GetAccess() + +/mob/living/carbon/human/is_mechanical() + return ..() || (species.flags & ALL_RPARTS) != 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index e2ebed386b3..6f106f5e125 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -9,24 +9,6 @@ var/global/default_martial_art = new/datum/martial_art var/b_markings = 0 var/m_style = "None" - //Hair colour and style - var/r_hair = 0 - var/g_hair = 0 - var/b_hair = 0 - var/h_style = "Bald" - - //Head accessory colour and style - var/r_headacc = 0 - var/g_headacc = 0 - var/b_headacc = 0 - var/ha_style = "None" - - //Facial hair colour and style - var/r_facial = 0 - var/g_facial = 0 - var/b_facial = 0 - var/f_style = "Shaved" - //Eye colour var/r_eyes = 0 var/g_eyes = 0 diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 5278f0cc723..d44bfbbb27f 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -12,6 +12,8 @@ if(embedded_flag) handle_embedded_objects() //Moving with objects stuck in you can cause bad times. + if(slowed) + tally += 10 var/health_deficiency = (maxHealth - health + staminaloss) if(reagents) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 2ddcb3d0f15..f9d9ae27442 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -607,4 +607,4 @@ return 0 return 1 - return 0 //Unsupported slot \ No newline at end of file + return 0 //Unsupported slot diff --git a/code/modules/mob/living/carbon/human/species/abdcutor.dm b/code/modules/mob/living/carbon/human/species/abductor.dm similarity index 100% rename from code/modules/mob/living/carbon/human/species/abdcutor.dm rename to code/modules/mob/living/carbon/human/species/abductor.dm diff --git a/code/modules/mob/living/carbon/human/species/apollo.dm b/code/modules/mob/living/carbon/human/species/apollo.dm index a7735a00db9..5642eedbcbe 100644 --- a/code/modules/mob/living/carbon/human/species/apollo.dm +++ b/code/modules/mob/living/carbon/human/species/apollo.dm @@ -45,6 +45,8 @@ base_color = "#704300" flesh_color = "#704300" blood_color = "#FFFF99" + //Default styles for created mobs. + default_hair = "Antennae" /datum/species/wryn/handle_death(var/mob/living/carbon/human/H) @@ -54,6 +56,7 @@ to_chat(C, "It feels like part of you has died.") /datum/species/wryn/handle_attack_hand(var/mob/living/carbon/human/H, var/mob/living/carbon/human/M) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") if(M.a_intent == I_HARM) if(H.handcuffed) if(!H.get_int_organ(/obj/item/organ/internal/wryn/hivenode)) return @@ -71,7 +74,7 @@ to_chat(M, "You hear a loud crunch as you mercilessly pull off [H]'s antennae.") to_chat(H, "You hear a loud crunch as your antennae is ripped off your head by [M].") to_chat(H, "It's so quiet...") - H.h_style = "Bald" + head_organ.h_style = "Bald" H.update_hair() M.attack_log += text("\[[time_stamp()]\] removed antennae [H.name] ([H.ckey])") @@ -87,7 +90,7 @@ blurb = "A sub-race of unforunates who have been exposed to too much supermatter radiation. As a result, \ supermatter crystal clusters have begun to grow across their bodies. Research to find a cure for this ailment \ has been slow, and so this is a common fate for veteran engineers. The supermatter crystals produce oxygen, \ - negating the need for the individual to breath. Their massive change in biology, however, renders most medicines \ + negating the need for the individual to breathe. Their massive change in biology, however, renders most medicines \ obselete. Ionizing radiation seems to cause resonance in some of their crystals, which seems to encourage regeneration \ and produces a calming effect on the individual. Nucleations are highly stigmatized, and are treated much in the same \ way as lepers were back on Earth." @@ -97,6 +100,9 @@ flags = IS_WHITELISTED | NO_BREATHE | NO_BLOOD | NO_PAIN | HAS_LIPS | NO_SCAN dietflags = DIET_OMNI //still human at their core, so they maintain their eating habits and diet + //Default styles for created mobs. + default_hair = "Nucleation Crystals" + reagent_tag = PROCESS_ORG has_organ = list( "heart" = /obj/item/organ/internal/heart, diff --git a/code/modules/mob/living/carbon/human/species/drask.dm b/code/modules/mob/living/carbon/human/species/drask.dm index 87f2c287dbe..59789f533f6 100644 --- a/code/modules/mob/living/carbon/human/species/drask.dm +++ b/code/modules/mob/living/carbon/human/species/drask.dm @@ -52,6 +52,7 @@ reagent_tag = PROCESS_ORG base_color = "#a3d4eb" blood_color = "#a3d4eb" + butt_sprite = "drask" has_organ = list( "heart" = /obj/item/organ/internal/heart/drask, diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index f3e8793fed1..922810e758d 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -6,7 +6,7 @@ deform = 'icons/mob/human_races/r_golem.dmi' default_language = "Galactic Common" - flags = NO_BREATHE | NO_BLOOD | RADIMMUNE + flags = NO_BREATHE | NO_BLOOD | RADIMMUNE | NOGUNS virus_immune = 1 dietflags = DIET_OMNI //golems can eat anything because they are magic or something reagent_tag = PROCESS_ORG diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index 72972f98baf..dffc73d4e1d 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -34,8 +34,6 @@ brute_mod = 1.5 burn_mod = 1.5 - flags = IS_RESTRICTED - /datum/species/monkey/handle_npc(var/mob/living/carbon/human/H) if(H.stat != CONSCIOUS) return diff --git a/code/modules/mob/living/carbon/human/species/plasmaman.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm index d85da69017b..26ee19b0788 100644 --- a/code/modules/mob/living/carbon/human/species/plasmaman.dm +++ b/code/modules/mob/living/carbon/human/species/plasmaman.dm @@ -12,6 +12,8 @@ //default_mutations=list(SKELETON) // This screws things up + butt_sprite = "plasma" + breath_type = "plasma" heat_level_1 = 350 // Heat damage level 1 above this point. diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 8508d7aa5b8..599857390d2 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -16,6 +16,7 @@ var/eyes = "eyes_s" // Icon for eyes. var/blurb = "A completely nondescript species." // A brief lore summary for use in the chargen screen. + var/butt_sprite = "human" var/primitive_form // Lesser form, if any (ie. monkey for humans) var/greater_form // Greater form, if any, ie. human for monkeys. @@ -118,6 +119,11 @@ var/male_scream_sound = 'sound/goonstation/voice/male_scream.ogg' var/female_scream_sound = 'sound/goonstation/voice/female_scream.ogg' + //Default hair/headacc style vars. + var/default_hair = "Bald" //Default hair style for newly created humans unless otherwise set. + var/default_fhair = "Shaved" //Default facial hair style for newly created humans unless otherwise set. + var/default_headacc = "None" //Default head accessory style for newly created humans unless otherwise set. + // Determines the organs that the species spawns with and var/list/has_organ = list( // which required-organ checks are conducted. "heart" = /obj/item/organ/internal/heart, @@ -158,7 +164,6 @@ /datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. - for(var/obj/item/organ/internal/iorgan in H.internal_organs) if(iorgan in H.internal_organs) qdel(iorgan) diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index 26c6ddb0c57..00398c0f0fa 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -55,6 +55,9 @@ flesh_color = "#34AF10" reagent_tag = PROCESS_ORG base_color = "#066000" + //Default styles for created mobs. + default_hair = "Unathi Horns" + butt_sprite = "unathi" allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) @@ -104,11 +107,14 @@ flags = HAS_LIPS | CAN_BE_FAT clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = FEET_PADDED | HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING + bodyflags = FEET_PADDED | HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING | HAS_FUR dietflags = DIET_OMNI reagent_tag = PROCESS_ORG flesh_color = "#AFA59E" base_color = "#333333" + //Default styles for created mobs. + default_headacc = "Tajaran Ears" + butt_sprite = "tajaran" allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) @@ -148,11 +154,12 @@ flags = HAS_LIPS clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = FEET_PADDED | HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING + bodyflags = FEET_PADDED | HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING | HAS_FUR dietflags = DIET_OMNI reagent_tag = PROCESS_ORG flesh_color = "#966464" base_color = "#B43214" + butt_sprite = "vulp" allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) @@ -189,7 +196,20 @@ dietflags = DIET_HERB flesh_color = "#8CD7A3" blood_color = "#1D2CBF" + //Default styles for created mobs. + default_hair = "Skrell Male Tentacles" reagent_tag = PROCESS_ORG + butt_sprite = "skrell" + + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver/skrell, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes, + ) suicide_messages = list( "is attempting to bite their tongue off!", @@ -251,6 +271,9 @@ blood_color = "#2299FC" flesh_color = "#808D11" + //Default styles for created mobs. + default_hair = "Short Vox Quills" + butt_sprite = "vox" reagent_tag = PROCESS_ORG scream_verb = "shrieks" @@ -376,6 +399,7 @@ dietflags = DIET_HERB blood_color = "#FB9800" reagent_tag = PROCESS_ORG + butt_sprite = "kidan" allowed_consumed_mobs = list(/mob/living/simple_animal/diona) @@ -408,6 +432,7 @@ reagent_tag = PROCESS_ORG exotic_blood = "water" //ventcrawler = 1 //ventcrawling commented out + butt_sprite = "slime" has_organ = list( "brain" = /obj/item/organ/internal/brain/slime @@ -578,6 +603,7 @@ unarmed_type = /datum/unarmed_attack/punch darksight = 5 // BOOSTED from 2 eyes = "grey_eyes_s" + butt_sprite = "grey" brute_mod = 1.25 //greys are fragile @@ -642,6 +668,7 @@ body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not blood_color = "#004400" flesh_color = "#907E4A" + butt_sprite = "diona" reagent_tag = PROCESS_ORG @@ -656,17 +683,17 @@ vision_organ = /obj/item/organ/internal/diona_receptor has_limbs = list( - "chest" = list("path" = /obj/item/organ/external/diona/chest), - "groin" = list("path" = /obj/item/organ/external/diona/groin), - "head" = list("path" = /obj/item/organ/external/diona/head), - "l_arm" = list("path" = /obj/item/organ/external/diona/arm), - "r_arm" = list("path" = /obj/item/organ/external/diona/arm/right), - "l_leg" = list("path" = /obj/item/organ/external/diona/leg), - "r_leg" = list("path" = /obj/item/organ/external/diona/leg/right), - "l_hand" = list("path" = /obj/item/organ/external/diona/hand), - "r_hand" = list("path" = /obj/item/organ/external/diona/hand/right), - "l_foot" = list("path" = /obj/item/organ/external/diona/foot), - "r_foot" = list("path" = /obj/item/organ/external/diona/foot/right) + "chest" = list("path" = /obj/item/organ/external/chest/diona), + "groin" = list("path" = /obj/item/organ/external/groin/diona), + "head" = list("path" = /obj/item/organ/external/head/diona), + "l_arm" = list("path" = /obj/item/organ/external/arm/diona), + "r_arm" = list("path" = /obj/item/organ/external/arm/right/diona), + "l_leg" = list("path" = /obj/item/organ/external/leg/diona), + "r_leg" = list("path" = /obj/item/organ/external/leg/right/diona), + "l_hand" = list("path" = /obj/item/organ/external/hand/diona), + "r_hand" = list("path" = /obj/item/organ/external/hand/right/diona), + "l_foot" = list("path" = /obj/item/organ/external/foot/diona), + "r_foot" = list("path" = /obj/item/organ/external/foot/right/diona) ) suicide_messages = list( @@ -751,11 +778,14 @@ dietflags = 0 //IPCs can't eat, so no diet blood_color = "#1F181F" flesh_color = "#AAAAAA" + //Default styles for created mobs. + default_hair = "Blue IPC Screen" virus_immune = 1 can_revive_by_healing = 1 reagent_tag = PROCESS_SYN male_scream_sound = 'sound/goonstation/voice/robot_scream.ogg' female_scream_sound = 'sound/goonstation/voice/robot_scream.ogg' + butt_sprite = "machine" has_organ = list( "brain" = /obj/item/organ/internal/brain/mmi_holder/posibrain, @@ -791,6 +821,10 @@ ) /datum/species/machine/handle_death(var/mob/living/carbon/human/H) - H.h_style = "" + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + head_organ.h_style = "Bald" + head_organ.f_style = "Shaved" spawn(100) - if(H) H.update_hair() \ No newline at end of file + if(H) + H.update_hair() + H.update_fhair() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 85fff9e6ead..1b5f6c25735 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -393,13 +393,13 @@ var/global/list/damage_icon_parts = list() //base icons var/icon/head_accessory_standing = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") - if(ha_style && (src.species.bodyflags & HAS_HEAD_ACCESSORY)) - var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[ha_style] + if(head_organ.ha_style && (head_organ.species.bodyflags & HAS_HEAD_ACCESSORY)) + var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[head_organ.ha_style] if(head_accessory_style && head_accessory_style.species_allowed) - if(src.species.name in head_accessory_style.species_allowed) + if(head_organ.species.name in head_accessory_style.species_allowed) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) - head_accessory_s.Blend(rgb(r_headacc, g_headacc, b_headacc), ICON_ADD) + head_accessory_s.Blend(rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc), ICON_ADD) head_accessory_standing = head_accessory_s //head_accessory_standing.Blend(head_accessory_s, ICON_OVERLAY) //Having it this way preserves animations. Useful for animated antennae. else @@ -429,17 +429,17 @@ var/global/list/damage_icon_parts = list() var/icon/hair_standing = new /icon('icons/mob/human_face.dmi',"bald_s") //var/icon/debrained_s = new /icon("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s") - if(h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic()))) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic()))) + var/datum/sprite_accessory/hair_style = hair_styles_list[head_organ.h_style] //if(!src.get_int_organ(/obj/item/organ/internal/brain) && src.get_species() != "Machine" )//make it obvious we have NO BRAIN // hair_standing.Blend(debrained_s, ICON_OVERLAY) if(hair_style && hair_style.species_allowed) - if((src.species.name in hair_style.species_allowed) || (src.species.flags & ALL_RPARTS)) + if((head_organ.species.name in hair_style.species_allowed) || (head_organ.species.flags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(src.get_species() == "Slime People") // I am el worstos + if(head_organ.species.name == "Slime People") // I am el worstos hair_s.Blend(rgb(r_skin, g_skin, b_skin, 160), ICON_AND) else if(hair_style.do_colouration) - hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + hair_s.Blend(rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair), ICON_ADD) hair_standing = hair_s //hair_standing.Blend(hair_s, ICON_OVERLAY) //Having it this way preserves animations. Useful for IPC screens. @@ -470,15 +470,15 @@ var/global/list/damage_icon_parts = list() //base icons var/icon/face_standing = new /icon('icons/mob/human_face.dmi',"bald_s") - if(f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + if(head_organ.f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[head_organ.f_style] if(facial_hair_style && facial_hair_style.species_allowed) - if((src.species.name in facial_hair_style.species_allowed) || (src.species.flags & ALL_RPARTS)) + if((head_organ.species.name in facial_hair_style.species_allowed) || (head_organ.species.flags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(src.get_species() == "Slime People") // I am el worstos + if(head_organ.species.name == "Slime People") // I am el worstos facial_s.Blend(rgb(r_skin, g_skin, b_skin, 160), ICON_AND) else if(facial_hair_style.do_colouration) - facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + facial_s.Blend(rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial), ICON_ADD) face_standing.Blend(facial_s, ICON_OVERLAY) else //warning("Invalid f_style for [species.name]: [f_style]") @@ -1265,22 +1265,23 @@ var/global/list/damage_icon_parts = list() //gender no longer matters for the mouth, although there should probably be seperate base head icons. // var/g = "m" // if (gender == FEMALE) g = "f" - + var/obj/item/organ/external/head/H = get_organ("head") //base icons var/icon/face_lying = new /icon('icons/mob/human_face.dmi',"bald_l") - if(f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + + if(H.f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] if(facial_hair_style) var/icon/facial_l = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_l") - facial_l.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + facial_l.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) face_lying.Blend(facial_l, ICON_OVERLAY) - if(h_style) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(H.h_style) + var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] if(hair_style) var/icon/hair_l = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_l") - hair_l.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + hair_l.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) face_lying.Blend(hair_l, ICON_OVERLAY) //Eyes diff --git a/code/modules/mob/living/carbon/slime/emote.dm b/code/modules/mob/living/carbon/slime/emote.dm index 64838a1704d..8c290dc6094 100644 --- a/code/modules/mob/living/carbon/slime/emote.dm +++ b/code/modules/mob/living/carbon/slime/emote.dm @@ -7,6 +7,7 @@ if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' act = copytext(act,1,length(act)) + act = lowertext(act) switch(act) //Alphabetical please if ("me") if(silent) diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm index 08f5089a200..1ad57bd787d 100644 --- a/code/modules/mob/living/carbon/superheroes.dm +++ b/code/modules/mob/living/carbon/superheroes.dm @@ -148,6 +148,7 @@ /obj/effect/proc_holder/spell/targeted/recruit/cast(list/targets) for(var/mob/living/carbon/human/target in targets) + var/obj/item/organ/external/head/head_organ = target.get_organ("head") if(ticker.mode.greyshirts.len >= 3) to_chat(usr, "You have already recruited the maximum number of henchmen.") if(!in_range(usr, target)) @@ -210,8 +211,8 @@ to_chat(target, "You may not harm other Greyshirt or [usr]. However, you do not need to obey other Greyshirts.") ticker.mode.greyshirts += target.mind target.set_species("Human") - target.h_style = "Bald" - target.f_style = "Shaved" + head_organ.h_style = "Bald" + head_organ.f_style = "Shaved" target.s_tone = 35 target.r_eyes = 1 target.b_eyes = 1 diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 7e70e3a613f..c3c64c1c696 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -111,6 +111,7 @@ handle_slurring() handle_paralysed() handle_sleeping() + handle_slowed() /mob/living/proc/handle_stunned() @@ -160,7 +161,10 @@ clear_alert("asleep") return sleeping - +/mob/living/proc/handle_slowed() + if(slowed) + slowed = max(slowed-1, 0) + return slowed /mob/living/proc/handle_disabilities() //Eyes diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index bd0db4f3966..dbdb6ee0a7f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -358,12 +358,14 @@ SetParalysis(0) SetStunned(0) SetWeakened(0) + slowed = 0 losebreath = 0 dizziness = 0 jitteriness = 0 confused = 0 drowsyness = 0 radiation = 0 + druggy = 0 nutrition = 400 bodytemperature = 310 sdisabilities = 0 @@ -578,12 +580,19 @@ return /mob/living/proc/resist_buckle() + spawn(0) + resist_muzzle() buckled.user_unbuckle_mob(src,src) +/mob/living/proc/resist_muzzle() + return + /mob/living/proc/resist_fire() return /mob/living/proc/resist_restraints() + spawn(0) + resist_muzzle() return /*////////////////////// @@ -826,3 +835,11 @@ butcher_results.Remove(path) //In case you want to have things like simple_animals drop their butcher results on gib, so it won't double up below. visible_message("[user] butchers [src].") gib() + +/mob/living/movement_delay() + var/tally = 0 + + if(slowed) + tally += 10 + + return tally diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 2e130b8feab..d8ab75777d4 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -171,8 +171,13 @@ proc/get_radio_key_from_channel(var/channel) verb = say_quote(message, speaking) if(is_muzzled()) - to_chat(src, "You're muzzled and cannot speak!") - return + var/obj/item/clothing/mask/muzzle/G = wear_mask + if(G.mute) //if the mask is supposed to mute you completely or just muffle you + to_chat(src, "You're muzzled and cannot speak!") + return + else + message = muffledspeech(message) + verb = "mumbles" message = trim_left(message) @@ -361,7 +366,10 @@ proc/get_radio_key_from_channel(var/channel) return if(is_muzzled()) - to_chat(src, "You're muzzled and cannot speak!") + if(istype(wear_mask, /obj/item/clothing/mask/muzzle/tapegag)) //just for tape + to_chat(src, "Your mouth is taped and you cannot speak!") + else + to_chat(src, "You're muzzled and cannot speak!") return var/message_range = 1 diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 272834e0328..3346882a488 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -307,7 +307,7 @@ var/list/ai_verbs_default = list( //if(icon_state == initial(icon_state)) var/icontype = "" if (custom_sprite == 1) icontype = ("Custom")//automagically selects custom sprite if one is available - else icontype = input("Select an icon!", "AI", null, null) in list("Monochrome", "Blue", "Clown", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Static", "Triumvirate", "Triumvirate Static", "Red October", "Sparkles", "ANIMA", "President") + else icontype = input("Select an icon!", "AI", null, null) in list("Monochrome", "Blue", "Clown", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Static", "Triumvirate", "Triumvirate Static", "Red October", "Sparkles", "ANIMA", "President", "NT") switch(icontype) if("Custom") icon_state = "[src.ckey]-ai" if("Clown") icon_state = "ai-clown2" @@ -329,6 +329,7 @@ var/list/ai_verbs_default = list( if("Sparkles") icon_state = "ai-sparkles" if("ANIMA") icon_state = "ai-anima" if("President") icon_state = "ai-president" + if("NT") icon_state = "ai-nt" else icon_state = "ai" //else // to_chat(usr, "You can only change your display once!") diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index e4b7f983b9d..71d80df9e02 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -142,7 +142,7 @@ if(c.can_use()) cameras += c - for(var/turf/t in block(locate(x, y, z), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z))) + for(var/turf/t in block(locate(max(x, 1), max(y, 1), max(z, 1)), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z))) turfs[t] = t for(var/camera in cameras) diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm index c5c3603466e..c70979c5947 100644 --- a/code/modules/mob/living/silicon/emote.dm +++ b/code/modules/mob/living/silicon/emote.dm @@ -8,6 +8,7 @@ //Emote Cooldown System (it's so simple!) // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 + act = lowertext(act) switch(act) //Cooldown-inducing emotes if("scream", "screams") diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm index f9d75773ff9..6ad793fff88 100644 --- a/code/modules/mob/living/silicon/pai/death.dm +++ b/code/modules/mob/living/silicon/pai/death.dm @@ -1,15 +1,15 @@ /mob/living/silicon/pai/death(gibbed) - if(stat == DEAD) return - if(canmove || resting) - var/turf/T = get_turf_or_move(loc) - for (var/mob/M in viewers(T)) - M.show_message("\red [src] emits a dull beep before it loses power and collapses.", 3, "\red You hear a dull beep followed by the sound of glass crunching.", 2) - name = "pAI debris" - desc = "The unfortunate remains of some poor personal AI device." - icon_state = "[chassis]_dead" - else - card.overlays.Cut() - card.overlays += "pai-off" + if(stat == DEAD) + return + + force_fold_out() + + var/turf/T = get_turf_or_move(loc) + for (var/mob/M in viewers(T)) + M.show_message("\red [src] emits a dull beep before it loses power and collapses.", 3, "\red You hear a dull beep followed by the sound of glass crunching.", 2) + name = "pAI debris" + desc = "The unfortunate remains of some poor personal AI device." + icon_state = "[chassis]_dead" stat = DEAD canmove = 0 sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 4e1373e979b..635efadcaba 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -340,35 +340,37 @@ if(stat || sleeping || paralysis || weakened) return - if(src.loc != card) - to_chat(src, "\red You are already in your mobile form!") + if(loc != card) + to_chat(src, "You are already in your mobile form!") return if(world.time <= last_special) - to_chat(src, "\red You must wait before folding your chassis out again!") + to_chat(src, "You must wait before folding your chassis out again!") return last_special = world.time + 200 //I'm not sure how much of this is necessary, but I would rather avoid issues. - if(istype(card.loc,/mob)) + force_fold_out() + + visible_message("[src] folds outwards, expanding into a mobile form.", "You fold outwards, expanding into a mobile form.") + +/mob/living/silicon/pai/proc/force_fold_out() + if(istype(card.loc, /mob)) var/mob/holder = card.loc holder.unEquip(card) - else if(istype(card.loc,/obj/item/device/pda)) + else if(istype(card.loc, /obj/item/device/pda)) var/obj/item/device/pda/holder = card.loc holder.pai = null - - src.client.perspective = EYE_PERSPECTIVE - src.client.eye = src - src.forceMove(get_turf(card)) + if(client) + client.perspective = EYE_PERSPECTIVE + client.eye = src + forceMove(get_turf(card)) card.forceMove(src) card.screen_loc = null - var/turf/T = get_turf(src) - if(istype(T)) T.visible_message("[src] folds outwards, expanding into a mobile form.") - /mob/living/silicon/pai/verb/fold_up() set category = "pAI Commands" set name = "Collapse Chassis" @@ -376,12 +378,12 @@ if(stat || sleeping || paralysis || weakened) return - if(src.loc == card) - to_chat(src, "\red You are already in your card form!") + if(loc == card) + to_chat(src, "You are already in your card form!") return if(world.time <= last_special) - to_chat(src, "\red You must wait before returning to your card form!") + to_chat(src, "You must wait before returning to your card form!") return close_up() @@ -474,16 +476,15 @@ last_special = world.time + 200 resting = 0 - if(src.loc == card) + if(loc == card) return - var/turf/T = get_turf(src) - if(istype(T)) T.visible_message("[src] neatly folds inwards, compacting down to a rectangular card.") + visible_message("[src] neatly folds inwards, compacting down to a rectangular card.", "You neatly fold inwards, compacting down to a rectangular card.") - src.stop_pulling() - if(src.client) - src.client.perspective = EYE_PERSPECTIVE - src.client.eye = card + stop_pulling() + if(client) + client.perspective = EYE_PERSPECTIVE + client.eye = card // If we are being held, handle removing our holder from their inv. var/obj/item/weapon/holder/H = loc @@ -492,13 +493,13 @@ if(istype(M)) M.unEquip(H) H.loc = get_turf(src) - src.loc = get_turf(H) + loc = get_turf(H) // Move us into the card and move the card to the ground //This seems redundant but not including the forced loc setting messes the behavior up. - src.loc = card + loc = card card.loc = get_turf(card) - src.forceMove(card) + forceMove(card) card.forceMove(card.loc) icon_state = "[chassis]" diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 30273aec02c..36c61910e6d 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -8,6 +8,7 @@ //Emote Cooldown System (it's so simple!) // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 + act = lowertext(act) switch(act) //Cooldown-inducing emotes if("law","flip","flips","halt") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT. diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 5d88814440b..e6fc318335b 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -355,4 +355,7 @@ /mob/living/silicon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/noise) if(affect_silicon) - return ..() \ No newline at end of file + return ..() + +/mob/living/silicon/is_mechanical() + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 3c5206ba3a5..700b47da3f3 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -216,17 +216,10 @@ else to_chat(user, "[src] is in pristine condition.") -/mob/living/simple_animal/bot/adjustBruteLoss(amount) - . = ..() - +/mob/living/simple_animal/bot/adjustHealth(amount) if(amount > 0 && prob(10)) new /obj/effect/decal/cleanable/blood/oil(loc) - -/mob/living/simple_animal/bot/adjustFireLoss(amount) - . = ..() - - if(amount > 0 && prob(5)) - new /obj/effect/decal/cleanable/blood/oil(loc) + return ..(amount) /mob/living/simple_animal/bot/updatehealth() ..() @@ -346,9 +339,7 @@ return var/obj/item/weapon/weldingtool/WT = W if(WT.remove_fuel(0, user)) - adjustBruteLoss(-10) - adjustFireLoss(-10) - updatehealth() + adjustHealth(-10) add_fingerprint(user) user.visible_message("[user] repairs [src]!","You repair [src].") else @@ -1019,4 +1010,7 @@ Pass a positive integer as an argument to override a bot's default speed. if(260 to 300) throw_alert("temp", /obj/screen/alert/cold/robot, 1) else - throw_alert("temp", /obj/screen/alert/cold/robot, 2) \ No newline at end of file + throw_alert("temp", /obj/screen/alert/cold/robot, 2) + +/mob/living/simple_animal/bot/is_mechanical() + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/emote.dm b/code/modules/mob/living/simple_animal/bot/emote.dm index 4054e520ecf..0c8b591f069 100644 --- a/code/modules/mob/living/simple_animal/bot/emote.dm +++ b/code/modules/mob/living/simple_animal/bot/emote.dm @@ -11,6 +11,7 @@ //Emote Cooldown System (it's so simple!) // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 + act = lowertext(act) switch(act) //Cooldown-inducing emotes if("scream", "screams") diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index 3534bbf55b2..80bcbc679f0 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -492,7 +492,7 @@ if(reagent_id == "internal_beaker") if(use_beaker && reagent_glass && reagent_glass.reagents.total_volume) var/fraction = min(injection_amount/reagent_glass.reagents.total_volume, 1) - reagent_glass.reagents.reaction(patient, 2, fraction) + reagent_glass.reagents.reaction(patient, INGEST, fraction) reagent_glass.reagents.trans_to(patient, injection_amount) //Inject from beaker instead. else patient.reagents.add_reagent(reagent_id,injection_amount) diff --git a/code/modules/mob/living/simple_animal/friendly/diona.dm b/code/modules/mob/living/simple_animal/friendly/diona.dm index 4606558d271..f62176ee926 100644 --- a/code/modules/mob/living/simple_animal/friendly/diona.dm +++ b/code/modules/mob/living/simple_animal/friendly/diona.dm @@ -250,18 +250,19 @@ return /mob/living/simple_animal/diona/emote(var/act, var/m_type=1, var/message = null) - if(stat) + if(stat) return - + var/on_CD = 0 + act = lowertext(act) switch(act) if("chirp") - on_CD = handle_emote_CD() + on_CD = handle_emote_CD() else - on_CD = 0 + on_CD = 0 if(on_CD == 1) - return + return switch(act) //IMPORTANT: Emotes MUST NOT CONFLICT anywhere along the chain. if("chirp") diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index fdf597b005e..346a04e7851 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -21,6 +21,7 @@ attacktext = "kicks" attack_sound = 'sound/weapons/punch1.ogg' health = 40 + maxHealth = 40 melee_damage_lower = 1 melee_damage_upper = 2 stop_automated_movement_when_pulled = 1 @@ -109,6 +110,7 @@ attacktext = "kicks" attack_sound = 'sound/weapons/punch1.ogg' health = 50 + maxHealth = 50 var/milk_content = 0 can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY @@ -172,7 +174,8 @@ response_disarm = "gently pushes aside the" response_harm = "kicks the" attacktext = "kicks" - health = 1 + health = 3 + maxHealth = 3 ventcrawler = 2 var/amount_grown = 0 pass_flags = PASSTABLE | PASSGRILLE | PASSMOB @@ -216,6 +219,7 @@ var/global/chicken_count = 0 response_harm = "kicks the" attacktext = "kicks" health = 10 + maxHealth = 10 var/eggsleft = 0 var/chicken_color pass_flags = PASSTABLE | PASSMOB @@ -299,6 +303,7 @@ var/global/chicken_count = 0 response_harm = "kicks the" attacktext = "kicks" health = 50 + maxHealth = 50 can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY @@ -321,6 +326,7 @@ var/global/chicken_count = 0 response_harm = "kicks the" attacktext = "pecks" health = 50 + maxHealth = 50 can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY @@ -343,6 +349,7 @@ var/global/chicken_count = 0 response_harm = "kicks the" attacktext = "kicks" health = 50 + maxHealth = 50 can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY @@ -365,6 +372,7 @@ var/global/chicken_count = 0 response_harm = "kicks the" attacktext = "kicks" health = 50 + maxHealth = 50 can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY @@ -387,5 +395,6 @@ var/global/chicken_count = 0 response_harm = "kicks the" attacktext = "kicks" health = 50 + maxHealth = 50 can_collar = 1 gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index e536ac303bb..56f63ee99be 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -38,6 +38,7 @@ icon_living = "aliend_running" icon_dead = "aliend_l" health = 60 + maxHealth = 60 melee_damage_lower = 15 melee_damage_upper = 15 var/plant_cooldown = 30 @@ -59,6 +60,7 @@ icon_living = "aliens_running" icon_dead = "aliens_l" health = 120 + maxHealth = 120 melee_damage_lower = 15 melee_damage_upper = 15 ranged = 1 diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index 5a2ef732eb5..54b0d10608a 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -42,33 +42,23 @@ var/datum/reagent/beegent = null //hehe, beegent var/obj/structure/beebox/beehome = null - var/idle = 0 var/isqueen = FALSE + var/idle = 0 var/icon_base = "bee" var/static/list/bee_icons = list() - /mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0) return 1 - /mob/living/simple_animal/hostile/poison/bees/New() ..() generate_bee_visuals() - /mob/living/simple_animal/hostile/poison/bees/Destroy() - if(beehome) - beehome.bees.Remove(src) - beehome = null beegent = null return ..() - /mob/living/simple_animal/hostile/poison/bees/death(gibbed) - if(beehome) - beehome.bees.Remove(src) - beehome = null beegent = null ..() ghostize() @@ -77,10 +67,6 @@ /mob/living/simple_animal/hostile/poison/bees/examine(mob/user) ..() - if(!beehome) - to_chat(user, "This bee is homeless!") - - /mob/living/simple_animal/hostile/poison/bees/proc/generate_bee_visuals() overlays.Cut() @@ -107,31 +93,87 @@ wings = bee_icons["[icon_base]_wings"] overlays += wings - //We don't attack beekeepers/people dressed as bees//Todo: bee costume /mob/living/simple_animal/hostile/poison/bees/CanAttack(atom/the_target) . = ..() - if(!.) - return 0 - if(ishuman(the_target)) - var/mob/living/carbon/human/H = the_target - return !H.bee_friendly() - + return . /mob/living/simple_animal/hostile/poison/bees/Found(atom/A) + if(isliving(A)) + var/mob/living/L = A + return !L.bee_friendly() + return 0 + +/mob/living/simple_animal/hostile/poison/bees/AttackingTarget() + if(beegent && isliving(target)) + var/mob/living/L = target + if(!isnull(target.reagents)) + beegent.reaction_mob(L, INGEST) + L.reagents.add_reagent(beegent.id, rand(1,5)) + target.attack_animal(src) + +/mob/living/simple_animal/hostile/poison/bees/proc/assign_reagent(datum/reagent/R) + if(istype(R)) + beegent = R + name = "[initial(name)] ([R.name])" + generate_bee_visuals() + +/mob/living/simple_animal/hostile/poison/bees/handle_automated_action() + . = ..() + if(!.) + return + +/mob/living/simple_animal/hostile/poison/bees/proc/reagent_incompatible(mob/living/simple_animal/hostile/poison/bees/B) + if(!B) + return 0 + if(B.beegent && beegent && B.beegent.id != beegent.id || B.beegent && !beegent || !B.beegent && beegent) + return 1 + return 0 + + + + +//Botany Worker Bees +/mob/living/simple_animal/hostile/poison/bees/worker + //Blank type define in case we need to give them special stuff later, plus organization (currently they are same as base type bee) + + +/mob/living/simple_animal/hostile/poison/bees/worker/Destroy() + if(beehome) + beehome.bees.Remove(src) + beehome = null + ..() + +/mob/living/simple_animal/hostile/poison/bees/worker/death(gibbed) + if(beehome) + beehome.bees.Remove(src) + beehome = null + ..() + +/mob/living/simple_animal/hostile/poison/bees/worker/examine(mob/user) + ..() + + if(!beehome) + to_chat(user, "This bee is homeless!") + +/mob/living/simple_animal/hostile/poison/bees/worker/Found(atom/A) if(istype(A, /obj/machinery/portable_atmospherics/hydroponics)) var/obj/machinery/portable_atmospherics/hydroponics/Hydro = A if(Hydro.seed && !Hydro.dead && !Hydro.recent_bee_visit) wanted_objects |= /obj/machinery/portable_atmospherics/hydroponics //so we only hunt them while they're alive/seeded/not visisted return 1 - if(ishuman(A)) - var/mob/living/carbon/human/H = A - return !H.bee_friendly() - return 0 + ..() +/mob/living/simple_animal/hostile/poison/bees/worker/CanAttack(atom/the_target) + . = ..() + if(!.) + return 0 + if(isliving(the_target)) //Should ignore ghosts and camera mobs already, but just in case + var/mob/living/L = the_target + return !L.bee_friendly() -/mob/living/simple_animal/hostile/poison/bees/AttackingTarget() - //Pollinate +/mob/living/simple_animal/hostile/poison/bees/worker/AttackingTarget() + //Pollinate if(istype(target, /obj/machinery/portable_atmospherics/hydroponics)) var/obj/machinery/portable_atmospherics/hydroponics/Hydro = target pollinate(Hydro) @@ -141,22 +183,9 @@ target = null wanted_objects.Remove(/obj/structure/beebox) //so we don't attack beeboxes when not going home else - if(beegent && isliving(target)) - var/mob/living/L = target - if(!isnull(target.reagents)) - beegent.reaction_mob(L, INGEST) - L.reagents.add_reagent(beegent.id, rand(1,5)) - target.attack_animal(src) + ..() - -/mob/living/simple_animal/hostile/poison/bees/proc/assign_reagent(datum/reagent/R) - if(istype(R)) - beegent = R - name = "[initial(name)] ([R.name])" - generate_bee_visuals() - - -/mob/living/simple_animal/hostile/poison/bees/proc/pollinate(obj/machinery/portable_atmospherics/hydroponics/Hydro) +/mob/living/simple_animal/hostile/poison/bees/worker/proc/pollinate(obj/machinery/portable_atmospherics/hydroponics/Hydro) if(!istype(Hydro) || !Hydro.seed || Hydro.dead || Hydro.recent_bee_visit) target = null return @@ -187,12 +216,10 @@ if(beehome) beehome.bee_resources = min(beehome.bee_resources + growth, 100) - -/mob/living/simple_animal/hostile/poison/bees/handle_automated_action() +/mob/living/simple_animal/hostile/poison/bees/worker/handle_automated_action() . = ..() if(!.) return - if(!isqueen) if(loc == beehome) idle = min(100, ++idle) @@ -212,7 +239,9 @@ beehome = BB - /mob/living/simple_animal/hostile/poison/bees/queen + +//Botany Queen Bee +/mob/living/simple_animal/hostile/poison/bees/queen name = "queen bee" desc = "she's the queen of bees, BZZ BZZ" icon_base = "queen" @@ -223,28 +252,13 @@ /mob/living/simple_animal/hostile/poison/bees/queen/Found(atom/A) return 0 - -//leave pollination for the peasent bees -/mob/living/simple_animal/hostile/poison/bees/queen/AttackingTarget() - if(beegent && isliving(target)) - var/mob/living/L = target - beegent.reaction_mob(L, TOUCH) - L.reagents.add_reagent(beegent.id, rand(1,5)) - target.attack_animal(src) - - -//PEASENT BEES -/mob/living/simple_animal/hostile/poison/bees/queen/pollinate() - return - - -/mob/living/simple_animal/hostile/poison/bees/proc/reagent_incompatible(mob/living/simple_animal/hostile/poison/bees/B) - if(!B) +/mob/living/simple_animal/hostile/poison/bees/queen/CanAttack(atom/the_target) + . = ..() + if(!.) return 0 - if(B.beegent && beegent && B.beegent.id != beegent.id || B.beegent && !beegent || !B.beegent && beegent) - return 1 - return 0 - + if(isliving(the_target)) //Should ignore ghosts and camera mobs already, but just in case + var/mob/living/L = the_target + return !L.bee_friendly() /obj/item/queen_bee name = "queen bee" @@ -254,7 +268,6 @@ icon = 'icons/mob/bees.dmi' var/mob/living/simple_animal/hostile/poison/bees/queen/queen - /obj/item/queen_bee/attackby(obj/item/I, mob/user, params) if(istype(I,/obj/item/weapon/reagent_containers/syringe)) var/obj/item/weapon/reagent_containers/syringe/S = I @@ -280,7 +293,6 @@ to_chat(user, "You don't have enough units of that chemical to modify the bee's DNA!") ..() - /obj/item/queen_bee/bought/New() ..() queen = new(src) @@ -288,3 +300,43 @@ /obj/item/queen_bee/Destroy() qdel(queen) return ..() + + + +//Syndicate Bees +/mob/living/simple_animal/hostile/poison/bees/syndi + name = "syndi-bee" + desc = "The result of a large influx of BEES!" + melee_damage_lower = 5 + melee_damage_upper = 5 + maxHealth = 25 + health = 25 + faction = list("hostile", "syndicate") + search_objects = 0 //these bees don't care about trivial things like plants, especially when there is havoc to sow + beegent = new /datum/reagent/facid() //prepare to die + var/list/master_and_friends = list() + +/mob/living/simple_animal/hostile/poison/bees/syndi/assign_reagent(datum/reagent/R) + return + +/mob/living/simple_animal/hostile/poison/bees/syndi/Found(atom/A) + return CanAttack(A) + +/mob/living/simple_animal/hostile/poison/bees/syndi/CanAttack(atom/the_target) + . = ..() + if(!.) + return 0 + if(isliving(the_target)) + var/mob/living/L = the_target + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(H in master_and_friends) + return 0 + return 1 + +/mob/living/simple_animal/hostile/poison/bees/syndi/AttackingTarget() + ..() + if(target && isliving(target)) + var/mob/living/L = target + if(L.stat) + LoseTarget() diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm index c5a656c8c66..4412dc77829 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm @@ -41,6 +41,7 @@ name = "Strong Hivebot" desc = "A robot, this one is armed and looks tough!" health = 80 + maxHealth = 80 ranged = 1 /mob/living/simple_animal/hostile/hivebot/death() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 757b72f3809..b1627d17af0 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -186,7 +186,7 @@ /mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay, var/minimum_distance) walk_to(src, target, minimum_distance, delay) -/mob/living/simple_animal/hostile/adjustBruteLoss(var/damage) +/mob/living/simple_animal/hostile/adjustHealth(damage) ..(damage) if(!stat && search_objects < 3)//Not unconscious, and we don't ignore mobs if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 7cff96385e1..e5ee97a70ef 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -99,7 +99,7 @@ visible_message("[src] starts to move!") attempt_open = 1 -/mob/living/simple_animal/hostile/mimic/crate/adjustBruteLoss(var/damage) +/mob/living/simple_animal/hostile/mimic/crate/adjustHealth(damage) trigger() ..(damage) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm index 5145a7c6a60..5a9f4a433af 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -204,7 +204,7 @@ Reward() ..() -/mob/living/simple_animal/hostile/asteroid/goldgrub/adjustBruteLoss(var/damage) +/mob/living/simple_animal/hostile/asteroid/goldgrub/adjustHealth(damage) idle_vision_range = 9 ..() @@ -403,7 +403,7 @@ pre_attack = 0 return -/mob/living/simple_animal/hostile/asteroid/goliath/adjustBruteLoss(var/damage) +/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(damage) ranged_cooldown-- handle_preattack() ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index 82a7f09af80..e6dda5e301c 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -59,7 +59,7 @@ health = maxHealth ..() -/mob/living/simple_animal/hostile/mushroom/adjustBruteLoss(var/damage)//Possibility to flee from a fight just to make it more visually interesting +/mob/living/simple_animal/hostile/mushroom/adjustHealth(damage)//Possibility to flee from a fight just to make it more visually interesting if(!retreat_distance && prob(33)) retreat_distance = 5 spawn(30) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm index b9f04ec68ee..cd34c8a6491 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -61,7 +61,7 @@ H.enemies |= enemies return 0 -/mob/living/simple_animal/hostile/retaliate/adjustBruteLoss(var/damage) +/mob/living/simple_animal/hostile/retaliate/adjustHealth(damage) ..(damage) Retaliate() diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 4d6688aa75b..0ce0cc71a86 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -71,7 +71,7 @@ if(!Proj) return if(prob(65)) if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - src.health -= Proj.damage + adjustHealth(Proj.damage) else visible_message("\red [src] blocks [Proj] with its shield!") return 0 diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 23477c2fc18..9a638ce3a80 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -269,8 +269,9 @@ return /mob/living/simple_animal/emote(var/act, var/m_type=1, var/message = null) - if(stat) return - + if(stat) + return + act = lowertext(act) switch(act) //IMPORTANT: Emotes MUST NOT CONFLICT anywhere along the chain. if("scream") message = "\The [src] whimpers." @@ -404,22 +405,18 @@ if(health < maxHealth) if(MED.amount >= 1) if(MED.heal_brute >= 1) - adjustBruteLoss(-MED.heal_brute) - MED.amount -= 1 - if(MED.amount <= 0) - qdel(MED) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\blue [user] applies [MED] on [src]") + heal_organ_damage((MED.heal_brute * 1.66), (MED.heal_burn * 1.66)) + MED.use(1) + visible_message("[user] applies [MED] on [src]") return else - to_chat(user, "\blue [MED] won't help at all.") + to_chat(user, "[MED] won't help at all.") return else - to_chat(user, "\blue [src] is at full health.") + to_chat(user, "[src] is at full health.") return else - to_chat(user, "\blue [src] is dead, medical items won't bring it back to life.") + to_chat(user, "[src] is dead, medical items won't bring it back to life.") return else if(can_collar && !collar && istype(O, /obj/item/clothing/accessory/petcollar)) var/obj/item/clothing/accessory/petcollar/C = O @@ -492,25 +489,31 @@ if(3.0) adjustBruteLoss(30) +/mob/living/simple_animal/proc/adjustHealth(amount) + if(status_flags & GODMODE) + return 0 + bruteloss = Clamp(bruteloss + amount, 0, maxHealth) + handle_regular_status_updates() + /mob/living/simple_animal/adjustBruteLoss(amount) if(damage_coeff[BRUTE]) - return ..(amount * damage_coeff[BRUTE]) + adjustHealth(amount * damage_coeff[BRUTE]) /mob/living/simple_animal/adjustFireLoss(amount) if(damage_coeff[BURN]) - return ..(amount * damage_coeff[BURN]) + adjustHealth(amount * damage_coeff[BURN]) /mob/living/simple_animal/adjustOxyLoss(amount) if(damage_coeff[OXY]) - return ..(amount * damage_coeff[OXY]) + adjustHealth(amount * damage_coeff[OXY]) /mob/living/simple_animal/adjustToxLoss(amount) if(damage_coeff[TOX]) - return ..(amount * damage_coeff[TOX]) + adjustHealth(amount * damage_coeff[TOX]) /mob/living/simple_animal/adjustCloneLoss(amount) if(damage_coeff[CLONE]) - return ..(amount * damage_coeff[CLONE]) + adjustHealth(amount * damage_coeff[CLONE]) /mob/living/simple_animal/adjustStaminaLoss(amount) if(damage_coeff[STAMINA]) @@ -665,7 +668,7 @@ if(!can_collar || collar) return var/obj/item/clothing/accessory/petcollar/C = usr.get_active_hand() - if(!C) + if(!istype(C)) usr.visible_message("[usr] rubs [src]'s neck.","You rub [src]'s neck for a moment.") return usr.drop_item() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e5661f10ea5..872350d6d9e 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -903,13 +903,8 @@ var/list/slot_equipment_priority = list( \ /mob/proc/can_use_hands() return -/mob/proc/is_active() - return (0 >= usr.stat) - /mob/proc/is_mechanical() - if(mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI")) - return 1 - return istype(src, /mob/living/silicon) || get_species() == "Machine" + return mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI") /mob/proc/is_ready() return client && !!mind @@ -936,19 +931,9 @@ var/list/slot_equipment_priority = list( \ /mob/proc/get_gender() return gender -/mob/proc/see(message) - if(!is_active()) - return 0 - to_chat(src, message) - return 1 - /mob/proc/is_muzzled() return 0 -/mob/proc/show_viewers(message) - for(var/mob/M in viewers()) - M.see(message) - /mob/Stat() ..() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index e84aab56d17..7f5e2e31248 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -98,6 +98,7 @@ var/paralysis = 0.0 var/stunned = 0.0 var/weakened = 0.0 + var/slowed = 0 var/losebreath = 0.0//Carbon var/intent = null//Living var/shakecamera = 0 diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index ffb6f6c13b8..c427f6e7a50 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -88,13 +88,17 @@ stat("Time To Start:", "DELAYED") if(ticker.current_state == GAME_STATE_PREGAME) - stat("Players: [totalPlayers]", "Players Ready: [totalPlayersReady]") + stat("Players:", "[totalPlayers]") + if(client.holder) + stat("Players Ready:", "[totalPlayersReady]") totalPlayers = 0 totalPlayersReady = 0 for(var/mob/new_player/player in player_list) - stat("[player.key]", (player.ready)?("(Playing)"):(null)) + if(client.holder) + stat("[player.key]", (player.ready)?("(Playing)"):(null)) totalPlayers++ - if(player.ready)totalPlayersReady++ + if(player.ready) + totalPlayersReady++ /mob/new_player/Topic(href, href_list[]) if(!client) return 0 diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index e0fbfcdf91b..93797b5bb17 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -886,12 +886,12 @@ species_allowed = list("Vox") vox_quills_fluff - name = "Fluffy Quills" + name = "Fluffy Vox Quills" icon_state = "vox_afro" species_allowed = list("Vox") vox_quills_mohawk - name = "Quill Mohawk" + name = "Vox Quill Mohawk" icon_state = "vox_mohawk" species_allowed = list("Vox") @@ -910,6 +910,11 @@ icon_state = "vox_nights" species_allowed = list("Vox") + vox_razor + name = "Vox Razorback" + icon_state = "vox_razor" + species_allowed = list("Vox") + // Apollo-specific //Wryn antennae @@ -1893,22 +1898,22 @@ icon_state = "markings_tiger" /datum/sprite_accessory/body_markings/tigerhead - name = "Tiger Body + Head" + name = "Tiger Body and Head" species_allowed = list("Unathi", "Tajaran", "Vulpkanin") icon_state = "markings_tigerhead" /datum/sprite_accessory/body_markings/tigerheadface_taj - name = "Tajaran Tiger Body + Head + Face" + name = "Tajaran Tiger Body, Head and Face" species_allowed = list("Tajaran") icon_state = "markings_tigerheadface_taj" /datum/sprite_accessory/body_markings/tigerheadface_vulp - name = "Vulpkanin Tiger Body + Head + Face" + name = "Vulpkanin Tiger Body, Head and Face" species_allowed = list("Vulpkanin") icon_state = "markings_tigerheadface_vulp" /datum/sprite_accessory/body_markings/tigerheadface_una - name = "Unathi Tiger Body + Head + Face" + name = "Unathi Tiger Body, Head and Face" species_allowed = list("Unathi") icon_state = "markings_tigerheadface_una" diff --git a/code/modules/mob/spirit/spirit.dm b/code/modules/mob/spirit/spirit.dm index 12bf5b5a45d..f7229a69e1f 100644 --- a/code/modules/mob/spirit/spirit.dm +++ b/code/modules/mob/spirit/spirit.dm @@ -25,7 +25,7 @@ mob/spirit var/follow_target = null -mob/spirit/is_active() +mob/spirit/proc/is_active() if (client && client.inactivity <= 10 * 60 * 10) return TRUE return FALSE diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 900e7c36efc..015de466161 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -268,6 +268,35 @@ qdel(src) + +/mob/living/carbon/human/proc/paize(var/name) + if(notransform) + return + for(var/obj/item/W in src) + unEquip(W) + regenerate_icons() + notransform = 1 + canmove = 0 + icon = null + invisibility = 101 + for(var/t in organs) //this really should not be necessary + qdel(t) + + var/obj/item/device/paicard/card = new(loc) + var/mob/living/silicon/pai/pai = new(card) + pai.key = key + card.setPersonality(pai) + + pai.name = name + pai.real_name = name + card.name = name + + to_chat(pai, "You have become a pAI! Your name is [pai.name].") + pai.update_pipe_vision() + spawn(0)//To prevent the proc from returning null. + qdel(src) + return + /mob/proc/safe_respawn(var/MP) if(!MP) return 0 diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index 606dcade9c9..583b68b3dc6 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -2,9 +2,13 @@ name = "Appearance Editor" var/flags = APPEARANCE_ALL_HAIR var/mob/living/carbon/human/owner = null + var/obj/item/organ/external/head/head_organ = null var/list/valid_species = list() var/list/valid_hairstyles = list() var/list/valid_facial_hairstyles = list() + var/list/valid_head_accessories = list() + var/list/valid_marking_styles = list() + var/list/valid_body_accessories = list() var/check_whitelist var/list/whitelist @@ -13,6 +17,7 @@ /datum/nano_module/appearance_changer/New(var/location, var/mob/living/carbon/human/H, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list()) ..() owner = H + head_organ = owner.get_organ("head") src.check_whitelist = check_species_whitelist src.whitelist = species_whitelist src.blacklist = species_blacklist @@ -54,7 +59,7 @@ return 1 if(href_list["hair_color"]) if(can_change(APPEARANCE_HAIR_COLOR)) - var/new_hair = input("Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair)) as color|null + var/new_hair = input("Please select hair color.", "Hair Color", rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair)) as color|null if(new_hair && can_still_topic(state)) var/r_hair = hex2num(copytext(new_hair, 2, 4)) var/g_hair = hex2num(copytext(new_hair, 4, 6)) @@ -69,7 +74,7 @@ return 1 if(href_list["facial_hair_color"]) if(can_change(APPEARANCE_FACIAL_HAIR_COLOR)) - var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial)) as color|null + var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial)) as color|null if(new_facial && can_still_topic(state)) var/r_facial = hex2num(copytext(new_facial, 2, 4)) var/g_facial = hex2num(copytext(new_facial, 4, 6)) @@ -87,6 +92,41 @@ if(owner.change_eye_color(r_eyes, g_eyes, b_eyes)) update_dna() return 1 + if(href_list["head_accessory"]) + if(can_change_head_accessory() && (href_list["head_accessory"] in valid_head_accessories)) + if(owner.change_head_accessory(href_list["head_accessory"])) + update_dna() + return 1 + if(href_list["head_accessory_color"]) + if(can_change_head_accessory()) + var/new_head_accessory = input("Please select head accessory color.", "Head Accessory Color", rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc)) as color|null + if(new_head_accessory && can_still_topic(state)) + var/r_headacc = hex2num(copytext(new_head_accessory, 2, 4)) + var/g_headacc = hex2num(copytext(new_head_accessory, 4, 6)) + var/b_headacc = hex2num(copytext(new_head_accessory, 6, 8)) + if(owner.change_head_accessory_color(r_headacc, g_headacc, b_headacc)) + update_dna() + return 1 + if(href_list["marking"]) + if(can_change_markings() && (href_list["marking"] in valid_marking_styles)) + if(owner.change_markings(href_list["marking"])) + update_dna() + return 1 + if(href_list["marking_color"]) + if(can_change_markings()) + var/new_markings = input("Please select marking color.", "Marking Color", rgb(owner.r_markings, owner.g_markings, owner.b_markings)) as color|null + if(new_markings && can_still_topic(state)) + var/r_markings = hex2num(copytext(new_markings, 2, 4)) + var/g_markings = hex2num(copytext(new_markings, 4, 6)) + var/b_markings = hex2num(copytext(new_markings, 6, 8)) + if(owner.change_marking_color(r_markings, g_markings, b_markings)) + update_dna() + return 1 + if(href_list["body_accessory"]) + if(can_change_body_accessory() && (href_list["body_accessory"] in valid_body_accessories)) + if(owner.change_body_accessory(href_list["body_accessory"])) + update_dna() + return 1 return 0 @@ -107,13 +147,21 @@ data["change_skin_tone"] = can_change_skin_tone() data["change_skin_color"] = can_change_skin_color() data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR) + data["change_head_accessory"] = can_change_head_accessory() + if(data["change_head_accessory"]) + var/head_accessory_styles[0] + for(var/head_accessory_style in valid_head_accessories) + head_accessory_styles[++head_accessory_styles.len] = list("headaccessorystyle" = head_accessory_style) + data["head_accessory_styles"] = head_accessory_styles + data["head_accessory_style"] = head_organ.ha_style + data["change_hair"] = can_change(APPEARANCE_HAIR) if(data["change_hair"]) var/hair_styles[0] for(var/hair_style in valid_hairstyles) hair_styles[++hair_styles.len] = list("hairstyle" = hair_style) data["hair_styles"] = hair_styles - data["hair_style"] = owner.h_style + data["hair_style"] = head_organ.h_style data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR) if(data["change_facial_hair"]) @@ -121,10 +169,31 @@ for(var/facial_hair_style in valid_facial_hairstyles) facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_style) data["facial_hair_styles"] = facial_hair_styles - data["facial_hair_style"] = owner.f_style + data["facial_hair_style"] = head_organ.f_style + data["change_markings"] = can_change_markings() + if(data["change_markings"]) + var/marking_styles[0] + for(var/marking_style in valid_marking_styles) + marking_styles[++marking_styles.len] = list("markingstyle" = marking_style) + data["marking_styles"] = marking_styles + data["marking_style"] = owner.m_style + + data["change_body_accessory"] = can_change_body_accessory() + if(data["change_body_accessory"]) + var/body_accessory_styles[0] + for(var/body_accessory_style in valid_body_accessories) + body_accessory_styles[++body_accessory_styles.len] = list("bodyaccessorystyle" = body_accessory_style) + data["body_accessory_styles"] = body_accessory_styles + var/datum/body_accessory/BA + if(owner.body_accessory) + BA = owner.body_accessory.name + data["body_accessory_style"] = BA + + data["change_head_accessory_color"] = can_change_head_accessory() data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR) data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR) + data["change_marking_color"] = can_change_markings() ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "appearance_changer.tmpl", "[src]", 800, 450, state = state) @@ -145,10 +214,22 @@ /datum/nano_module/appearance_changer/proc/can_change_skin_color() return owner && (flags & APPEARANCE_SKIN) && (owner.species.bodyflags & HAS_SKIN_COLOR) +/datum/nano_module/appearance_changer/proc/can_change_head_accessory() + return owner && (flags & APPEARANCE_HEAD_ACCESSORY) && (head_organ.species.bodyflags & HAS_HEAD_ACCESSORY) + +/datum/nano_module/appearance_changer/proc/can_change_markings() + return owner && (flags & APPEARANCE_MARKINGS) && (owner.species.bodyflags & HAS_MARKINGS) + +/datum/nano_module/appearance_changer/proc/can_change_body_accessory() + return owner && (flags & APPEARANCE_BODY_ACCESSORY) && (owner.species.bodyflags & HAS_TAIL) + /datum/nano_module/appearance_changer/proc/cut_and_generate_data() // Making the assumption that the available species remain constant + valid_hairstyles.Cut() valid_facial_hairstyles.Cut() - valid_facial_hairstyles.Cut() + valid_head_accessories.Cut() + valid_marking_styles.Cut() + valid_body_accessories.Cut() generate_data() /datum/nano_module/appearance_changer/proc/generate_data() @@ -158,4 +239,10 @@ valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist) if(!valid_hairstyles.len || !valid_facial_hairstyles.len) valid_hairstyles = owner.generate_valid_hairstyles() - valid_facial_hairstyles = owner.generate_valid_facial_hairstyles() \ No newline at end of file + valid_facial_hairstyles = owner.generate_valid_facial_hairstyles() + if(!valid_head_accessories.len) + valid_head_accessories = owner.generate_valid_head_accessories() + if(!valid_marking_styles.len) + valid_marking_styles = owner.generate_valid_markings() + if(!valid_body_accessories.len) + valid_body_accessories = owner.generate_valid_body_accessories() diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 9cf13e22f1d..d4a2ad141cb 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -226,45 +226,18 @@ /obj/machinery/photocopier/proc/copyass() var/icon/temp_img - if(check_ass()) //You have to be sitting on the copier and either be a xeno or a human without clothes on. - if(ishuman(ass)) //Suit checks are in check_ass - var/mob/living/carbon/human/H = ass - switch(H.get_species()) - if("Human") - temp_img = icon('icons/obj/butts.dmi', "human") - if("Tajaran") - temp_img = icon('icons/obj/butts.dmi', "tajaran") - if("Unathi") - temp_img = icon('icons/obj/butts.dmi', "unathi") - if("Skrell") - temp_img = icon('icons/obj/butts.dmi', "skrell") - if("Vox") - temp_img = icon('icons/obj/butts.dmi', "vox") - if("Kidan") - temp_img = icon('icons/obj/butts.dmi', "kidan") - if("Grey") - temp_img = icon('icons/obj/butts.dmi', "grey") - if("Diona") - temp_img = icon('icons/obj/butts.dmi', "diona") - if("Slime People") - temp_img = icon('icons/obj/butts.dmi', "slime") - if("Vulpkanin") - temp_img = icon('icons/obj/butts.dmi', "vulp") - if("Machine") - temp_img = icon('icons/obj/butts.dmi', "machine") - if("Plasmaman") - temp_img = icon('icons/obj/butts.dmi', "plasma") - if("Drask") - temp_img = icon('icons/obj/butts.dmi', "drask") - else - temp_img = icon('icons/obj/butts.dmi', "human") - else if(istype(ass,/mob/living/silicon/robot/drone)) - temp_img = icon('icons/obj/butts.dmi', "drone") - else if(istype(ass,/mob/living/simple_animal/diona)) - temp_img = icon('icons/obj/butts.dmi', "nymph") - else if(isalien(ass) || istype(ass,/mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro. - temp_img = icon('icons/obj/butts.dmi', "xeno") - else return + if(!check_ass()) //You have to be sitting on the copier and either be a xeno or a human without clothes on. + return + + if(ishuman(ass)) //Suit checks are in check_ass + var/mob/living/carbon/human/H = ass + temp_img = icon('icons/obj/butts.dmi', H.species.butt_sprite) + else if(istype(ass,/mob/living/silicon/robot/drone)) + temp_img = icon('icons/obj/butts.dmi', "drone") + else if(istype(ass,/mob/living/simple_animal/diona)) + temp_img = icon('icons/obj/butts.dmi', "nymph") + else if(isalien(ass) || istype(ass,/mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro. + temp_img = icon('icons/obj/butts.dmi', "xeno") else return var/obj/item/weapon/photo/p = new /obj/item/weapon/photo (loc) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 07a908bb6d1..8208635f577 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -25,6 +25,7 @@ By design, d1 is the smallest direction and d2 is the highest /obj/structure/cable level = 1 anchored =1 + on_blueprints = TRUE var/datum/powernet/powernet name = "power cable" desc = "A flexible superconducting cable for heavy-duty power transfer" diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index 81af0089e6f..0f19ce0990e 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -17,6 +17,7 @@ var/image/overlay_image + var/power_multiplier = 1 // This is so admins can tweak how good it is to find a good balance for effort -> power var/powercap = 500000 //Not a hard cap, but outputs above this have a 10% chance to cause the TeG to lose half it's power. /obj/machinery/power/generator/New() @@ -81,7 +82,7 @@ var/efficiency = 0.65 var/energy_transfer = delta_temperature*air2_heat_capacity*air1_heat_capacity/(air2_heat_capacity+air1_heat_capacity) var/heat = energy_transfer*(1-efficiency) - lastgen = energy_transfer*efficiency*0.05 + lastgen = energy_transfer*efficiency*0.05*power_multiplier if(air2.temperature > air1.temperature) air2.temperature = air2.temperature - energy_transfer/air2_heat_capacity @@ -97,8 +98,10 @@ circ2.air2.merge(air2) //Update the gas networks - circ1.parent2.update = 1 - circ2.parent2.update = 1 + if(circ1.parent2) + circ1.parent2.update = 1 + if(circ2.parent2) + circ2.parent2.update = 1 // update icon overlays and power usage only if displayed level has changed if(lastgen > powercap && prob(10)) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 9cce0b5fa9d..0df18d27150 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -433,83 +433,59 @@ if(status == LIGHT_EMPTY) to_chat(user, "There is no [fitting] in this light.") return - if(user.a_intent == "help") - if(on) - to_chat(user, "This light [fitting] feels hot!") - else - to_chat(user, "The light [fitting] feels cold.") - return - - if(user.a_intent == "disarm" || user.a_intent == "grab") //trying to grab the bulb // make it burn hands if not wearing fire-insulated gloves - if(on) - var/prot = 0 - var/mob/living/carbon/human/H = user + if(on) + var/prot = 0 + var/mob/living/carbon/human/H = user - if(istype(H)) + if(istype(H)) + if(H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + if(G.max_heat_protection_temperature) + prot = (G.max_heat_protection_temperature > 360) + else + prot = 1 - if(H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - if(G.max_heat_protection_temperature) - prot = (G.max_heat_protection_temperature > 360) - else - prot = 1 - - if(prot > 0 || (RESIST_HEAT in user.mutations)) - to_chat(user, "You remove the light [fitting]") - else if(TK in user.mutations) - to_chat(user, "You telekinetically remove the light [fitting].") - else + if(prot > 0 || (RESIST_HEAT in user.mutations)) + to_chat(user, "You remove the light [fitting]") + else if(TK in user.mutations) + to_chat(user, "You telekinetically remove the light [fitting].") + else + if(user.a_intent == I_DISARM || user.a_intent == I_GRAB) to_chat(user, "You try to remove the light [fitting], but you burn your hand on it!") var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand") if(affecting.take_damage( 0, 5 )) // 5 burn damage H.UpdateDamageIcon() H.updatehealth() - return // if burned, don't remove the light - else - to_chat(user, "You remove the light [fitting].") + return + else + to_chat(user, "You try to remove the light [fitting], but it's too hot to touch!") + return + else + to_chat(user, "You remove the light [fitting].") - // create a light tube/bulb item and put it in the user's hand - var/obj/item/weapon/light/L = new light_type() - L.status = status - L.rigged = rigged - L.brightness_range = brightness_range - L.brightness_power = brightness_power - L.brightness_color = brightness_color + // create a light tube/bulb item and put it in the user's hand + var/obj/item/weapon/light/L = new light_type() + L.status = status + L.rigged = rigged + L.brightness_range = brightness_range + L.brightness_power = brightness_power + L.brightness_color = brightness_color // light item inherits the switchcount, then zero it - L.switchcount = switchcount - switchcount = 0 + L.switchcount = switchcount + switchcount = 0 - L.update() - L.add_fingerprint(user) + L.update() + L.add_fingerprint(user) - user.put_in_active_hand(L) //puts it in our active hand - - status = LIGHT_EMPTY - update() - - if(user.a_intent == "harm") //hitting the bulb - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - if(prob(10)) //10% chance to break a light with bare hands - to_chat(user, "You hit the light, and it smashes!") - for(var/mob/M in viewers(src)) - if(M == user) - continue - M.show_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2) - if(on) - electrocute_mob(user, get_area(src), src, 0.3) - broken() - else - user.visible_message("[user.name] hits the light.") - playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) - - return + user.put_in_active_hand(L) //puts it in our active hand + status = LIGHT_EMPTY + update() // break the light and make sparks if was on diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 91502e270a6..7aa54d3429b 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -10,6 +10,7 @@ name = null icon = 'icons/obj/power.dmi' anchored = 1.0 + on_blueprints = TRUE var/datum/powernet/powernet = null use_power = 0 idle_power_usage = 0 diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index a4858a4a8c8..cb4f21d2497 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -134,11 +134,8 @@ return if(ishuman(user)) var/mob/living/carbon/human/H = user - if(H.get_species() == "Golem") - to_chat(user, "Your metal fingers don't fit in the trigger guard!") - return - if(H.get_species() == "Shadowling") - to_chat(user, "The muzzle flash would cause damage to your form!") + if(H.species.flags & NOGUNS) + to_chat(user, "Your fingers don't fit in the trigger guard!") return if(H.martial_art && H.martial_art.name == "The Sleeping Carp") //great dishonor to famiry to_chat(user, "Use of ranged weaponry would bring dishonor to the clan.") diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 1b2e9a0b3d4..9be9ea9c124 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -387,45 +387,48 @@ var/const/INGEST = 2 can_process = 1 return can_process -/datum/reagents/proc/reaction(var/atom/A, var/method=TOUCH, var/volume_modifier=0) - +/datum/reagents/proc/reaction(atom/A, method=TOUCH, volume_modifier = 1) switch(method) if(TOUCH) for(var/datum/reagent/R in reagent_list) if(ismob(A)) - spawn(0) - if(!R) return - var/check = reaction_check(A, R) - if(!check) - continue - else - R.reaction_mob(A, TOUCH, R.volume+volume_modifier) + if(!R) + return + var/check = reaction_check(A, R) + if(!check) + continue + else + R.reaction_mob(A, TOUCH, R.volume*volume_modifier) if(isturf(A)) - spawn(0) - if(!R) return - else R.reaction_turf(A, R.volume+volume_modifier) + if(!R) + return + else + R.reaction_turf(A, R.volume*volume_modifier) if(isobj(A)) - spawn(0) - if(!R) return - else R.reaction_obj(A, R.volume+volume_modifier) + if(!R) + return + else + R.reaction_obj(A, R.volume*volume_modifier) if(INGEST) for(var/datum/reagent/R in reagent_list) if(ismob(A) && R) - spawn(0) - if(!R) return - var/check = reaction_check(A, R) - if(!check) - continue - else - R.reaction_mob(A, INGEST, R.volume+volume_modifier) + if(!R) + return + var/check = reaction_check(A, R) + if(!check) + continue + else + R.reaction_mob(A, INGEST, R.volume*volume_modifier) if(isturf(A) && R) - spawn(0) - if(!R) return - else R.reaction_turf(A, R.volume+volume_modifier) + if(!R) + return + else + R.reaction_turf(A, R.volume*volume_modifier) if(isobj(A) && R) - spawn(0) - if(!R) return - else R.reaction_obj(A, R.volume+volume_modifier) + if(!R) + return + else + R.reaction_obj(A, R.volume*volume_modifier) return /datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null) // Like add_reagent but you can enter a list. Format it like this: list("toxin" = 10, "beer" = 15) diff --git a/code/modules/reagents/newchem/disease.dm b/code/modules/reagents/newchem/disease.dm index be1672434e4..aa0a2db6ae0 100644 --- a/code/modules/reagents/newchem/disease.dm +++ b/code/modules/reagents/newchem/disease.dm @@ -63,8 +63,8 @@ ..() /datum/reagent/salmonella - name = "Salmonella " - id = "salmonella " + name = "Salmonella" + id = "salmonella" description = "A nasty bacteria found in spoiled food." reagent_state = LIQUID color = "#1E4600" @@ -74,6 +74,63 @@ M.ForceContractDisease(new /datum/disease/food_poisoning(0)) ..() +/datum/reagent/gibbis + name = "Gibbis" + id = "gibbis" + description = "Liquid gibbis." + reagent_state = LIQUID + color = "#FF0000" + +/datum/reagent/gibbis/on_mob_life(var/mob/living/carbon/M as mob) + if(!M) M = holder.my_atom + if(volume > 2.5) + M.ForceContractDisease(new /datum/disease/gbs/curable(0)) + ..() + +/datum/reagent/prions + name = "Prions" + id = "prions" + description = "A disease-causing agent that is neither bacterial nor fungal nor viral and contains no genetic material." + reagent_state = LIQUID + color = "#FFFFFF" + +/datum/reagent/prions/on_mob_life(var/mob/living/carbon/M as mob) + if(!M) M = holder.my_atom + if(volume > 4.5) + M.ForceContractDisease(new /datum/disease/kuru(0)) + ..() + +/datum/reagent/grave_dust + name = "Grave Dust" + id = "grave_dust" + description = "Moldy old dust taken from a grave site." + reagent_state = LIQUID + color = "#465046" + +/datum/reagent/grave_dust/on_mob_life(var/mob/living/carbon/M as mob) + if(!M) M = holder.my_atom + if(volume > 4.5) + M.ForceContractDisease(new /datum/disease/vampire(0)) + ..() + +/datum/reagent/heartworms + name = "Space heartworms" + id = "heartworms" + description = "Aww, gross! These things can't be good for your heart. They're gunna eat it!" + reagent_state = SOLID + color = "#925D6C" + +/datum/reagent/heartworms/on_mob_life(var/mob/living/carbon/M as mob) + if(!M) M = holder.my_atom + if(volume > 4.5) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/internal/heart/ate_heart = H.get_int_organ(/obj/item/organ/internal/heart) + if(ate_heart) + ate_heart.remove(H) + qdel(ate_heart) + ..() + /datum/reagent/spore name = "Blob Spores" id = "spore" diff --git a/code/modules/reagents/newchem/drinks.dm b/code/modules/reagents/newchem/drinks.dm index 323bb24e832..01920c617c3 100644 --- a/code/modules/reagents/newchem/drinks.dm +++ b/code/modules/reagents/newchem/drinks.dm @@ -67,6 +67,56 @@ mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' +/datum/reagent/ethanol/dragons_breath + name = "Dragon's Breath" + id = "dragonsbreath" + description = "Possessing this stuff probably breaks the Geneva convention." + reagent_state = LIQUID + color = "#DC0000" + alcohol_perc = 1 + +/datum/reagent/ethanol/dragons_breath/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume) + if(method == INGEST && prob(20)) + if(M.on_fire) + M.adjust_fire_stacks(3) + +/datum/reagent/ethanol/dragons_breath/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(M.reagents.has_reagent("milk")) + to_chat(M, "The milk stops the burning. Ahhh.") + M.reagents.del_reagent("milk") + M.reagents.del_reagent("dragonsbreath") + return + if(prob(8)) + to_chat(M, "Oh god! Oh GODD!!") + if(prob(50)) + to_chat(M, "Your throat burns terribly!") + M.emote(pick("scream","cry","choke","gasp")) + M.Stun(1) + if(prob(8)) + to_chat(M, "Why!? WHY!?") + if(prob(8)) + to_chat(M, "ARGHHHH!") + if(prob(2 * volume)) + to_chat(M, "OH GOD OH GOD PLEASE NO!!") + if(M.on_fire) + M.adjust_fire_stacks(5) + if(prob(50)) + to_chat(M, "IT BURNS!!!!") + M.visible_message("[M] is consumed in flames!") + M.dust() + return + ..() + +/datum/chemical_reaction/dragons_breath + name = "Dragon's Breath" + id = "dragonsbreath" + result = "dragonsbreath" + required_reagents = list("whiskey" = 1, "phlogiston" = 1, "pyrosium" = 1, "fuel" = 1, "ghostchilijuice"= 1) + result_amount = 1 + mix_message = "A tiny mushroom cloud erupts from the container. That's not worrying at all!" + mix_sound = 'sound/effects/meteorimpact.ogg' + // ROBOT ALCOHOL PAST THIS POINT // WOOO! diff --git a/code/modules/reagents/newchem/drugs.dm b/code/modules/reagents/newchem/drugs.dm index 127a37593d1..62daeee99a3 100644 --- a/code/modules/reagents/newchem/drugs.dm +++ b/code/modules/reagents/newchem/drugs.dm @@ -337,9 +337,10 @@ var/check = rand(0,100) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(check < 8 && H.h_style != "Very Long Beard") - H.h_style = "Very Long Hair" - H.f_style = "Very Long Beard" + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(check < 8 && head_organ.h_style != "Very Long Beard") + head_organ.h_style = "Very Long Hair" + head_organ.f_style = "Very Long Beard" H.update_hair() H.update_fhair() H.visible_message("[H] has a wild look in their eyes!") diff --git a/code/modules/reagents/newchem/food.dm b/code/modules/reagents/newchem/food.dm index e86ed8a2b11..e8b5ed3f681 100644 --- a/code/modules/reagents/newchem/food.dm +++ b/code/modules/reagents/newchem/food.dm @@ -601,3 +601,44 @@ datum/reagent/pepperoni/reaction_mob(var/mob/living/M, var/method=TOUCH, var/vol if(!H.heart_attack) H.heart_attack = 1 ..() + +/datum/reagent/ghost_chili_juice + name = "Ghost chili juice" + id = "ghostchilijuice" + description = "Juice from the universe's hottest chilli. Do not consume." + reagent_state = LIQUID + color = "#FF7F32" + +/datum/reagent/ghost_chili_juice/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + if(M.reagents.has_reagent("milk")) + to_chat(M, "The milk stops the burning. Ahhh.") + M.reagents.del_reagent("milk") + M.reagents.del_reagent("ghostchilijuice") + return + if(prob(8)) + to_chat(M, "Oh god! Oh GODD!!") + if(prob(50)) + to_chat(M, "Your throat burns furiously!") + M.emote(pick("scream","cry","choke","gasp")) + M.Stun(1) + if(prob(8)) + to_chat(M, "Why!? WHY!?") + if(prob(8)) + to_chat(M, "ARGHHHH!") + if(prob(33)) + M.visible_message("[M] suddenly and violently vomits!") + M.fakevomit(no_text = 1) + to_chat(M, "Thank goodness. You're not sure how long you could have held out with heat that intense!") + M.reagents.del_reagent("ghostchilijuice") + return + if(prob(10)) + to_chat(M, "OH GOD OH GOD PLEASE NO!!") + if(M.on_fire) + M.adjust_fire_stacks(5) + if(prob(50)) + to_chat(M, "IT BURNS!!!!") + M.visible_message("[M] is consumed in flames!") + M.dust() + return + ..() \ No newline at end of file diff --git a/code/modules/reagents/newchem/medicine.dm b/code/modules/reagents/newchem/medicine.dm index bc319a9b6bd..aca5897735c 100644 --- a/code/modules/reagents/newchem/medicine.dm +++ b/code/modules/reagents/newchem/medicine.dm @@ -800,6 +800,7 @@ datum/reagent/stimulants/on_mob_life(var/mob/living/M as mob) M.adjustBruteLoss(-10*REM) M.adjustFireLoss(-10*REM) M.setStaminaLoss(0) + M.slowed = 0 M.dizziness = max(0,M.dizziness-10) M.drowsyness = max(0,M.drowsyness-10) M.confused = 0 diff --git a/code/modules/reagents/newchem/other.dm b/code/modules/reagents/newchem/other.dm index c26d8bbe983..1e31ba5b506 100644 --- a/code/modules/reagents/newchem/other.dm +++ b/code/modules/reagents/newchem/other.dm @@ -198,12 +198,13 @@ datum/reagent/hair_dye datum/reagent/hair_dye/reaction_mob(var/mob/living/M, var/volume) if(M && ishuman(M)) var/mob/living/carbon/human/H = M - H.r_facial = rand(0,255) - H.g_facial = rand(0,255) - H.b_facial = rand(0,255) - H.r_hair = rand(0,255) - H.g_hair = rand(0,255) - H.b_hair = rand(0,255) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + head_organ.r_facial = rand(0,255) + head_organ.g_facial = rand(0,255) + head_organ.b_facial = rand(0,255) + head_organ.r_hair = rand(0,255) + head_organ.g_hair = rand(0,255) + head_organ.b_hair = rand(0,255) H.update_hair() H.update_fhair() ..() @@ -228,8 +229,9 @@ datum/reagent/hairgrownium datum/reagent/hairgrownium/reaction_mob(var/mob/living/M, var/volume) if(M && ishuman(M)) var/mob/living/carbon/human/H = M - H.h_style = random_hair_style(H.gender, H.species) - H.f_style = random_facial_hair_style(H.gender, H.species) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + head_organ.h_style = random_hair_style(H.gender, head_organ.species.name) + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.species.name) H.update_hair() H.update_fhair() ..() @@ -252,12 +254,21 @@ datum/reagent/super_hairgrownium result_amount = 3 mix_message = "The liquid becomes amazingly furry and smells peculiar." -datum/reagent/super_hairgrownium/on_mob_life(var/mob/living/M as mob) - if(!M) M = holder.my_atom +datum/reagent/super_hairgrownium/reaction_mob(var/mob/living/M, var/volume) if(M && ishuman(M)) var/mob/living/carbon/human/H = M - H.h_style = "Very Long Hair" - H.f_style = "Very Long Beard" + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + var/datum/sprite_accessory/tmp_hair_style = hair_styles_list["Very Long Hair"] + var/datum/sprite_accessory/tmp_facial_hair_style = facial_hair_styles_list["Very Long Beard"] + + if(head_organ.species.name in tmp_hair_style.species_allowed) //If 'Very Long Hair' is a style the person's species can have, give it to them. + head_organ.h_style = "Very Long Hair" + else //Otherwise, give them a random hair style. + head_organ.h_style = random_hair_style(H.gender, head_organ.species.name) + if(head_organ.species.name in tmp_facial_hair_style.species_allowed) //If 'Very Long Beard' is a style the person's species can have, give it to them. + head_organ.f_style = "Very Long Beard" + else //Otherwise, give them a random facial hair style. + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.species.name) H.update_hair() H.update_fhair() if(!H.wear_mask || H.wear_mask && !istype(H.wear_mask, /obj/item/clothing/mask/fakemoustache)) @@ -351,6 +362,52 @@ datum/reagent/fartonium/on_mob_life(var/mob/living/M as mob) required_reagents = list("sodium" = 1, "hydrogen" = 1, "oxygen" = 1) result_amount = 3 +/datum/reagent/hugs + name = "Pure hugs" + id = "hugs" + description = "Hugs, in liquid form. Yes, the concept of a hug. As a liquid. This makes sense in the future." + reagent_state = LIQUID + color = "#FF97B9" + +/datum/reagent/love + name = "Pure love" + id = "love" + description = "What is this emotion you humans call \"love?\" Oh, it's this? This is it? Huh, well okay then, thanks." + reagent_state = LIQUID + color = "#FF83A5" + +/datum/reagent/love/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume) + to_chat(M, "You feel loved!") + +/datum/reagent/love/on_mob_life(var/mob/living/M as mob) + if(!M) M = holder.my_atom + + if(M.a_intent == I_HARM) + M.a_intent = I_HELP + + if(prob(8)) + var/lovely_phrase = pick("appreciated", "loved", "pretty good", "really nice", "pretty happy with yourself, even though things haven't always gone as well as they could") + to_chat(M, "You feel [lovely_phrase].") + + else if(!M.restrained()) + for(var/mob/living/carbon/C in orange(1, M)) + if(C) + if(C == M) + continue + if(!C.stat) + M.visible_message("[M] gives [C] a [pick("hug","warm embrace")].") + playsound(get_turf(M), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + break + ..() + +/datum/chemical_reaction/love + name = "pure love" + id = "love" + result = "love" + required_reagents = list("hugs" = 1, "chocolate" = 1) + result_amount = 2 + mix_message = "The substance gives off a lovely scent!" + ///Alchemical Reagents datum/reagent/eyenewt diff --git a/code/modules/reagents/newchem/pyro.dm b/code/modules/reagents/newchem/pyro.dm index b4070440ab3..655b8e996eb 100644 --- a/code/modules/reagents/newchem/pyro.dm +++ b/code/modules/reagents/newchem/pyro.dm @@ -293,7 +293,7 @@ datum/reagent/blackpowder/reaction_turf(var/turf/T, var/volume) //oh shit required_reagents = list("potassium" = 1, "sugar" = 1, "phosphorus" = 1) result_amount = 1 mix_message = "The mixture quickly turns into a pall of smoke!" - var/forbidden_reagents = list("sugar", "phosphorus", "potassium") //Do not transfer this stuff through smoke. + var/forbidden_reagents = list("sugar", "phosphorus", "potassium", "stimulants") //Do not transfer this stuff through smoke. /datum/chemical_reaction/smoke/on_reaction(var/datum/reagents/holder, var/created_volume) for(var/f_reagent in forbidden_reagents) @@ -325,7 +325,7 @@ datum/reagent/blackpowder/reaction_turf(var/turf/T, var/volume) //oh shit min_temp = 374 secondary = 1 result_amount = 1 - forbidden_reagents = list() + forbidden_reagents = list("stimulants") mix_sound = null /datum/reagent/sonic_powder diff --git a/code/modules/reagents/newchem/toxins.dm b/code/modules/reagents/newchem/toxins.dm index 4c7f75829e0..ae8b80ac1cd 100644 --- a/code/modules/reagents/newchem/toxins.dm +++ b/code/modules/reagents/newchem/toxins.dm @@ -397,6 +397,15 @@ ..() return +/datum/chemical_reaction/initropidril + name = "Initropidril" + id = "initropidril" + result = "initropidril" + required_reagents = list("crank" = 1, "histamine" = 1, "krokodil" = 1, "bath_salts" = 1, "atropine" = 1, "nicotine" = 1, "morphine" = 1) + result_amount = 4 + mix_message = "A sweet and sugary scent drifts from the unpleasant milky substance." + + /datum/reagent/concentrated_initro name = "Concentrated Initropidril" id = "concentrated_initro" diff --git a/code/modules/reagents/oldchem/reagents/_reagent_base.dm b/code/modules/reagents/oldchem/reagents/_reagent_base.dm index 9221c42f0c8..5b755c1ee98 100644 --- a/code/modules/reagents/oldchem/reagents/_reagent_base.dm +++ b/code/modules/reagents/oldchem/reagents/_reagent_base.dm @@ -63,13 +63,11 @@ return /datum/reagent/proc/on_mob_life(var/mob/living/M as mob, var/alien) - if(!istype(M, /mob/living)) // YOU'RE A FUCKING RETARD NEO WHY CAN'T YOU JUST FIX THE PROBLEM ON THE REAGENT - Iamgoofball - return //Noticed runtime errors from facid trying to damage ghosts, this should fix. --NEO - // Certain elements in too large amounts cause side-effects + if(!istype(M)) + return if(holder) - holder.remove_reagent(src.id, metabolization_rate) //By default it slowly disappears. + holder.remove_reagent(id, metabolization_rate) //By default it slowly disappears. current_cycle++ - return // Called when two reagents of the same are mixing. /datum/reagent/proc/on_merge(var/data) diff --git a/code/modules/reagents/oldchem/reagents/drink/reagents_alcohol.dm b/code/modules/reagents/oldchem/reagents/drink/reagents_alcohol.dm index 12e1a554edd..82d46d60519 100644 --- a/code/modules/reagents/oldchem/reagents/drink/reagents_alcohol.dm +++ b/code/modules/reagents/oldchem/reagents/drink/reagents_alcohol.dm @@ -36,8 +36,7 @@ if(ishuman(M) && !M.isSynthetic()) var/mob/living/carbon/human/H = M L = H.get_int_organ(/obj/item/organ/internal/liver) - if(!L || (istype(L) && L.dna.species in list("Skrell", "Neara"))) - d*=5 + d *= L ? L.alcohol_intensity : 5 M.dizziness += dizzy_adj. if(d >= slur_start && d < pass_out) diff --git a/code/modules/reagents/oldchem/reagents/reagents_misc.dm b/code/modules/reagents/oldchem/reagents/reagents_misc.dm index 8c3352243eb..889a2011d48 100644 --- a/code/modules/reagents/oldchem/reagents/reagents_misc.dm +++ b/code/modules/reagents/oldchem/reagents/reagents_misc.dm @@ -42,16 +42,6 @@ reagent_state = GAS color = "#808080" // rgb: 128, 128, 128 -/datum/reagent/oxygen/on_mob_life(var/mob/living/M as mob, var/alien) - if(M.stat == 2) return - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species && (H.species.name == "Vox" || H.species.name =="Vox Armalis")) - M.adjustToxLoss(REAGENTS_METABOLISM) - holder.remove_reagent(src.id, REAGENTS_METABOLISM) //By default it slowly disappears. - return - ..() - /datum/reagent/nitrogen name = "Nitrogen" @@ -60,16 +50,6 @@ reagent_state = GAS color = "#808080" // rgb: 128, 128, 128 -/datum/reagent/nitrogen/on_mob_life(var/mob/living/M as mob, var/alien) - if(M.stat == 2) return - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species && (H.species.name == "Vox" || H.species.name =="Vox Armalis")) - M.adjustOxyLoss(-2*REM) - holder.remove_reagent(src.id, REAGENTS_METABOLISM) //By default it slowly disappears. - return - ..() - /datum/reagent/hydrogen name = "Hydrogen" diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 31b6ca73fd0..902892d3f7e 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -787,7 +787,7 @@ New() ..() reagents.add_reagent("nutriment", 6) - reagents.add_reagent("mannitol", 6) + reagents.add_reagent("prions", 10) bitesize = 2 /obj/item/weapon/reagent_containers/food/snacks/ghostburger diff --git a/code/modules/reagents/reagent_containers/food/snacks/candy.dm b/code/modules/reagents/reagent_containers/food/snacks/candy.dm index 39abcac4a6a..1370eff0093 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/candy.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/candy.dm @@ -96,6 +96,34 @@ reagents.add_reagent("chocolate",6) bitesize = 3 +/obj/item/weapon/reagent_containers/food/snacks/candy/fudge/peanut + name = "Peanut Fudge" + desc = "Chocolate fudge, with bits of peanuts mixed in. People with nut allergies shouldn't eat this." + icon_state = "fudge_peanut" + filling_color = "#7D5F46" + +/obj/item/weapon/reagent_containers/food/snacks/candy/fudge/cherry + name = "Chocolate Cherry Fudge" + desc = "Chocolate fudge surrounding sweet cherries. Good for tricking kids into eating some fruit." + icon_state = "fudge_cherry" + filling_color = "#7D5F46" + +/obj/item/weapon/reagent_containers/food/snacks/candy/fudge/cookies_n_cream + name = "Cookies 'n' Cream Fudge" + desc = "An extra creamy fudge with bits of real chocolate cookie mixed in. Crunchy!" + icon_state = "fudge_cookies_n_cream" + filling_color = "#7D5F46" + +/obj/item/weapon/reagent_containers/food/snacks/candy/fudge/cookies_n_cream/New() + ..() + reagents.add_reagent("cream", 3) + +/obj/item/weapon/reagent_containers/food/snacks/candy/fudge/turtle + name = "Turtle Fudge" + desc = "Chocolate fudge with caramel and nuts. It doesn't contain real turtles, thankfully." + icon_state = "fudge_turtle" + filling_color = "#7D5F46" + // *********************************************************** // Candy Products (Pre-existing) // *********************************************************** diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm index 3079a5286ec..ca4b15fc211 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle.dm @@ -299,7 +299,7 @@ New() ..() - reagents.add_reagent(pick("polonium","initropidril","concentrated_initro","pancuronium","sodium_thiopental","ketamine","sulfonal","amanitin","coniine","curare","sarin","histamine","venom","cyanide","spidereggs","nanomachines"), 40) + reagents.add_reagent(pick_list("chemistry_tools.json", "traitor_poison_bottle"), 40) /obj/item/weapon/reagent_containers/glass/bottle/plasma name = "plasma dust bottle" diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 4301d393391..cb3737824e0 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -14,6 +14,7 @@ icon_state = "disposal" anchored = 1 density = 1 + on_blueprints = TRUE var/datum/gas_mixture/air_contents // internal reservoir var/mode = 1 // item mode 0=off 1=charging 2=charged var/flush = 0 // true if flush handle is pulled @@ -656,6 +657,7 @@ anchored = 1 density = 0 + on_blueprints = TRUE level = 1 // underfloor only var/dpdir = 0 // bitmask of pipe directions dir = 0 // dir will contain dominant direction for junction pipes diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm index d2da596b692..385969c3f3f 100644 --- a/code/modules/research/designs/machine_designs.dm +++ b/code/modules/research/designs/machine_designs.dm @@ -92,6 +92,16 @@ build_path = /obj/item/weapon/circuitboard/teleporter_station category = list ("Teleportation Machinery") +/datum/design/teleport_perma + name = "Machine Board (Permanent Teleporter)" + desc = "Allows for the construction of circuit boards used to build a Permanent Teleporter." + id = "tele_perma" + req_tech = list("programming" = 3, "bluespace" = 5, "materials" = 4, "engineering" = 5) + build_type = IMPRINTER + materials = list(MAT_GLASS = 1000, "sacid" = 20) + build_path = /obj/item/weapon/circuitboard/teleporter_perma + category = list ("Teleportation Machinery") + /datum/design/bodyscanner name = "Machine Board (Body Scanner)" desc = "Allows for the construction of circuit boards used to build a Body Scanner." diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 16748fbb46b..3c8b89ea2a0 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -81,9 +81,9 @@ Note: Must be placed west/left of and R&D console to function. var/A = materials.amount(M) if(!A) A = reagents.get_reagent_amount(M) - A = A / max(1, (being_built.reagents[M]/efficiency_coeff)) + A = A / max(1, (being_built.reagents[M])) else - A = A / max(1, (being_built.materials[M]/efficiency_coeff)) + A = A / max(1, (being_built.materials[M])) return A /obj/machinery/r_n_d/protolathe/attackby(var/obj/item/O as obj, var/mob/user as mob, params) diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 58c1cf7fe6f..9e8b29f94c1 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -171,7 +171,7 @@ proc/CallMaterialName(ID) return D.loc = src to_chat(user, "You add the disk to the machine!") - else + else if(!(linked_destroy && linked_destroy.busy) && !(linked_lathe && linked_lathe.busy) && !(linked_imprinter && linked_imprinter.busy)) ..() src.updateUsrDialog() return @@ -411,7 +411,7 @@ proc/CallMaterialName(ID) var/list/efficient_mats = list() for(var/MAT in being_built.materials) - efficient_mats[MAT] = being_built.materials[MAT] / coeff + efficient_mats[MAT] = being_built.materials[MAT] if(!linked_lathe.materials.has_materials(efficient_mats, amount)) src.visible_message("The [src.name] beeps, \"Not enough materials to complete prototype.\"") @@ -419,7 +419,7 @@ proc/CallMaterialName(ID) g2g = 0 else for(var/R in being_built.reagents) - if(!linked_lathe.reagents.has_reagent(R, being_built.reagents[R]/coeff)) + if(!linked_lathe.reagents.has_reagent(R, being_built.reagents[R])) src.visible_message("The [src.name] beeps, \"Not enough reagents to complete prototype.\"") enough_materials = 0 g2g = 0 @@ -427,7 +427,7 @@ proc/CallMaterialName(ID) if(enough_materials) linked_lathe.materials.use_amount(efficient_mats, amount) for(var/R in being_built.reagents) - linked_lathe.reagents.remove_reagent(R, being_built.reagents[R]/coeff) + linked_lathe.reagents.remove_reagent(R, being_built.reagents[R]) var/P = being_built.build_path //lets save these values before the spawn() just in case. Nobody likes runtimes. var/O = being_built.locked @@ -439,8 +439,7 @@ proc/CallMaterialName(ID) new_item.investigate_log("built by [key]","singulo") new_item.reliability = 100 if(!istype(new_item, /obj/item/stack/sheet)) // To avoid materials dupe glitches - new_item.materials[MAT_METAL] /= coeff - new_item.materials[MAT_GLASS] /= coeff + new_item.materials = efficient_mats.Copy() if(O) var/obj/item/weapon/storage/lockbox/L = new/obj/item/weapon/storage/lockbox(linked_lathe.loc) new_item.loc = L @@ -873,7 +872,6 @@ proc/CallMaterialName(ID) dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" - var/coeff = linked_lathe.efficiency_coeff for(var/datum/design/D in files.known_designs) if(!(selected_category in D.category)|| !(D.build_type & PROTOLATHE)) continue @@ -884,9 +882,9 @@ proc/CallMaterialName(ID) t = linked_lathe.check_mat(D, M) temp_material += " | " if (t < 1) - temp_material += "[D.materials[M]/coeff] [CallMaterialName(M)]" + temp_material += "[D.materials[M]] [CallMaterialName(M)]" else - temp_material += " [D.materials[M]/coeff] [CallMaterialName(M)]" + temp_material += " [D.materials[M]] [CallMaterialName(M)]" c = min(c,t) @@ -894,9 +892,9 @@ proc/CallMaterialName(ID) t = linked_lathe.check_mat(D, R) temp_material += " | " if (t < 1) - temp_material += "[D.reagents[R]/coeff] [CallMaterialName(R)]" + temp_material += "[D.reagents[R]] [CallMaterialName(R)]" else - temp_material += " [D.reagents[R]/coeff] [CallMaterialName(R)]" + temp_material += " [D.reagents[R]] [CallMaterialName(R)]" c = min(c,t) if (c >= 1) @@ -920,7 +918,6 @@ proc/CallMaterialName(ID) dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" - var/coeff = linked_lathe.efficiency_coeff for(var/datum/design/D in matching_designs) var/temp_material var/c = 50 @@ -929,18 +926,18 @@ proc/CallMaterialName(ID) t = linked_lathe.check_mat(D, M) temp_material += " | " if (t < 1) - temp_material += "[D.materials[M]/coeff] [CallMaterialName(M)]" + temp_material += "[D.materials[M]] [CallMaterialName(M)]" else - temp_material += " [D.materials[M]/coeff] [CallMaterialName(M)]" + temp_material += " [D.materials[M]] [CallMaterialName(M)]" c = min(c,t) for(var/R in D.reagents) t = linked_lathe.check_mat(D, R) temp_material += " | " if (t < 1) - temp_material += "[D.reagents[R]/coeff] [CallMaterialName(R)]" + temp_material += "[D.reagents[R]] [CallMaterialName(R)]" else - temp_material += " [D.reagents[R]/coeff] [CallMaterialName(R)]" + temp_material += " [D.reagents[R]] [CallMaterialName(R)]" c = min(c,t) if (c >= 1) diff --git a/code/modules/research/xenoarchaeology/finds/finds_misc.dm b/code/modules/research/xenoarchaeology/finds/finds_misc.dm index 68293501b77..e94049a74f1 100644 --- a/code/modules/research/xenoarchaeology/finds/finds_misc.dm +++ b/code/modules/research/xenoarchaeology/finds/finds_misc.dm @@ -25,7 +25,6 @@ return /obj/item/weapon/shard/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - ..() if ( istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W if(WT.remove_fuel(0, user)) diff --git a/code/modules/scripting/Implementations/Telecomms.dm b/code/modules/scripting/Implementations/Telecomms.dm index e06a5f9a18d..273ccb67d0e 100644 --- a/code/modules/scripting/Implementations/Telecomms.dm +++ b/code/modules/scripting/Implementations/Telecomms.dm @@ -60,6 +60,9 @@ return interpreter.container = src + + interpreter.CreateGlobalScope() // Reset the variables. + interpreter.curScope = interpreter.globalScope interpreter.SetVar("PI", 3.141592653) // value of pi interpreter.SetVar("E", 2.718281828) // value of e @@ -127,7 +130,7 @@ @param time: time to sleep in deciseconds (1/10th second) */ - interpreter.SetProc("sleep", /proc/delay) + interpreter.SetProc("sleep", "delay", signal, list("time")) /* -> Replaces a string with another string @@ -199,27 +202,27 @@ interpreter.SetProc("tostring", /proc/n_num2str) interpreter.SetProc("sqrt", /proc/n_sqrt) interpreter.SetProc("abs", /proc/n_abs) - interpreter.SetProc("floor", /proc/Floor) - interpreter.SetProc("ceil", /proc/Ceiling) + interpreter.SetProc("floor", /proc/n_floor) + interpreter.SetProc("ceil", /proc/n_ceiling) interpreter.SetProc("round", /proc/n_round) interpreter.SetProc("clamp", /proc/n_clamp) - interpreter.SetProc("inrange", /proc/IsInRange) + interpreter.SetProc("inrange", /proc/n_isInRange) interpreter.SetProc("rand", /proc/rand_chance) interpreter.SetProc("arctan", /proc/Atan2) - interpreter.SetProc("lcm", /proc/Lcm) + interpreter.SetProc("lcm", /proc/n_lcm) interpreter.SetProc("gcd", /proc/Gcd) interpreter.SetProc("mean", /proc/Mean) - interpreter.SetProc("root", /proc/Root) + interpreter.SetProc("root", /proc/n_root) interpreter.SetProc("sin", /proc/n_sin) interpreter.SetProc("cos", /proc/n_cos) interpreter.SetProc("arcsin", /proc/n_asin) interpreter.SetProc("arccos", /proc/n_acos) - interpreter.SetProc("tan", /proc/Tan) - interpreter.SetProc("csc", /proc/Csc) - interpreter.SetProc("cot", /proc/Cot) - interpreter.SetProc("sec", /proc/Sec) - interpreter.SetProc("todegrees", /proc/ToDegrees) - interpreter.SetProc("toradians", /proc/ToRadians) + interpreter.SetProc("tan", /proc/n_tan) + interpreter.SetProc("csc", /proc/n_csc) + interpreter.SetProc("cot", /proc/n_cot) + interpreter.SetProc("sec", /proc/n_sec) + interpreter.SetProc("todegrees", /proc/n_toDegrees) + interpreter.SetProc("toradians", /proc/n_toRadians) interpreter.SetProc("lerp", /proc/Lerp) interpreter.SetProc("max", /proc/n_max) interpreter.SetProc("min", /proc/n_min) @@ -255,6 +258,28 @@ signal.data["reject"] = 1 /* -- Actual language proc code -- */ +/datum/signal/proc/delay(var/time) + var/obj/machinery/telecomms/server/S = data["server"] + var/datum/n_Interpreter/TCS_Interpreter/interpreter = S.Compiler.interpreter + // Backup the scope + var/datum/scope/globalScope = interpreter.globalScope + var/datum/scope/curScope = interpreter.curScope + var/list/scopes = interpreter.scopes.stack.Copy() + var/list/functions = interpreter.functions.stack.Copy() + var/datum/node/statement/FunctionDefinition/curFunction = interpreter.curFunction + var/status = interpreter.status + var/returnVal = interpreter.returnVal + // Sleep + sleep(time) + // Restore the scope + interpreter.returnVal = returnVal + interpreter.status = status + interpreter.curFunction = curFunction + interpreter.functions.stack = functions + interpreter.scopes.stack = scopes + interpreter.curScope = curScope + interpreter.globalScope = globalScope + /datum/signal/proc/mem(var/address, var/value) if(istext(address)) var/obj/machinery/telecomms/server/S = data["server"] diff --git a/code/modules/scripting/Implementations/_Logic.dm b/code/modules/scripting/Implementations/_Logic.dm index a97fc320e0e..c31d55f3077 100644 --- a/code/modules/scripting/Implementations/_Logic.dm +++ b/code/modules/scripting/Implementations/_Logic.dm @@ -99,11 +99,6 @@ // --- Miscellaneous functions --- -// Clone of sleep() -/proc/delay(var/time) - //writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/delay() called tick#: [world.time]") - sleep(time) - // Clone of rand() /proc/rand_chance(var/low = 0, var/high) //writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/rand_chance() called tick#: [world.time]") @@ -221,13 +216,13 @@ proc/n_abs(var/num) proc/n_floor(var/num) //writepanic("[__FILE__].[__LINE__] \\/proc/n_floor() called tick#: [world.time]") if(isnum(num)) - return round(num) + return Floor(num) // Round up -proc/n_ceil(var/num) +proc/n_ceiling(var/num) //writepanic("[__FILE__].[__LINE__] \\/proc/n_ceil() called tick#: [world.time]") if(isnum(num)) - return round(num)+1 + return Ceiling(num) // Round to nearest integer proc/n_round(var/num) @@ -235,22 +230,61 @@ proc/n_round(var/num) if(isnum(num)) if(num-round(num)<0.5) return round(num) - return n_ceil(num)\ + return Ceiling(num) // END OF BY DONKIE :( /proc/n_sin(var/const/x) - return sin(x) + if(isnum(x)) + return sin(x) /proc/n_cos(var/const/x) - return cos(x) + if(isnum(x)) + return cos(x) + +/proc/n_tan(var/const/x) + if(isnum(x)) + return Tan(x) + +/proc/n_csc(var/const/x) + if(isnum(x)) + return Csc(x) + +/proc/n_cot(var/const/x) + if(isnum(x)) + return Cot(x) + +/proc/n_sec(var/const/x) + if(isnum(x)) + return Sec(x) /proc/n_asin(var/const/x) - return arcsin(x) + if(isnum(x)) + return arcsin(x) /proc/n_acos(var/const/x) - return arccos(x) + if(isnum(x)) + return arccos(x) +/proc/n_isInRange(var/const/x, var/const/min, var/const/max) + if(isnum(x) && isnum(min) && isnum(max)) + return IsInRange(x, min, max) + +/proc/n_lcm(var/const/a, var/const/b) + if(isnum(a) && isnum(b)) + return Lcm(a, b) + +/proc/n_root(var/const/n, var/const/x) + if(isnum(n) && isnum(x)) + return Root(n, x) + +/proc/n_toDegrees(var/const/x) + if(isnum(x)) + return ToDegrees(x) + +/proc/n_toRadians(var/const/x) + if(isnum(x)) + return ToRadians(x) /proc/n_max(...) return max(arglist(args)) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 2a794de2ff8..119378d53f4 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -683,7 +683,12 @@ to_chat(usr, "Access denied.") return + var/list/options = params2list(possible_destinations) if(href_list["move"]) + if(!options.Find(href_list["move"])) //I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. + // Seriously, though, NEVER trust a Topic with something like this. Ever. + message_admins("move HREF ([src] attempted to move to: [href_list["move"]]) exploit attempted by [key_name_admin(usr)] on [src] (JMP)") + return switch(shuttle_master.moveShuttle(shuttleId, href_list["move"], 1)) if(0) to_chat(usr, "Shuttle received message and will be sent shortly.") diff --git a/code/modules/store/items.dm b/code/modules/store/items.dm index 489caa96a91..c67ed43fd92 100644 --- a/code/modules/store/items.dm +++ b/code/modules/store/items.dm @@ -171,6 +171,12 @@ typepath = /obj/item/flag/species/vulp cost = 1000 +/datum/storeitem/flag_drask + name = "Drask flag" + desc = "A flag proudly proclaiming the superior heritage of Drask." + typepath = /obj/item/flag/species/drask + cost = 1000 + /datum/storeitem/flag_ian name = "Ian flag" desc = "The banner of Ian, because SQUEEEEE." diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index 3386f4b9366..90f2d9afed0 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -97,10 +97,12 @@ E.forceMove(target) if(target.get_species() == "Machine")//as this is the only step needed for ipc put togethers if(target_zone == "head") - var/obj/item/organ/external/head/H = target.organs_by_name["head"] + var/obj/item/organ/external/head/H = target.get_organ("head") var/datum/robolimb/robohead = all_robolimbs[H.model] if(robohead.is_monitor) //Ensures that if an IPC gets a head that's got a human hair wig attached to their body, the hair won't wipe. - target.h_style = "" + H.h_style = "" + H.f_style = "" + target.m_style = "" E.status &= ~ORGAN_DESTROYED if(E.children) for(var/obj/item/organ/external/C in E.children) diff --git a/code/modules/surgery/organs/blood.dm b/code/modules/surgery/organs/blood.dm index f2dd4c3c778..c1a1c7562a9 100644 --- a/code/modules/surgery/organs/blood.dm +++ b/code/modules/surgery/organs/blood.dm @@ -190,7 +190,9 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 if(src.species.exotic_blood) vessel.remove_reagent(species.exotic_blood,amm) - vessel.reaction(T, TOUCH, amm) + if(vessel.total_volume) + var/fraction = amm / vessel.total_volume + vessel.reaction(T, TOUCH, fraction) return else diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index db6ffd81a2a..0488d768adf 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -54,6 +54,7 @@ var/global/list/limb_icon_cache = list() overlays.Cut() if(!owner) return + var/obj/item/organ/external/head/H = owner.get_organ("head") if(species.has_organ["eyes"]) var/obj/item/organ/internal/eyes/eyes = owner.get_int_organ(/obj/item/organ/internal/eyes)//owner.internal_organs_by_name["eyes"] @@ -79,32 +80,32 @@ var/global/list/limb_icon_cache = list() markings_s.Blend(rgb(owner.r_markings, owner.g_markings, owner.b_markings), ICON_ADD) overlays |= markings_s - if(owner.ha_style) - var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[owner.ha_style] - if(head_accessory_style && head_accessory_style.species_allowed && (species.name in head_accessory_style.species_allowed)) + if(H.ha_style) + var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[H.ha_style] + if(head_accessory_style && head_accessory_style.species_allowed && (H.species.name in head_accessory_style.species_allowed)) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) - head_accessory_s.Blend(rgb(owner.r_headacc, owner.g_headacc, owner.b_headacc), ICON_ADD) + head_accessory_s.Blend(rgb(H.r_headacc, H.g_headacc, H.b_headacc), ICON_ADD) overlays |= head_accessory_s - if(owner.f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] - if(facial_hair_style && ((facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) || (src.species.flags & ALL_RPARTS))) + if(H.f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] + if(facial_hair_style && ((facial_hair_style.species_allowed && (H.species.name in facial_hair_style.species_allowed)) || (src.species.flags & ALL_RPARTS))) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(species.name == "Slime People") // I am el worstos + if(H.species.name == "Slime People") // I am el worstos facial_s.Blend(rgb(owner.r_skin, owner.g_skin, owner.b_skin, 160), ICON_AND) else if(facial_hair_style.do_colouration) - facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD) + facial_s.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) overlays |= facial_s - if(owner.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] - if(hair_style && ((species.name in hair_style.species_allowed) || (src.species.flags & ALL_RPARTS))) + if(H.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) + var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] + if(hair_style && ((H.species.name in hair_style.species_allowed) || (src.species.flags & ALL_RPARTS))) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(species.name == "Slime People") // I am el worstos + if(H.species.name == "Slime People") // I am el worstos hair_s.Blend(rgb(owner.r_skin, owner.g_skin, owner.b_skin, 160), ICON_AND) else if(hair_style.do_colouration) - hair_s.Blend(rgb(owner.r_hair, owner.g_hair, owner.b_hair), ICON_ADD) + hair_s.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) overlays |= hair_s return mob_icon diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 248da9d1154..5982237cbac 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -292,6 +292,7 @@ organ_tag = "liver" parent_organ = "groin" slot = "liver" + var/alcohol_intensity = 1 /obj/item/organ/internal/liver/process() @@ -499,18 +500,19 @@ if(istype(owner, /mob/living/carbon/human)) var/mob/living/carbon/human/H = owner - if(!(H.h_style == "Very Long Hair" || H.h_style == "Mowhawk")) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(!(head_organ.h_style == "Very Long Hair" || head_organ.h_style == "Mohawk")) if(prob(10)) - H.h_style = "Mohawk" + head_organ.h_style = "Mohawk" else - H.h_style = "Very Long Hair" - H.r_hair = 216 - H.g_hair = 192 - H.b_hair = 120 + head_organ.h_style = "Very Long Hair" + head_organ.r_hair = 216 + head_organ.g_hair = 192 + head_organ.b_hair = 120 H.update_hair() - if(!(H.f_style == "Very Long Beard")) - H.f_style = "Very Long Beard" - H.r_facial = 216 - H.g_facial = 192 - H.b_facial = 120 + if(!(head_organ.f_style == "Very Long Beard")) + head_organ.f_style = "Very Long Beard" + head_organ.r_facial = 216 + head_organ.g_facial = 192 + head_organ.b_facial = 120 H.update_fhair() \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/diona.dm b/code/modules/surgery/organs/subtypes/diona.dm index 407f2187842..5d2bf63035b 100644 --- a/code/modules/surgery/organs/subtypes/diona.dm +++ b/code/modules/surgery/organs/subtypes/diona.dm @@ -17,125 +17,81 @@ D.death() return 1 */ -/obj/item/organ/external/diona - name = "tendril" +/obj/item/organ/external/chest/diona + name = "core trunk" + max_damage = 200 + min_broken_damage = 50 + cannot_break = 1 + amputation_point = "trunk" + encased = null + gendered_icon = 0 + +/obj/item/organ/external/groin/diona + name = "fork" + min_broken_damage = 50 + cannot_break = 1 + amputation_point = "lower trunk" + gendered_icon = 0 + +/obj/item/organ/external/arm/diona + name = "left upper tendril" + max_damage = 35 + min_broken_damage = 20 + cannot_break = 1 + amputation_point = "upper left trunk" + +/obj/item/organ/external/arm/right/diona + name = "right upper tendril" + max_damage = 35 + min_broken_damage = 20 + cannot_break = 1 + amputation_point = "upper right trunk" + +/obj/item/organ/external/leg/diona + name = "left lower tendril" + max_damage = 35 + min_broken_damage = 20 + cannot_break = 1 + amputation_point = "lower left fork" + +/obj/item/organ/external/leg/right/diona + name = "right lower tendril" + max_damage = 35 + min_broken_damage = 20 + cannot_break = 1 + amputation_point = "lower right fork" + +/obj/item/organ/external/foot/diona + name = "left foot" + max_damage = 20 + min_broken_damage = 10 cannot_break = 1 amputation_point = "branch" -/obj/item/organ/external/diona/chest - name = "core trunk" - limb_name = "chest" - icon_name = "torso" - max_damage = 200 - min_broken_damage = 50 - w_class = 5 - body_part = UPPER_TORSO - vital = 1 - cannot_amputate = 1 - parent_organ = null - -/obj/item/organ/external/diona/groin - name = "fork" - limb_name = "groin" - icon_name = "groin" - max_damage = 100 - min_broken_damage = 50 - w_class = 4 - body_part = LOWER_TORSO - parent_organ = "chest" - -/obj/item/organ/external/diona/arm - name = "left upper tendril" - limb_name = "l_arm" - icon_name = "l_arm" - max_damage = 35 - min_broken_damage = 20 - w_class = 3 - body_part = ARM_LEFT - parent_organ = "chest" - can_grasp = 1 - -/obj/item/organ/external/diona/arm/right - name = "right upper tendril" - limb_name = "r_arm" - icon_name = "r_arm" - body_part = ARM_RIGHT - -/obj/item/organ/external/diona/leg - name = "left lower tendril" - limb_name = "l_leg" - icon_name = "l_leg" - max_damage = 35 - min_broken_damage = 20 - w_class = 3 - body_part = LEG_LEFT - icon_position = LEFT - parent_organ = "groin" - can_stand = 1 - -/obj/item/organ/external/diona/leg/right - name = "right lower tendril" - limb_name = "r_leg" - icon_name = "r_leg" - body_part = LEG_RIGHT - icon_position = RIGHT - -/obj/item/organ/external/diona/foot - name = "left foot" - limb_name = "l_foot" - icon_name = "l_foot" +/obj/item/organ/external/foot/right/diona + name = "right foot" max_damage = 20 min_broken_damage = 10 - w_class = 2 - body_part = FOOT_LEFT - icon_position = LEFT - parent_organ = "l_leg" - can_stand = 1 + cannot_break = 1 + amputation_point = "branch" -/obj/item/organ/external/diona/foot/right - name = "right foot" - limb_name = "r_foot" - icon_name = "r_foot" - body_part = FOOT_RIGHT - icon_position = RIGHT - parent_organ = "r_leg" - amputation_point = "right ankle" - -/obj/item/organ/external/diona/hand +/obj/item/organ/external/hand/diona name = "left grasper" - limb_name = "l_hand" - icon_name = "l_hand" - max_damage = 30 - min_broken_damage = 15 - w_class = 2 - body_part = HAND_LEFT - parent_organ = "l_arm" - can_grasp = 1 + cannot_break = 1 + amputation_point = "branch" -/obj/item/organ/external/diona/hand/right +/obj/item/organ/external/hand/right/diona name = "right grasper" - limb_name = "r_hand" - icon_name = "r_hand" - body_part = HAND_RIGHT - parent_organ = "r_arm" + cannot_break = 1 + amputation_point = "branch" -/obj/item/organ/external/diona/head - limb_name = "head" - icon_name = "head" - name = "head" +/obj/item/organ/external/head/diona max_damage = 50 min_broken_damage = 25 - vital = 1 - w_class = 3 - body_part = HEAD - parent_organ = "chest" - var/can_intake_reagents = 1 - -/obj/item/organ/external/diona/head/remove() - if(owner) - owner.unEquip(owner.head) - owner.unEquip(owner.l_ear) - ..() + cannot_break = 1 + encased = null + amputation_point = "upper trunk" + gendered_icon = 0 //DIONA ORGANS. /* /obj/item/organ/external/diona/removed() diff --git a/code/modules/surgery/organs/subtypes/drask.dm b/code/modules/surgery/organs/subtypes/drask.dm index 5ecfa67e054..3e9b37cebe8 100644 --- a/code/modules/surgery/organs/subtypes/drask.dm +++ b/code/modules/surgery/organs/subtypes/drask.dm @@ -38,6 +38,8 @@ icon_state = "brain2" organ_tag = "brain" slot = "brain" + mmi_icon = 'icons/obj/surgery_drask.dmi' + mmi_icon_state = "mmi_full" /obj/item/organ/internal/eyes/drask name = "eyes" diff --git a/code/modules/surgery/organs/subtypes/skrell.dm b/code/modules/surgery/organs/subtypes/skrell.dm new file mode 100644 index 00000000000..faf58b7a3ef --- /dev/null +++ b/code/modules/surgery/organs/subtypes/skrell.dm @@ -0,0 +1,2 @@ +/obj/item/organ/internal/liver/skrell + alcohol_intensity = 5 \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/standard.dm b/code/modules/surgery/organs/subtypes/standard.dm index c9cbbb17906..d481ba1b7ae 100644 --- a/code/modules/surgery/organs/subtypes/standard.dm +++ b/code/modules/surgery/organs/subtypes/standard.dm @@ -141,6 +141,24 @@ encased = "skull" var/can_intake_reagents = 1 + //Hair colour and style + var/r_hair = 0 + var/g_hair = 0 + var/b_hair = 0 + var/h_style = "Bald" + + //Head accessory colour and style + var/r_headacc = 0 + var/g_headacc = 0 + var/b_headacc = 0 + var/ha_style = "None" + + //Facial hair colour and style + var/r_facial = 0 + var/g_facial = 0 + var/b_facial = 0 + var/f_style = "Shaved" + /obj/item/organ/external/head/remove() if(owner) if(!istype(dna)) diff --git a/code/world.dm b/code/world.dm index f5cfdee0401..b217f57b68b 100644 --- a/code/world.dm +++ b/code/world.dm @@ -18,7 +18,7 @@ var/global/datum/global_init/init = new () cache_lifespan = 0 //stops player uploaded stuff from being kept in the rsc past the current session -#define RECOMMENDED_VERSION 508 +#define RECOMMENDED_VERSION 510 /world/New() //logs diff --git a/config/example/game_options.txt b/config/example/game_options.txt index 69847e0a6b6..5d82bfb425d 100644 --- a/config/example/game_options.txt +++ b/config/example/game_options.txt @@ -54,6 +54,10 @@ ANIMAL_DELAY 0 ## Uncomment for explosions that react to doors and walls REACTIONARY_EXPLOSIONS +# The number of objectives traitors get. +# Not including escaping/hijacking. +TRAITOR_OBJECTIVES_AMOUNT 2 + ### Configure the bomb cap ## This caps all explosions to the specified range. Used for both balance reasons and to prevent overloading the server and lagging the game out. ## This is given as the 3rd number(light damage) in the standard (1,2,3) explosion notation. The other numbers are derived by dividing by 2 and 4. diff --git a/html/changelog.html b/html/changelog.html index ee1e84b1671..0930debbc21 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,133 @@ -->
+

20 May 2016

+

Fox McCloud updated:

+
    +
  • Fixes Chaplains being able to be vampires
  • +
  • Cryopods will now always display the occupant's name
  • +
+

KasparoVy updated:

+
    +
  • Fixes a runtime with Dioneae by repathing their limbs.
  • +
+

QuinnAggeler updated:

+
    +
  • Makes dehydrated space carp description more accurate and informative
  • +
+

monster860 updated:

+
    +
  • Adds the permanent teleporter. Use the circuitboard on a teleporter hub to set the target before constructing it.
  • +
+ +

17 May 2016

+

AugRob updated:

+
    +
  • Add screwdriver sound when opening/closing panels on airlocks
  • +
+

Fox MCCloud updated:

+
    +
  • Removes "harm" traitor objective
  • +
  • Increases non-escape/hijack/die objectives from 1 to 2
  • +
  • Tweaks available objectives to traitors a bit
  • +
+

Fox McCloud updated:

+
    +
  • Players can no longer see how many players have readied up or who has readied up
  • +
  • Hulks, Shadowlings, and Golems can no longer use laserpointers
  • +
  • Adds in the ability to flip over someone with *flip
  • +
  • Fixes and improves foam to better interact with reagents
  • +
+

KasparoVy updated:

+
    +
  • Refactors hair so it's on the head (organ).
  • +
  • Adjusts some Vox hair style names so they're consistent with all others.
  • +
  • Refactors Morph and the order by which options are presented.
  • +
  • Players with heads of a different species than the body will now only be able to access the head accessories, hair/facial hair styles of the head's species.
  • +
  • Fixes some typos.
  • +
  • Fixes a bug where hairgrownium made you bald and super hairgrownium only changed the hair/facial hair styles of Humans.
  • +
  • Fixes a bug where Morph wouldn't correctly set eye colour or skin tone.
  • +
  • Fixes a typo that didn't really have any negative effect on the beard organ to begin with.
  • +
  • Fixes bugs where Alopecia and Facial Hypertrichosis disease symptoms wouldn't update player sprite correctly.
  • +
  • Adds a new Vox hairstyle.
  • +
  • You can now change your head accessory (and its colour), body markings (and their colour), and body accessory if you're a species that has such things via the Morph genetic power and C.M.A. (the bathroom SalonPro Nano-Mirrors and admin verbs).
  • +
+

monster860 updated:

+
    +
  • Fixes sleep() in telecomms
  • +
  • Windows can now be constructed and deconstructed using RCD's.
  • +
+ +

10 May 2016

+

Crazylemon64 updated:

+
    +
  • Ragin' Mage creation works correctly again.
  • +
+

FalseIncarnate updated:

+
    +
  • Adds a Briefcase Full of Bees as a Botanist-only traitor item (10 TC)
  • +
  • Fixes worker bees having an insatiable desire to murder bots. (Syndi-bees still murder them though)
  • +
+

FlattestGuitar updated:

+
    +
  • Robots now slur and stutter robotically
  • +
  • Adds tape gags. Click on someone with a roll of tape to shut them up!
  • +
+

Fox McCloud updated:

+
    +
  • Removes material efficiency upgrades from the mech fab and protolathe
  • +
  • Ore redemption machine sheets/points per ore scaled from 1 up to 2 (down from 1 up to 4)
  • +
  • Fixes materials exploit duplication
  • +
  • Fixes the protolathe locking up under some circumstances
  • +
  • Updates the laser cannon to be range based: the further its projectile travels, the more damage it does. Base damage greatly reduced.
  • +
  • removes fungus from mushrooms
  • +
  • adds fungus to "mold" plant
  • +
  • adds mold seeds to hydro vendor
  • +
  • bumps up ???? reagent from 1 to 5 on bad recipes
  • +
  • Adds in 3 disease: Grave Fever, Space Kuru, and Non-contagious GBS
  • +
  • Adds Reagent to cause Space Kuru and Non-contagious GBS to traitor poison bottles
  • +
  • Initropidril now has a recipe
  • +
  • Adds a number of new reagents
  • +
  • Brain burgers now contain prions instead of mannitol
  • +
  • Scientists and chemists can no longer purchase traitor poison bottles
  • +
  • random drug bottles now have a much wider range of reagents in them
  • +
  • Fixes UI On slot machine saying it costs 5 credits when it's 10
  • +
  • Fixes abductors having tails
  • +
  • Fixes traitor scissors having a different hair-cutting sound
  • +
  • Fixes simple animals not dying right away when they reach zero health
  • +
  • Fixes a few farm animals, simple xenos, and a hivebot from having incorrect health
  • +
  • Buffed health pack usage on simple animals (should heal roughly 20 damage on them, per use)
  • +
  • Emotes no longer need to be purely lowercase to work
  • +
  • Chaplain can now select a green book as his Bible
  • +
  • Adds in His Grace, a hijack-only traitor item for the Chaplain
  • +
+

IK3I updated:

+
    +
  • Added key and tumbler based pod locks
  • +
  • Made Pod Locks and keys buildable in Pod Fabricator
  • +
  • Made Pod Keys recoverable from cryo
  • +
  • Added lock to Security Pod
  • +
  • Added a key for Security Pod to HoS and Pod Pilot Offices
  • +
  • New sprites for several pieces of pod equipment
  • +
  • Using a multitool on a decalock now gives usable info
  • +
+

NTSAM updated:

+
    +
  • Fixes the stuttery rainbow screen for IPCs.
  • +
  • Fixes the green IPC screen.
  • +
+

QuinnAggeler updated:

+
    +
  • Adds a sound emote for the Drask
  • +
  • Gives Drask the ability to eat soap
  • +
  • Adds a racial flag for the Drask
  • +
  • Makes syndicate, paramedic, clown, and EVA helmets display correctly on Drask
  • +
+

tigercat2000 updated:

+
    +
  • The station blueprints can now show you where wires/pipes/disposal pipes are supposed to go.
  • +
+

04 May 2016

CrAzYPiLoT updated:

    @@ -66,8 +193,8 @@

Fethas updated:

    -
  • Sniper Rifles for nuke ops
  • -
  • you can now actually shove heads on spears again
  • +
  • Sniper Rifles for nuke ops.
  • +
  • you can now actually shove heads on spears again.
  • Before i removed the traitor chemist item i cleaned up the harm reaction code paths.

FlattestGuitar updated:

diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 66e0b3c205f..a8361706d21 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -1347,7 +1347,7 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. Fethas: - rscadd: Sniper Rifles for nuke ops. - bugfix: you can now actually shove heads on spears again. - - tweak: Before i removed the traitor chemist item i cleaned up the harm reaction + - tweak: Before i removed the traitor chemist item i cleaned up the harm reaction code paths. FlattestGuitar: - tweak: cheap lighters only damage your hand if you fail to properly use such a @@ -1422,3 +1422,110 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - bugfix: Plasmamen security now spawn with their suit slot items in their bags - tweak: Pod pilots spawn with taser in the suit slot - tweak: removes armor from plasmamen magistrate suits +2016-05-10: + Crazylemon64: + - bugfix: Ragin' Mage creation works correctly again. + FalseIncarnate: + - rscadd: Adds a Briefcase Full of Bees as a Botanist-only traitor item (10 TC) + - bugfix: Fixes worker bees having an insatiable desire to murder bots. (Syndi-bees + still murder them though) + FlattestGuitar: + - tweak: Robots now slur and stutter robotically + - rscadd: Adds tape gags. Click on someone with a roll of tape to shut them up! + Fox McCloud: + - tweak: Removes material efficiency upgrades from the mech fab and protolathe + - tweak: Ore redemption machine sheets/points per ore scaled from 1 up to 2 (down + from 1 up to 4) + - bugfix: Fixes materials exploit duplication + - bugfix: Fixes the protolathe locking up under some circumstances + - tweak: 'Updates the laser cannon to be range based: the further its projectile + travels, the more damage it does. Base damage greatly reduced.' + - tweak: removes fungus from mushrooms + - tweak: adds fungus to "mold" plant + - tweak: adds mold seeds to hydro vendor + - tweak: bumps up ???? reagent from 1 to 5 on bad recipes + - rscadd: 'Adds in 3 disease: Grave Fever, Space Kuru, and Non-contagious GBS' + - rscadd: Adds Reagent to cause Space Kuru and Non-contagious GBS to traitor poison + bottles + - rscadd: Initropidril now has a recipe + - rscadd: Adds a number of new reagents + - tweak: Brain burgers now contain prions instead of mannitol + - tweak: Scientists and chemists can no longer purchase traitor poison bottles + - tweak: random drug bottles now have a much wider range of reagents in them + - bugfix: Fixes UI On slot machine saying it costs 5 credits when it's 10 + - bugfix: Fixes abductors having tails + - bugfix: Fixes traitor scissors having a different hair-cutting sound + - bugfix: Fixes simple animals not dying right away when they reach zero health + - bugfix: Fixes a few farm animals, simple xenos, and a hivebot from having incorrect + health + - tweak: Buffed health pack usage on simple animals (should heal roughly 20 damage + on them, per use) + - tweak: Emotes no longer need to be purely lowercase to work + - rscadd: Chaplain can now select a green book as his Bible + - rscadd: Adds in His Grace, a hijack-only traitor item for the Chaplain + IK3I: + - rscadd: Added key and tumbler based pod locks + - rscadd: Made Pod Locks and keys buildable in Pod Fabricator + - rscadd: Made Pod Keys recoverable from cryo + - rscadd: Added lock to Security Pod + - rscadd: Added a key for Security Pod to HoS and Pod Pilot Offices + - rscadd: New sprites for several pieces of pod equipment + - bugfix: Using a multitool on a decalock now gives usable info + NTSAM: + - bugfix: Fixes the stuttery rainbow screen for IPCs. + - bugfix: Fixes the green IPC screen. + QuinnAggeler: + - rscadd: Adds a sound emote for the Drask + - rscadd: Gives Drask the ability to eat soap + - rscadd: Adds a racial flag for the Drask + - bugfix: Makes syndicate, paramedic, clown, and EVA helmets display correctly on + Drask + tigercat2000: + - rscadd: The station blueprints can now show you where wires/pipes/disposal pipes + are supposed to go. +2016-05-17: + AugRob: + - rscadd: Add screwdriver sound when opening/closing panels on airlocks + Fox MCCloud: + - tweak: Removes "harm" traitor objective + - tweak: Increases non-escape/hijack/die objectives from 1 to 2 + - tweak: Tweaks available objectives to traitors a bit + Fox McCloud: + - tweak: Players can no longer see how many players have readied up or who has readied + up + - tweak: Hulks, Shadowlings, and Golems can no longer use laserpointers + - rscadd: Adds in the ability to flip over someone with *flip + - tweak: Fixes and improves foam to better interact with reagents + KasparoVy: + - tweak: Refactors hair so it's on the head (organ). + - tweak: Adjusts some Vox hair style names so they're consistent with all others. + - tweak: Refactors Morph and the order by which options are presented. + - tweak: Players with heads of a different species than the body will now only be + able to access the head accessories, hair/facial hair styles of the head's species. + - bugfix: Fixes some typos. + - bugfix: Fixes a bug where hairgrownium made you bald and super hairgrownium only + changed the hair/facial hair styles of Humans. + - bugfix: Fixes a bug where Morph wouldn't correctly set eye colour or skin tone. + - bugfix: Fixes a typo that didn't really have any negative effect on the beard + organ to begin with. + - bugfix: Fixes bugs where Alopecia and Facial Hypertrichosis disease symptoms wouldn't + update player sprite correctly. + - rscadd: Adds a new Vox hairstyle. + - rscadd: You can now change your head accessory (and its colour), body markings + (and their colour), and body accessory if you're a species that has such things + via the Morph genetic power and C.M.A. (the bathroom SalonPro Nano-Mirrors and + admin verbs). + monster860: + - bugfix: Fixes sleep() in telecomms + - rscadd: Windows can now be constructed and deconstructed using RCD's. +2016-05-20: + Fox McCloud: + - bugfix: Fixes Chaplains being able to be vampires + - bugfix: Cryopods will now always display the occupant's name + KasparoVy: + - bugfix: Fixes a runtime with Dioneae by repathing their limbs. + QuinnAggeler: + - bugfix: Makes dehydrated space carp description more accurate and informative + monster860: + - rscadd: Adds the permanent teleporter. Use the circuitboard on a teleporter hub + to set the target before constructing it. diff --git a/html/changelogs/AutoChangeLog-pr-4301.yml b/html/changelogs/AutoChangeLog-pr-4301.yml deleted file mode 100644 index 29f13eefb87..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4301.yml +++ /dev/null @@ -1,9 +0,0 @@ -author: IK3I -delete-after: True -changes: - - rscadd: "Added key and tumbler based pod locks" - - rscadd: "Made Pod Locks and keys buildable in Pod Fabricator" - - rscadd: "Made Pod Keys recoverable from cryo" - - rscadd: "Added lock to Security Pod" - - rscadd: "Added a key for Security Pod to HoS and Pod Pilot Offices" - - rscadd: "New sprites for several pieces of pod equipment" diff --git a/html/changelogs/AutoChangeLog-pr-4339.yml b/html/changelogs/AutoChangeLog-pr-4339.yml deleted file mode 100644 index 19c41130016..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4339.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: FlattestGuitar -delete-after: True -changes: - - tweak: "Robots now slur and stutter robotically" diff --git a/html/changelogs/AutoChangeLog-pr-4343.yml b/html/changelogs/AutoChangeLog-pr-4343.yml deleted file mode 100644 index d681f61d173..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4343.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - tweak: "Updates the laser cannon to be range based: the further its projectile travels, the more damage it does. Base damage greatly reduced." diff --git a/html/changelogs/AutoChangeLog-pr-4353.yml b/html/changelogs/AutoChangeLog-pr-4353.yml deleted file mode 100644 index 3507a4153f6..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4353.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - tweak: "removes fungus from mushrooms" - - tweak: "adds fungus to \"mold\" plant" - - tweak: "adds mold seeds to hydro vendor" - - tweak: "bumps up ???? reagent from 1 to 5 on bad recipes" diff --git a/html/changelogs/AutoChangeLog-pr-4362.yml b/html/changelogs/AutoChangeLog-pr-4362.yml deleted file mode 100644 index 4901b08cd2c..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4362.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - bugfix: "Fixes UI On slot machine saying it costs 5 credits when it's 10" diff --git a/html/changelogs/AutoChangeLog-pr-4363.yml b/html/changelogs/AutoChangeLog-pr-4363.yml deleted file mode 100644 index 8e1c8ac2686..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4363.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - bugfix: "Fixes abductors having tails" diff --git a/html/changelogs/AutoChangeLog-pr-4364.yml b/html/changelogs/AutoChangeLog-pr-4364.yml deleted file mode 100644 index 0b074450742..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4364.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - bugfix: "Fixes traitor scissors having a different hair-cutting sound" diff --git a/html/changelogs/AutoChangeLog-pr-4474.yml b/html/changelogs/AutoChangeLog-pr-4474.yml new file mode 100644 index 00000000000..eb58c1daf4a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4474.yml @@ -0,0 +1,4 @@ +author: Tastyfish +delete-after: True +changes: + - rscdel: "Removes n2 pills healing vox oxyloss, and o2 pills poisoning vox." diff --git a/html/changelogs/AutoChangeLog-pr-4477.yml b/html/changelogs/AutoChangeLog-pr-4477.yml new file mode 100644 index 00000000000..b0e53674ec0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4477.yml @@ -0,0 +1,5 @@ +author: FalseIncarnate +delete-after: True +changes: + - rscadd: "Adds 4 new types of fudge for the chef to make: Peanut, Chocolate Cherry, Cookies 'n' Cream, and Turtle Fudge." + - tweak: "Normal fudge recipe now uses milk instead of cream." diff --git a/html/changelogs/AutoChangeLog-pr-4485.yml b/html/changelogs/AutoChangeLog-pr-4485.yml new file mode 100644 index 00000000000..4888746f37f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4485.yml @@ -0,0 +1,4 @@ +author: Crazylemon64 +delete-after: True +changes: + - rscadd: "You can now fasten the circulators in the TEG kit with a wrench - no adminbus needed to set it up, now" diff --git a/icons/goonstation/mob/inhands/items_lefthand.dmi b/icons/goonstation/mob/inhands/items_lefthand.dmi index 5702ba238c1..3982141cbd0 100644 Binary files a/icons/goonstation/mob/inhands/items_lefthand.dmi and b/icons/goonstation/mob/inhands/items_lefthand.dmi differ diff --git a/icons/goonstation/mob/inhands/items_righthand.dmi b/icons/goonstation/mob/inhands/items_righthand.dmi index 9adcb9a22e8..d3b2dc7531f 100644 Binary files a/icons/goonstation/mob/inhands/items_righthand.dmi and b/icons/goonstation/mob/inhands/items_righthand.dmi differ diff --git a/icons/goonstation/objects/objects.dmi b/icons/goonstation/objects/objects.dmi new file mode 100644 index 00000000000..41523d18541 Binary files /dev/null and b/icons/goonstation/objects/objects.dmi differ diff --git a/icons/mob/AI.dmi b/icons/mob/AI.dmi index 1170fd94edb..13c653883ef 100644 Binary files a/icons/mob/AI.dmi and b/icons/mob/AI.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 3cd59fe3f74..a53d468804d 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index ba0e34aca9b..c649cee3ec2 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 248525081c6..c0b8af3b551 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index d6dacdce500..ceedd8011b9 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/species/drask/helmet.dmi b/icons/mob/species/drask/helmet.dmi index 3759f81fc41..0fdd257f0d9 100644 Binary files a/icons/mob/species/drask/helmet.dmi and b/icons/mob/species/drask/helmet.dmi differ diff --git a/icons/mob/species/tajaran/mask.dmi b/icons/mob/species/tajaran/mask.dmi index 9c3339e29e0..be155741185 100644 Binary files a/icons/mob/species/tajaran/mask.dmi and b/icons/mob/species/tajaran/mask.dmi differ diff --git a/icons/mob/species/unathi/mask.dmi b/icons/mob/species/unathi/mask.dmi index a37b45b4e96..db8c09807ef 100644 Binary files a/icons/mob/species/unathi/mask.dmi and b/icons/mob/species/unathi/mask.dmi differ diff --git a/icons/mob/species/vox/mask.dmi b/icons/mob/species/vox/mask.dmi index df31a6851ae..cd9c224051b 100644 Binary files a/icons/mob/species/vox/mask.dmi and b/icons/mob/species/vox/mask.dmi differ diff --git a/icons/mob/species/vulpkanin/mask.dmi b/icons/mob/species/vulpkanin/mask.dmi index 37aedd13592..d6baae8ab67 100644 Binary files a/icons/mob/species/vulpkanin/mask.dmi and b/icons/mob/species/vulpkanin/mask.dmi differ diff --git a/icons/obj/assemblies.dmi b/icons/obj/assemblies.dmi index 362ce9b00d4..a8d8e668828 100644 Binary files a/icons/obj/assemblies.dmi and b/icons/obj/assemblies.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 1e033f6746d..ff0fc2384c0 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/flag.dmi b/icons/obj/flag.dmi index b85010f3727..d1e0f08fa49 100644 Binary files a/icons/obj/flag.dmi and b/icons/obj/flag.dmi differ diff --git a/icons/obj/food/candy.dmi b/icons/obj/food/candy.dmi index ed86db2b0bd..4bf2f9b9862 100644 Binary files a/icons/obj/food/candy.dmi and b/icons/obj/food/candy.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 97ca0e00693..9c90b468860 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/surgery_drask.dmi b/icons/obj/surgery_drask.dmi index df2fd75a360..082d3e0f4f2 100644 Binary files a/icons/obj/surgery_drask.dmi and b/icons/obj/surgery_drask.dmi differ diff --git a/icons/obj/trash.dmi b/icons/obj/trash.dmi index 4b713b2129e..faea5fe4180 100644 Binary files a/icons/obj/trash.dmi and b/icons/obj/trash.dmi differ diff --git a/nano/templates/appearance_changer.tmpl b/nano/templates/appearance_changer.tmpl index 19e7fd4759b..886076f21d2 100644 --- a/nano/templates/appearance_changer.tmpl +++ b/nano/templates/appearance_changer.tmpl @@ -23,7 +23,7 @@
{{/if}} -{{if data.change_eye_color || data.change_skin_tone || data.change_skin_color || data.change_hair_color || data.change_facial_hair_color}} +{{if data.change_eye_color || data.change_skin_tone || data.change_skin_color || data.change_head_accessory_color || data.change_hair_color || data.change_facial_hair_color || data.change_marking_color}}
Colors: @@ -38,12 +38,31 @@ {{if data.change_skin_color}} {{:helper.link('Change skin color', null, { 'skin_color' : 1})}} {{/if}} + {{if data.change_head_accessory_color}} + {{:helper.link('Change head accessory color', null, { 'head_accessory_color' : 1})}} + {{/if}} {{if data.change_hair_color}} {{:helper.link('Change hair color', null, { 'hair_color' : 1})}} {{/if}} {{if data.change_facial_hair_color}} {{:helper.link('Change facial hair color', null, { 'facial_hair_color' : 1})}} {{/if}} + {{if data.change_marking_color}} + {{:helper.link('Change marking color', null, { 'marking_color' : 1})}} + {{/if}} +
+
+{{/if}} + +{{if data.change_head_accessory}} +
+
+ Head accessory styles: +
+
+ {{for data.head_accessory_styles}} + {{:helper.link(value.headaccessorystyle, null, { 'head_accessory' : value.headaccessorystyle}, null, data.head_accessory_style == value.headaccessorystyle ? 'selected' : null)}} + {{/for}}
{{/if}} @@ -73,3 +92,29 @@ {{/if}} + +{{if data.change_markings}} +
+
+ Marking styles: +
+
+ {{for data.marking_styles}} + {{:helper.link(value.markingstyle, null, { 'marking' : value.markingstyle}, null, data.marking_style == value.markingstyle ? 'selected' : null)}} + {{/for}} +
+
+{{/if}} + +{{if data.change_body_accessory}} +
+
+ Body accessory styles: +
+
+ {{for data.body_accessory_styles}} + {{:helper.link(value.bodyaccessorystyle, null, { 'body_accessory' : value.bodyaccessorystyle}, null, data.body_accessory_style == value.bodyaccessorystyle ? 'selected' : null)}} + {{/for}} +
+
+{{/if}} diff --git a/paradise.dme b/paradise.dme index 13b426256cd..fd78e01b975 100644 --- a/paradise.dme +++ b/paradise.dme @@ -224,12 +224,14 @@ #include "code\datums\diseases\fluspanish.dm" #include "code\datums\diseases\food_poisoning.dm" #include "code\datums\diseases\gbs.dm" +#include "code\datums\diseases\kuru.dm" #include "code\datums\diseases\magnitis.dm" #include "code\datums\diseases\pierrot_throat.dm" #include "code\datums\diseases\retrovirus.dm" #include "code\datums\diseases\rhumba_beat.dm" #include "code\datums\diseases\transformation.dm" #include "code\datums\diseases\tuberculosis.dm" +#include "code\datums\diseases\vampire.dm" #include "code\datums\diseases\wizarditis.dm" #include "code\datums\diseases\advance\advance.dm" #include "code\datums\diseases\advance\presets.dm" @@ -776,6 +778,7 @@ #include "code\game\objects\items\stacks\tiles\tile_types.dm" #include "code\game\objects\items\weapons\AI_modules.dm" #include "code\game\objects\items\weapons\alien_specific.dm" +#include "code\game\objects\items\weapons\bee_briefcase.dm" #include "code\game\objects\items\weapons\cards_ids.dm" #include "code\game\objects\items\weapons\cash.dm" #include "code\game\objects\items\weapons\caution.dm" @@ -860,6 +863,7 @@ #include "code\game\objects\items\weapons\implants\implantuplink.dm" #include "code\game\objects\items\weapons\melee\energy.dm" #include "code\game\objects\items\weapons\melee\misc.dm" +#include "code\game\objects\items\weapons\storage\artistic_toolbox.dm" #include "code\game\objects\items\weapons\storage\backpack.dm" #include "code\game\objects\items\weapons\storage\bags.dm" #include "code\game\objects\items\weapons\storage\belt.dm" @@ -1497,7 +1501,7 @@ #include "code\modules\mob\living\carbon\human\interactive\functions.dm" #include "code\modules\mob\living\carbon\human\interactive\interactive.dm" #include "code\modules\mob\living\carbon\human\interactive\prefabs.dm" -#include "code\modules\mob\living\carbon\human\species\abdcutor.dm" +#include "code\modules\mob\living\carbon\human\species\abductor.dm" #include "code\modules\mob\living\carbon\human\species\apollo.dm" #include "code\modules\mob\living\carbon\human\species\drask.dm" #include "code\modules\mob\living\carbon\human\species\golem.dm" @@ -2002,6 +2006,7 @@ #include "code\modules\surgery\organs\subtypes\machine.dm" #include "code\modules\surgery\organs\subtypes\misc.dm" #include "code\modules\surgery\organs\subtypes\nucleation.dm" +#include "code\modules\surgery\organs\subtypes\skrell.dm" #include "code\modules\surgery\organs\subtypes\standard.dm" #include "code\modules\surgery\organs\subtypes\unbreakable.dm" #include "code\modules\surgery\organs\subtypes\wryn.dm" diff --git a/sound/goonstation/effects/screech.ogg b/sound/goonstation/effects/screech.ogg new file mode 100644 index 00000000000..4a63299ea1d Binary files /dev/null and b/sound/goonstation/effects/screech.ogg differ diff --git a/sound/goonstation/misc/burp_alien.ogg b/sound/goonstation/misc/burp_alien.ogg new file mode 100644 index 00000000000..3f9bdf2ab3a Binary files /dev/null and b/sound/goonstation/misc/burp_alien.ogg differ diff --git a/sound/misc/briefcase_bees.ogg b/sound/misc/briefcase_bees.ogg new file mode 100644 index 00000000000..5483d9d5f91 Binary files /dev/null and b/sound/misc/briefcase_bees.ogg differ diff --git a/strings/chemistry_tools.json b/strings/chemistry_tools.json new file mode 100644 index 00000000000..28bfe60010b --- /dev/null +++ b/strings/chemistry_tools.json @@ -0,0 +1,474 @@ +{ + "CYBERPUNK_drug_prefixes": [ + "ace", + "acid", + "android", + "angel", + "arse", + "astro", + "atomic", + "azimuth", + "bandit", + "base", + "bear", + "big", + "bit", + "blood", + "blue", + "bog", + "borg", + "bronx", + "buffalo", + "butterfly", + "cactus", + "cancer", + "cat", + "chaos", + "cherub", + "cloud", + "crazy", + "creamy", + "crispy", + "cryo", + "crypto", + "crystal", + "cyber", + "dad's", + "dank", + "dapper", + "dead", + "death", + "deep", + "demon", + "desert", + "devil", + "discharge", + "disco", + "dog", + "dragon", + "duck", + "electro", + "evil", + "exo", + "exotic", + "farty", + "flux", + "flying", + "freak", + "freckle", + "fusion", + "gentlemen's", + "george", + "ghost", + "giga", + "glow", + "goon", + "grandma's", + "hardcore", + "harlem", + "heather", + "heavenly", + "hell", + "hungry", + "hydro", + "ice", + "india", + "iron", + "jazz", + "jelly", + "jersey", + "jungle", + "knockout", + "liquid", + "loony", + "loopy", + "lucky", + "lunar", + "macro", + "mad", + "magic", + "mama's", + "mars", + "marsh", + "mega", + "meteor", + "micro", + "monday", + "monkey", + "moon", + "motor", + "mountain", + "murder", + "naughty", + "necro", + "neon", + "nice", + "night", + "ninja", + "nuke", + "omega", + "omni", + "pain", + "paranoid", + "plasma", + "prism", + "puffer", + "puffy", + "quirky", + "racist", + "rainbow", + "red", + "rift", + "rock", + "rough", + "samurai", + "scan", + "secret", + "shitty", + "sick", + "sicknasty", + "silver", + "sine", + "skull", + "sky", + "slime", + "slimy", + "smooth", + "solar", + "solid", + "space", + "special", + "spotty", + "star", + "sticky", + "stray", + "swamp", + "tachyon", + "tech", + "techno", + "troll", + "turbo", + "turkey", + "uber", + "ultra", + "uncle's", + "uncle", + "unicorn", + "vacuum", + "vampire", + "vile", + "viral", + "void", + "volcano", + "vorpal", + "watt", + "wicked", + "willow", + "wizard", + "wobbly", + "yellow", + "zesty", + "zeta", + "zip", + "zone", + "parrot" + ], + "CYBERPUNK_drug_suffixes": [ + "2000", + "420", + "9", + "99", + "aftershave", + "balls", + "bang", + "bass", + "beans", + "beat", + "beep", + "bees", + "biscuits", + "bit", + "blit", + "blot", + "blue", + "bones", + "boop", + "booster", + "brawn", + "bread", + "bright", + "bubbles", + "bullet", + "burgers", + "butter", + "buttons", + "buzz", + "byte", + "ceramique", + "chasers", + "cheese", + "chill", + "chizz", + "clap", + "coins", + "cooking", + "crack", + "crush", + "dark", + "data", + "diablo", + "dreck", + "drool", + "drugs", + "dust", + "eels", + "eggs", + "fire", + "flash", + "flux", + "giblets", + "goblins", + "gold", + "goop", + "grease", + "green", + "grinder", + "gunge", + "hammer", + "hash", + "hog", + "hook", + "hounds", + "ice", + "ink", + "itch", + "jack", + "jane", + "jerks", + "jones", + "junk", + "kick", + "lasagne", + "lightning", + "lock", + "max", + "meat", + "medicine", + "melons", + "milk", + "mollies", + "mondays", + "music", + "nine", + "nip", + "nuggets", + "nugs", + "null", + "particulars", + "pepper", + "pies", + "ping", + "poofs", + "pot", + "powder", + "puffs", + "punch", + "quake", + "quarks", + "red", + "reef", + "riot", + "ripper", + "runoff", + "saliva", + "sass", + "saturdays", + "sauce", + "scum", + "shaker", + "shank", + "shit", + "shock", + "shredder", + "slurm", + "smash", + "smoke", + "smokes", + "smuds", + "snap", + "snow", + "spank", + "spice", + "spit", + "stank", + "stealth", + "sticks", + "sting", + "stink", + "sundays", + "sushi", + "tango", + "tears", + "theta", + "torpedo", + "tuber", + "turbo", + "volts", + "wafers", + "wave", + "weed", + "white", + "wiggle", + "wisps", + "zap", + "zero", + "zeta", + "zip" + ], + "CYBERPUNK_drug_primaries": [ + "bath_salts", + "crank", + "krokodil", + "methamphetamine", + "lsd", + "psilocybin", + "space_drugs", + "thc", + "jenkem", + "nicotine", + "haloperidol", + "ephedrine", + "epinephrine", + "omnizine", + "morphine", + "ketamine", + "diphenhydramine" + ], + "CYBERPUNK_drug_adulterants": [ + "mercury", + "lithium", + "plasma", + "fuel", + "itching_powder", + "capsaicin", + "histamine", + "ethanol", + "diethylamine", + "atrazine", + "clf3", + "aluminum", + "sugar", + "soybeanoil", + "hydrogenated_soybeanoil", + "phlogiston", + "cryostylane", + "toxin", + "neurotoxin2", + "sulfur", + "saltpetre", + "cyanide", + "formaldehyde", + "sacid", + "facid", + "lipolicide", + "mutagen", + "pancuronium", + "radium", + "uranium", + "polonium", + "sodium_thiopental", + "triplepiss", + "hairgrownium", + "iron", + "sulfonal", + "glowing_slurry", + "toxic_slurry", + "carpet", + "oil", + "ammonia", + "acetone", + "ectoplasm", + "fungus", + "cleaner", + "blood", + "ash", + "synthflesh", + "toiletwater", + "porktonium", + "corn_starch", + "corn_syrup", + "vhfcs", + "gravy", + "msg", + "egg", + "????", + "suicider", + "moonshine", + "prions", + "grave_dust", + "nanomachines", + "chlorine", + "fluorine" + ], + "CYBERPUNK_drug_adulterants_safe": [ + "mercury", + "lithium", + "plasma", + "fuel", + "capsaicin", + "ethanol", + "diethylamine", + "atrazine", + "aluminum", + "sugar", + "soybeanoil", + "phlogiston", + "cryostylane", + "sulfur", + "saltpetre", + "lipolicide", + "triplepiss", + "hairgrownium", + "iron", + "sulfonal", + "carpet", + "oil", + "ammonia", + "acetone", + "ectoplasm", + "fungus", + "cleaner", + "blood", + "ash", + "synthflesh", + "toiletwater", + "corn_starch", + "corn_syrup", + "gravy", + "msg", + "egg", + "????", + "chlorine", + "fluorine" + ], + "traitor_poison_bottle": [ + "sarin", + "cyanide", + "sulfonal", + "initropidril", + "coniine", + "venom", + "ketamine", + "amanitin", + "polonium", + "curare", + "pancuronium", + "sodium_thiopental", + "gibbis", + "nanomachines", + "prions", + "spidereggs", + "concentrated_initro", + "heartworms" + ] +} \ No newline at end of file