diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index aab249117a5..786aa534ed5 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) @@ -5414,7 +5414,7 @@ "caf" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 2; icon_state = "whitebluecorner"; tag = "icon-whitebluecorner"},/area/medical/medbay2) "cag" = (/obj/machinery/vending/medical,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel{tag = "icon-whiteblue (SOUTHEAST)"; icon_state = "whiteblue"; dir = 6},/area/medical/medbay2) "cah" = (/obj/effect/spawner/window/reinforced,/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/structure/disposalpipe/segment,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id_tag = "cmooffice"; name = "Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area/medical/cmo) -"cai" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/cmo) +"cai" = (/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/cmo) "caj" = (/obj/structure/stool/bed/chair/office/dark{dir = 1},/obj/effect/landmark/start{name = "Chief Medical Officer"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/cmo) "cak" = (/obj/machinery/prize_counter,/turf/simulated/floor/wood,/area/crew_quarters/bar) "cal" = (/obj/effect/spawner/window/reinforced,/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id_tag = "cmooffice"; name = "Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area/medical/cmo) @@ -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/_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/mind.dm b/code/datums/mind.dm index ea478d6b9e0..a3d9dbd8442 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 38f711500ff..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 @@ -628,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 @@ -683,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..5cfe1324849 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -68,6 +68,7 @@ projectilesound = 'sound/weapons/taser2.ogg' AIStatus = AI_OFF var/resources = 0 //Resource points, generated by consuming metal/glass + loot = list(/obj/effect/decal/cleanable/blood/gibs/robot, /obj/item/weapon/ore/bluespace_crystal/artificial) /mob/living/simple_animal/hostile/swarmer/Login() ..() @@ -91,14 +92,12 @@ /mob/living/simple_animal/hostile/swarmer/death() ..() - new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc) ghostize() qdel(src) /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..c50b4b04700 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) @@ -785,7 +785,7 @@ /obj/item/weapon/guardiancreator/tech name = "holoparasite injector" desc = "It contains alien nanoswarm of unknown origin. Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, it requires an organic host as a home base and source of fuel." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/hypo.dmi' icon_state = "combat_hypo" theme = "tech" mob_name = "Holoparasite" 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/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm index 6f97740f8d5..e255394e7af 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm @@ -42,6 +42,7 @@ var/cooldown = 0 var/gorecooldown = 0 var/vialspawned = FALSE + loot = list(/obj/effect/decal/cleanable/blood/innards, /obj/effect/decal/cleanable/blood, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic, /obj/item/organ/internal/heart/demon) var/playstyle_string = "You are the Slaughter Demon, a terrible creature from another existence. You have a single desire: To kill. \ You may Ctrl+Click on blood pools to travel through them, appearing and dissaapearing from the station at will. \ Pulling a dead or critical mob while you enter a pool will pull them in with you, allowing you to feast. \ @@ -79,17 +80,14 @@ else speed = 0 +/obj/effect/decal/cleanable/blood/innards + icon = 'icons/obj/surgery.dmi' + icon_state = "innards" + name = "pile of viscera" + desc = "A repulsive pile of guts and gore." + /mob/living/simple_animal/slaughter/death() ..() - var/obj/effect/decal/cleanable/blood/innards = new (get_turf(src)) - innards.icon = 'icons/obj/surgery.dmi' - innards.icon_state = "innards" - innards.name = "pile of viscera" - innards.desc = "A repulsive pile of guts and gore." - new /obj/effect/decal/cleanable/blood(loc) - new /obj/effect/gibspawner/generic(get_turf(src)) - new /obj/effect/gibspawner/generic(get_turf(src)) - new /obj/item/organ/internal/heart/demon(loc) playsound(get_turf(src),'sound/misc/demon_dies.ogg', 200, 1) visible_message("[src] screams in anger as it collapses into a puddle of viscera, its most recent meals spilling out of it.") for(var/mob/living/M in consumed_mobs) 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/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/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 0948c8ae3a1..d3cc5f089a0 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -967,7 +967,9 @@ name = "Spaceport Security" desc = "The Premier security forces for all spaceports found along the Orion Trail." faction = list("orion") - corpse = /obj/effect/landmark/mobcorpse/orionsecurity + loot = list(/obj/effect/landmark/mobcorpse/orionsecurity, + /obj/item/weapon/gun/projectile/automatic/c20r, + /obj/item/weapon/shield/energy) /obj/effect/landmark/mobcorpse/orionsecurity name = "Spaceport Security" 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 26d159e959a..c131c55ee49 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -799,6 +799,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)) @@ -1066,4 +1067,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/devices/floor_painter.dm b/code/game/objects/items/devices/floor_painter.dm new file mode 100644 index 00000000000..7fa9759e330 --- /dev/null +++ b/code/game/objects/items/devices/floor_painter.dm @@ -0,0 +1,98 @@ +// Floor painter + +/obj/item/device/floor_painter + name = "floor painter" + icon_state = "floor_painter" + + var/floor_icon + var/floor_state = "floor" + var/floor_dir = SOUTH + + w_class = 1 + item_state = "electronic" + flags = CONDUCT + slot_flags = SLOT_BELT + + var/static/list/allowed_states = list("arrival", "arrivalcorner", "bar", "barber", "blackcorner", "blue", "bluecorner", + "bluefull", "bluered", "blueyellow", "blueyellowfull", "bot", "brown", "browncorner", "browncornerold", "brownold", + "cafeteria", "caution", "cautioncorner", "chapel", "cmo", "dark", "delivery", "escape", "escapecorner", "floor", + "freezerfloor", "green", "greenblue", "greenbluefull", "greencorner", "greenfull", "greenyellow", + "greenyellowfull", "grimy", "loadingarea", "neutral", "neutralcorner", "neutralfull", "orange", "orangecorner", + "orangefull", "purple", "purplecorner", "purplefull", "rampbottom", "ramptop", "red", "redblue", "redbluefull", + "redcorner", "redfull", "redgreen", "redgreenfull", "redyellow", "redyellowfull", "warning", "warningcorner", "warnwhite", + "warnwhitecorner", "white", "whiteblue", "whitebluecorner", "whitebluefull", "whitebot", "whitecorner", "whitedelivery", + "whitegreen", "whitegreencorner", "whitegreenfull", "whitehall", "whitepurple", "whitepurplecorner", "whitepurplefull", + "whitered", "whiteredcorner", "whiteredfull", "whiteyellow", "whiteyellowcorner", "whiteyellowfull", "yellow", + "yellowcorner", "yellowcornersiding", "yellowsiding") + +/obj/item/device/floor_painter/afterattack(var/atom/A, var/mob/user, proximity, params) + if(!proximity) + return + + var/turf/simulated/floor/plasteel/F = A + if(!istype(F)) + to_chat(user, "\The [src] can only be used on station flooring.") + return + + F.icon_state = floor_state + F.icon_regular_floor = floor_state + F.dir = floor_dir + +/obj/item/device/floor_painter/attack_self(var/mob/user) + if(!user) + return 0 + user.set_machine(src) + interact(user) + return 1 + +/obj/item/device/floor_painter/interact(mob/user as mob) + if(!floor_icon) + floor_icon = icon('icons/turf/floors.dmi', floor_state, floor_dir) + user << browse_rsc(floor_icon, "floor.png") + var/dat = {" +
+ <- + + -> +
+ Choose Style +
Style: [floor_state]
+ Choose Direction +
Direction: [dir2text(floor_dir)]
+ "} + + var/datum/browser/popup = new(user, "floor_painter", name, 225, 300) + popup.set_content(dat) + popup.open() + +/obj/item/device/floor_painter/Topic(href, href_list) + if(..()) + return + + if(href_list["choose_state"]) + var/state = input("Please select a style", "[src]") as null|anything in allowed_states + if(state) + floor_state = state + floor_dir = SOUTH // Reset dir, because some icon_states might not have that dir. + if(href_list["choose_dir"]) + var/seldir = input("Please select a direction", "[src]") as null|anything in list("north", "south", "east", "west", "northeast", "northwest", "southeast", "southwest") + if(seldir) + floor_dir = text2dir(seldir) + if(href_list["cycleleft"]) + var/index = allowed_states.Find(floor_state) + index-- + if(index < 1) + index = allowed_states.len + floor_state = allowed_states[index] + floor_dir = SOUTH + if(href_list["cycleright"]) + var/index = allowed_states.Find(floor_state) + index++ + if(index > allowed_states.len) + index = 1 + floor_state = allowed_states[index] + floor_dir = SOUTH + + floor_icon = icon('icons/turf/floors.dmi', floor_state, floor_dir) + if(usr) + attack_self(usr) 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/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/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/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/dnascrambler.dm b/code/game/objects/items/weapons/dnascrambler.dm index 47bea6ca58d..2765b4a319d 100644 --- a/code/game/objects/items/weapons/dnascrambler.dm +++ b/code/game/objects/items/weapons/dnascrambler.dm @@ -1,16 +1,16 @@ /obj/item/weapon/dnascrambler name = "dna scrambler" desc = "An illegal genetic serum designed to randomize the user's identity." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/hypo.dmi' item_state = "syringe_0" - icon_state = "b10" + icon_state = "lepopen1" var/used = null update_icon() if(used) - icon_state = "b0" + icon_state = "lepopen0" else - icon_state = "b10" + icon_state = "lepopen1" attack(mob/M as mob, mob/user as mob) if(!M || !user) 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/legcuffs.dm b/code/game/objects/items/weapons/legcuffs.dm index fa485cbf93b..034dfc2ddc2 100644 --- a/code/game/objects/items/weapons/legcuffs.dm +++ b/code/game/objects/items/weapons/legcuffs.dm @@ -19,11 +19,15 @@ desc = "A trap used to catch bears and other legged creatures." var/armed = 0 var/obj/item/weapon/grenade/iedcasing/IED = null + var/obj/item/device/assembly/signaler/sig = null /obj/item/weapon/restraints/legcuffs/beartrap/Destroy() if(IED) qdel(IED) IED = null + if(sig) + qdel(sig) + sig = null return ..() /obj/item/weapon/restraints/legcuffs/beartrap/suicide_act(mob/user) @@ -43,6 +47,9 @@ if(IED) to_chat(user, "This beartrap already has an IED hooked up to it!") return + if(sig) + to_chat(user, "This beartrap already has a signaler hooked up to it!") + return IED = I switch(IED.assembled) if(0,1) //if it's not fueled/hooked up @@ -50,7 +57,7 @@ IED = null return if(2,3) - user.drop_item(src) + user.drop_item() I.forceMove(src) message_admins("[key_name_admin(user)] has rigged a beartrap with an IED.") log_game("[key_name(user)] has rigged a beartrap with an IED.") @@ -60,12 +67,33 @@ to_chat(user, "You shouldn't be reading this message! Contact a coder or someone, something broke!") IED = null return + if(istype(I, /obj/item/device/assembly/signaler)) + if(IED) + to_chat(user, "This beartrap already has an IED hooked up to it!") + return + if(sig) + to_chat(user, "This beartrap already has a signaler hooked up to it!") + return + sig = I + if(sig.secured) + to_chat(user, "The signaler is secured.") + sig = null + return + user.drop_item() + I.forceMove(src) + to_chat(user, "You sneak the [sig] underneath the pressure plate and connect the trigger wire.") + desc = "A trap used to catch bears and other legged creatures. There is a remote signaler hooked up to it." if(istype(I, /obj/item/weapon/screwdriver)) if(IED) IED.forceMove(get_turf(src)) IED = null to_chat(user, "You remove the IED from the [src].") return + if(sig) + sig.forceMove(get_turf(src)) + sig = null + to_chat(user, "You remove the signaler from the [src].") + return ..() /obj/item/weapon/restraints/legcuffs/beartrap/Crossed(AM as mob|obj) @@ -88,6 +116,9 @@ spawn(IED.det_time) IED.prime() + if(sig && isturf(src.loc)) + sig.signal() + if(ishuman(AM)) var/mob/living/carbon/H = AM if(H.lying) @@ -192,4 +223,4 @@ /obj/item/weapon/legcuffs/bolas/Bump() ..() - throw_failed() //allows a mech bolas to be destroyed \ No newline at end of file + throw_failed() //allows a mech bolas to be destroyed 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 7fb6806b5c0..090955de57a 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 f2d76051a37..46972243a06 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -498,6 +498,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 @@ -516,8 +517,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) @@ -558,7 +559,9 @@ client/proc/one_click_antag() for(var/i = 0, i___" // 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/clothing.dm b/code/modules/clothing/clothing.dm index 04f0f3ed42d..8d6595b73ff 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -25,6 +25,7 @@ var/active_sound = null var/toggle_cooldown = null var/cooldown = 0 + var/species_disguise = null //BS12: Species-restricted clothing check. /obj/item/clothing/mob_can_equip(M as mob, slot) diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 071c6032722..0fbb39e6f1b 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) @@ -216,6 +219,7 @@ item_state = "cardborg_h" flags = HEADCOVERSEYES | HEADCOVERSMOUTH flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + species_disguise = "High-tech robot" /obj/item/clothing/head/cardborg/equipped(mob/living/user, slot) ..() 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/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 5abc5e86cbf..7985eb06b57 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -206,6 +206,7 @@ item_state = "cardborg" body_parts_covered = UPPER_TORSO|LOWER_TORSO flags_inv = HIDEJUMPSUIT + species_disguise = "High-tech robot" /obj/item/clothing/suit/cardborg/equipped(mob/living/user, slot) ..() 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/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index d7ce6d9f49a..372e3df9a98 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -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..26637b8bf1b 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() ..() @@ -897,7 +897,7 @@ /obj/item/weapon/lazarus_injector name = "lazarus injector" desc = "An injector with a cocktail of nanomachines and chemicals, this device can seemingly raise animals from the dead, making them become friendly to the user. Unfortunately, the process is useless on higher forms of life and incredibly costly, so these were hidden in storage until an executive thought they'd be great motivation for some of their employees." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/hypo.dmi' icon_state = "lazarus_hypo" item_state = "hypo" throwforce = 0 diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 77afb5e2665..ed3c9bc5014 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..10dc8c41a1f 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,30 @@ 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 + if(istype(get_active_hand(), /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/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 714e9c45146..539d88f11cb 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -56,17 +56,22 @@ var/list/nospecies = list("Abductor", "Shadowling", "Neara", "Monkey", "Stok", "Farwa", "Wolpin") //species that won't show their race no matter what - if (skipjumpsuit && skipface || (species.name in nospecies)) //either obscured or on the nospecies list - msg += "!\n" //omit the species when examining - else if (species.name == "Slime People") //snowflakey because Slime People are defined as a plural + var/displayed_species = get_species() + for(var/obj/item/clothing/C in src) //Disguise checks + if (C == src.head || C == src.wear_suit || C == src.wear_mask || C == src.w_uniform || C == src.belt || C == src.back) + if(C.species_disguise) + displayed_species = C.species_disguise + if (skipjumpsuit && skipface || (displayed_species in nospecies)) //either obscured or on the nospecies list + msg += "!\n" //omit the species when examining + else if (displayed_species == "Slime People") //snowflakey because Slime People are defined as a plural msg += ", a slime person!\n" - else if (species.name == "Unathi") //DAMN YOU, VOWELS + else if (displayed_species == "Unathi") //DAMN YOU, VOWELS msg += ", a unathi!\n" else - msg += ", \a [lowertext(species.name)]!\n" + msg += ", \a [lowertext(displayed_species)]!\n" //uniform - if(w_uniform && !skipjumpsuit) + if(w_uniform && !skipjumpsuit && !(w_uniform.flags & ABSTRACT)) //Ties var/tie_msg if(istype(w_uniform,/obj/item/clothing/under)) @@ -80,14 +85,14 @@ msg += "[t_He] [t_is] wearing \icon[w_uniform] \a [w_uniform][tie_msg].\n" //head - if(head) + if(head && !(head.flags & ABSTRACT)) if(head.blood_DNA) msg += "[t_He] [t_is] wearing \icon[head] [head.gender==PLURAL?"some":"a"] [head.blood_color != "#030303" ? "blood-stained":"oil-stained"] [head.name] on [t_his] head!\n" else msg += "[t_He] [t_is] wearing \icon[head] \a [head] on [t_his] head.\n" //suit/armour - if(wear_suit) + if(wear_suit && !(wear_suit.flags & ABSTRACT)) if(wear_suit.blood_DNA) msg += "[t_He] [t_is] wearing \icon[wear_suit] [wear_suit.gender==PLURAL?"some":"a"] [wear_suit.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_suit.name]!\n" else @@ -101,7 +106,7 @@ msg += "[t_He] [t_is] carrying \icon[s_store] \a [s_store] on [t_his] [wear_suit.name].\n" //back - if(back) + if(back && !(back.flags & ABSTRACT)) if(back.blood_DNA) msg += "[t_He] [t_has] \icon[back] [back.gender==PLURAL?"some":"a"] [back.blood_color != "#030303" ? "blood-stained":"oil-stained"] [back] on [t_his] back.\n" else @@ -122,7 +127,7 @@ msg += "[t_He] [t_is] holding \icon[r_hand] \a [r_hand] in [t_his] right hand.\n" //gloves - if(gloves && !skipgloves) + if(gloves && !skipgloves && !(gloves.flags & ABSTRACT)) if(gloves.blood_DNA) msg += "[t_He] [t_has] \icon[gloves] [gloves.gender==PLURAL?"some":"a"] [gloves.blood_color != "#030303" ? "blood-stained":"oil-stained"] [gloves.name] on [t_his] hands!\n" else @@ -147,7 +152,7 @@ msg += "[t_He] [t_has] \icon[belt] \a [belt] about [t_his] waist.\n" //shoes - if(shoes && !skipshoes) + if(shoes && !skipshoes && !(shoes.flags & ABSTRACT)) if(shoes.blood_DNA) msg += "[t_He] [t_is] wearing \icon[shoes] [shoes.gender==PLURAL?"some":"a"] [shoes.blood_color != "#030303" ? "blood-stained":"oil-stained"] [shoes.name] on [t_his] feet!\n" else @@ -157,14 +162,14 @@ //mask - if(wear_mask && !skipmask) + if(wear_mask && !skipmask && !(wear_mask.flags & ABSTRACT)) if(wear_mask.blood_DNA) msg += "[t_He] [t_has] \icon[wear_mask] [wear_mask.gender==PLURAL?"some":"a"] [wear_mask.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_mask.name] on [t_his] face!\n" else msg += "[t_He] [t_has] \icon[wear_mask] \a [wear_mask] on [t_his] face.\n" //eyes - if(glasses && !skipeyes) + if(glasses && !skipeyes && !(glasses.flags & ABSTRACT)) if(glasses.blood_DNA) msg += "[t_He] [t_has] \icon[glasses] [glasses.gender==PLURAL?"some":"a"] [glasses.blood_color != "#030303" ? "blood-stained":"oil-stained"] [glasses] covering [t_his] eyes!\n" else diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 3e5cb90f380..7775830b4a0 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) @@ -1270,6 +1255,54 @@ else germ_level += n +/mob/living/carbon/human/proc/check_and_regenerate_organs(var/mob/living/carbon/human/H) //Regenerates missing limbs/organs. + var/list/types_of_int_organs = list() //This will hold all the types of organs in the mob before rejuvenation. + for(var/obj/item/organ/internal/I in H.internal_organs) + types_of_int_organs |= I.type //Compiling the list of organ types. It is possible for organs to be missing from this list if they are absent from the mob. + + //Removing stumps. + for(var/obj/item/organ/organ in H.contents) + if(istype(organ, /obj/item/organ/external/stump)) //Get rid of all stumps. + qdel(organ) + H.contents -= organ //Making sure the list entry is removed. + for(var/obj/item/organ/organ in H.organs) + if(istype(organ, /obj/item/organ/external/stump)) + qdel(organ) + H.organs -= organ //Making sure the list entry is removed. + for(var/organ_name in H.organs_by_name) + var/obj/item/organ/organ = H.organs_by_name[organ_name] + if(istype(organ, /obj/item/organ/external/stump) || !organ) //The !organ check is to account for mechanical limb (prostheses) losses, since those are handled in a way that leaves indexed but null list entries instead of stumps. + qdel(organ) + H.organs_by_name -= organ_name //Making sure the list entry is removed. + + //Replacing lost limbs with the species default. + var/mob/living/carbon/human/temp_holder + for(var/limb_type in H.species.has_limbs) + if(!(limb_type in H.organs_by_name)) + var/list/organ_data = H.species.has_limbs[limb_type] + var/limb_path = organ_data["path"] + var/obj/item/organ/external/O = new limb_path(temp_holder) + if(H.get_limb_by_name(O.name)) //Check to see if the user already has an limb with the same name as the 'missing limb'. If they do, skip regrowth. + continue //In an example, this will prevent duplication of the mob's right arm if the mob is a Human and they have a Diona right arm, since, + //while the limb with the name 'right_arm' the mob has may not be listed in their species' bodyparts definition, it is still viable and has the appropriate limb name. + else + O = new limb_path(H) //Create the limb on the player. + O.owner = H + H.organs |= H.organs_by_name[O.limb_name] + + //Replacing lost organs with the species default. + temp_holder = new /mob/living/carbon/human() + for(var/index in H.species.has_organ) + var/organ = H.species.has_organ[index] + if(!(organ in types_of_int_organs)) //If the mob is missing this particular organ... + var/obj/item/organ/internal/I = new organ(temp_holder) //Create the organ inside our holder so we can check it before implantation. + if(H.get_organ_slot(I.slot)) //Check to see if the user already has an organ in the slot the 'missing organ' belongs to. If they do, skip implantation. + continue //In an example, this will prevent duplication of the mob's eyes if the mob is a Human and they have Nucleation eyes, since, + //while the organ in the eyes slot may not be listed in the mob's species' organs definition, it is still viable and fits in the appropriate organ slot. + else + I = new organ(H) //Create the organ inside the player. + I.insert(H) + /mob/living/carbon/human/revive() if(species && !(species.flags & NO_BLOOD)) @@ -1277,9 +1310,18 @@ vessel.add_reagent(blood_reagent, max_blood-vessel.total_volume) fixblood() - // Fix up all organs. - // This will ignore any prosthetics in the prefs currently. - species.create_organs(src) + //Fix up all organs and replace lost ones. + restore_all_organs() //Rejuvenate and reset all existing organs. + check_and_regenerate_organs(src) //Regenerate limbs and organs only if they're really missing. + surgeries.Cut() //End all surgeries. + update_revive() + + if(species.name != "Skeleton" && (SKELETON in mutations)) + mutations.Remove(SKELETON) + if(NOCLONE in mutations) + mutations.Remove(NOCLONE) + if(HUSK in mutations) + mutations.Remove(HUSK) if(!client || !key) //Don't boot out anyone already in the mob. for (var/obj/item/organ/internal/brain/H in world) @@ -1505,6 +1547,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 +1652,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 +1670,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 +1980,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/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/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 03091a7e50f..f6a1e5e2088 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..65d100dc420 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,12 +271,26 @@ 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" male_scream_sound = 'sound/voice/shriek1.ogg' female_scream_sound = 'sound/voice/shriek1.ogg' + has_organ = list( + "heart" = /obj/item/organ/internal/heart, + "lungs" = /obj/item/organ/internal/lungs, + "liver" = /obj/item/organ/internal/liver, + "kidneys" = /obj/item/organ/internal/kidneys, + "brain" = /obj/item/organ/internal/brain, + "appendix" = /obj/item/organ/internal/appendix, + "eyes" = /obj/item/organ/internal/eyes, + "stack" = /obj/item/organ/internal/stack/vox //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used + ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. + suicide_messages = list( "is attempting to bite their tongue off!", "is jamming their claws into their eye sockets!", @@ -347,8 +381,8 @@ "kidneys" = /obj/item/organ/internal/kidneys, "brain" = /obj/item/organ/internal/brain, "eyes" = /obj/item/organ/internal/eyes, - "stack" = /obj/item/organ/internal/stack/vox - ) + "stack" = /obj/item/organ/internal/stack/vox //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used + ) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ. suicide_messages = list( "is attempting to bite their tongue off!", @@ -376,6 +410,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 +443,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 +614,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 +679,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 +694,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 +789,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 +832,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..45bc15b1d51 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]") @@ -574,6 +574,8 @@ var/global/list/damage_icon_parts = list() UpdateDamageIcon() update_icons() update_fire() + force_update_limbs() + update_tail_layer(0) /* --------------------------------------- */ //vvvvvv UPDATE_INV PROCS vvvvvv @@ -1265,22 +1267,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/living.dm b/code/modules/mob/living/living.dm index 175f3d186c4..f28e884f92f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -320,7 +320,6 @@ /mob/living/proc/revive() rejuvenate() - buckled = initial(src.buckled) if(iscarbon(src)) var/mob/living/carbon/C = src @@ -348,6 +347,8 @@ timeofdeath = 0 /mob/living/proc/rejuvenate() + var/mob/living/carbon/human/human_mob = null //Get this declared for use later. + // shut down various types of badness setToxLoss(0) setOxyLoss(0) @@ -366,6 +367,7 @@ drowsyness = 0 radiation = 0 druggy = 0 + hallucination = 0 nutrition = 400 bodytemperature = 310 sdisabilities = 0 @@ -380,7 +382,13 @@ fire_stacks = 0 on_fire = 0 suiciding = 0 - buckled = initial(src.buckled) + if(buckled) //Unbuckle the mob and clear the alerts. + buckled.buckled_mob = null + buckled = null + anchored = initial(src.anchored) + update_canmove() + clear_alert("buckled") + post_buckle_mob(src) if(iscarbon(src)) var/mob/living/carbon/C = src @@ -392,12 +400,13 @@ // restore all of the human's blood and reset their shock stage if(ishuman(src)) - var/mob/living/carbon/human/human_mob = src + human_mob = src human_mob.restore_blood() human_mob.shock_stage = 0 human_mob.decaylevel = 0 restore_all_organs() + surgeries.Cut() //End all surgeries. if(stat == DEAD) dead_mob_list -= src living_mob_list += src @@ -406,6 +415,9 @@ stat = CONSCIOUS update_fire() regenerate_icons() + if(human_mob) + human_mob.update_eyes() + human_mob.update_dna() return /mob/living/proc/UpdateDamageIcon() @@ -580,12 +592,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 /*////////////////////// @@ -835,4 +854,4 @@ if(slowed) tally += 10 - return tally \ No newline at end of file + return tally diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 9e27c836be2..c6d0d8e3ee0 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -166,8 +166,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) @@ -356,7 +361,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/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 6c630ec0117..c894b014a87 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -20,6 +20,7 @@ flying = 1 universal_speak = 1 var/list/construct_spells = list() + loot = list(/obj/item/weapon/reagent_containers/food/snacks/ectoplasm) /mob/living/simple_animal/construct/New() ..() @@ -31,7 +32,6 @@ /mob/living/simple_animal/construct/death() ..() - new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm (src.loc) for(var/mob/M in viewers(src, null)) if((M.client && !( M.blinded ))) M.show_message("\red [src] collapses in a shattered heap. ") diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index c824351a7c8..4f8b7753caf 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -603,6 +603,7 @@ var/emagged = 0 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) minbodytemp = 0 + loot = list(/obj/effect/decal/cleanable/blood/gibs/robot) /mob/living/simple_animal/pet/corgi/Ian/borgi/emag_act(user as mob) if(!emagged) @@ -651,7 +652,6 @@ /mob/living/simple_animal/pet/corgi/Ian/borgi/death() ..() visible_message("[src] blows apart!") - new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc) var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread s.set_up(3, 1, src) s.start() 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/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm index c5a656c8c66..94cf8dae65c 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm @@ -23,6 +23,7 @@ minbodytemp = 0 speak_emote = list("states") gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE + loot = list(/obj/effect/decal/cleanable/blood/gibs/robot) /mob/living/simple_animal/hostile/hivebot/range name = "Hivebot" @@ -41,12 +42,12 @@ 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() ..() visible_message("[src] blows apart!") - new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc) var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread s.set_up(3, 1, src) s.start() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 53dd934cb6a..83fa25b0651 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..6d2efd88010 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -73,6 +73,8 @@ aggro_vision_range = 9 idle_vision_range = 2 turns_per_move = 5 + loot = list(/obj/item/weapon/ore/diamond{layer = 4.1}, + /obj/item/weapon/ore/diamond{layer = 4.1}) /obj/item/projectile/temp/basilisk name = "freezing blast" @@ -100,14 +102,6 @@ if(3.0) adjustBruteLoss(110) -/mob/living/simple_animal/hostile/asteroid/basilisk/death() - if(stat != DEAD) - var/counter - for(counter=0, counter<2, counter++) - var/obj/item/weapon/ore/diamond/D = new /obj/item/weapon/ore/diamond(src.loc) - D.layer = 4.1 - ..() - /mob/living/simple_animal/hostile/asteroid/goldgrub name = "goldgrub" desc = "A worm that grows fat from eating everything in its sight. Seems to enjoy precious metals and other shiny things, hence the name." @@ -204,7 +198,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 ..() @@ -239,6 +233,7 @@ retreat_distance = 3 minimum_distance = 3 pass_flags = PASSTABLE + loot = list(/obj/item/organ/internal/hivelord_core) /mob/living/simple_animal/hostile/asteroid/hivelord/OpenFire(var/the_target) var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood(src.loc) @@ -250,11 +245,6 @@ /mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget() OpenFire() -/mob/living/simple_animal/hostile/asteroid/hivelord/death() - if(stat != DEAD) - new /obj/item/organ/internal/hivelord_core(src.loc) - ..() - /obj/item/organ/internal/hivelord_core name = "hivelord remains" desc = "All that remains of a hivelord, it seems to be what allows it to break pieces of itself off without being hurt... its healing properties will soon become inert if not used quickly. Try not to think about what you're eating." @@ -370,6 +360,7 @@ idle_vision_range = 5 anchored = 1 //Stays anchored until death as to be unpullable var/pre_attack = 0 + loot = list(/obj/item/asteroid/goliath_hide{layer = 4.1}) /mob/living/simple_animal/hostile/asteroid/goliath/process_ai() ..() @@ -386,13 +377,6 @@ anchored = 1 ..() -/mob/living/simple_animal/hostile/asteroid/goliath/death() - anchored = 0 - if(stat != DEAD) - var/obj/item/asteroid/goliath_hide/G = new /obj/item/asteroid/goliath_hide(src.loc) - G.layer = 4.1 - ..() - /mob/living/simple_animal/hostile/asteroid/goliath/OpenFire() var/tturf = get_turf(target) if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen @@ -403,7 +387,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/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index fbbc0d0a5e3..89835092ffd 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -22,9 +22,8 @@ atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) unsuitable_atmos_damage = 15 speak_emote = list("yarrs") - var/corpse = /obj/effect/landmark/mobcorpse/pirate - var/weapon1 = /obj/item/weapon/melee/energy/sword/pirate - + loot = list(/obj/effect/landmark/mobcorpse/pirate, + /obj/item/weapon/melee/energy/sword/pirate) faction = list("pirate") /mob/living/simple_animal/hostile/pirate/ranged @@ -38,16 +37,12 @@ retreat_distance = 5 minimum_distance = 5 projectiletype = /obj/item/projectile/beam - corpse = /obj/effect/landmark/mobcorpse/pirate/ranged - weapon1 = /obj/item/weapon/gun/energy/laser + loot = list(/obj/effect/landmark/mobcorpse/pirate/ranged, + /obj/item/weapon/gun/energy/laser) /mob/living/simple_animal/hostile/pirate/death() ..() - if(corpse) - new corpse (src.loc) - if(weapon1) - new weapon1 (src.loc) ghostize() qdel(src) return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm index 5ee52bec825..71d088a425c 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm @@ -150,8 +150,8 @@ walk(src,0) /mob/living/simple_animal/hostile/retaliate/malf_drone/death() - src.visible_message("\blue \icon[src] [src] suddenly breaks apart.") ..() + visible_message("\blue \icon[src] [src] suddenly breaks apart.") qdel(src) /mob/living/simple_animal/hostile/retaliate/malf_drone/Destroy() //Seriously, what the actual hell. 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 a58223acb04..2e3718cd800 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/retaliate/undead.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm index 44de372550f..210ff43ebda 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm @@ -45,6 +45,7 @@ minbodytemp = 0 faction = list("undead") // did I mention ghost + loot = list(/obj/item/weapon/reagent_containers/food/snacks/ectoplasm) /mob/living/simple_animal/hostile/retaliate/ghost/Process_Spacemove(var/check_drift = 0) return 1 @@ -61,7 +62,7 @@ invisibility = pick(0,60,60,invisibility) ..() /mob/living/simple_animal/hostile/retaliate/ghost/death() - new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm(loc) + ..() qdel(src) return @@ -90,9 +91,10 @@ minbodytemp = 0 faction = list("undead") + loot = list(/obj/effect/decal/remains/human) /mob/living/simple_animal/hostile/retaliate/skeleton/death() - new /obj/effect/decal/remains/human(loc) + ..() qdel(src) return @@ -121,8 +123,9 @@ minbodytemp = 0 faction = list("undead") + loot = list(/obj/effect/decal/cleanable/blood/gibs) /mob/living/simple_animal/hostile/retaliate/zombie/death() - new /obj/effect/decal/cleanable/blood/gibs(loc) + ..() qdel(src) return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index 35cdbb14dfb..148eeeef9a7 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -19,35 +19,30 @@ attacktext = "punches" attack_sound = 'sound/weapons/punch1.ogg' a_intent = I_HARM - var/corpse = /obj/effect/landmark/mobcorpse/russian - var/weapon1 = /obj/item/weapon/kitchen/knife unsuitable_atmos_damage = 15 faction = list("russian") status_flags = CANPUSH + loot = list(/obj/effect/landmark/mobcorpse/russian, + /obj/item/weapon/kitchen/knife) /mob/living/simple_animal/hostile/russian/ranged icon_state = "russianranged" icon_living = "russianranged" - corpse = /obj/effect/landmark/mobcorpse/russian/ranged - weapon1 = /obj/item/weapon/gun/projectile/revolver/mateba ranged = 1 retreat_distance = 5 minimum_distance = 5 projectiletype = /obj/item/projectile/bullet projectilesound = 'sound/weapons/Gunshot.ogg' casingtype = /obj/item/ammo_casing/a357 + loot = list(/obj/effect/landmark/mobcorpse/russian/ranged, /obj/item/weapon/gun/projectile/revolver/mateba) -/mob/living/simple_animal/hostile/russian/ranged/New() - if(prob(50) && ispath(weapon1,/obj/item/weapon/gun/projectile/revolver/mateba)) //to preserve varedits - weapon1 = /obj/item/weapon/gun/projectile/shotgun/boltaction - casingtype = /obj/item/ammo_casing/a762 +/mob/living/simple_animal/hostile/russian/ranged/mosin + loot = list(/obj/effect/landmark/mobcorpse/russian/ranged, + /obj/item/weapon/gun/projectile/shotgun/boltaction) + casingtype = /obj/item/ammo_casing/a762 /mob/living/simple_animal/hostile/russian/death() ..() - if(corpse) - new corpse (src.loc) - if(weapon1) - new weapon1 (src.loc) qdel(src) return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 4d6688aa75b..5546547046d 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -19,22 +19,14 @@ attacktext = "punches" attack_sound = 'sound/weapons/punch1.ogg' a_intent = I_HARM - var/corpse = /obj/effect/landmark/mobcorpse/syndicatesoldier - var/weapon1 - var/weapon2 unsuitable_atmos_damage = 15 faction = list("syndicate") check_friendly_fire = 1 status_flags = CANPUSH + loot = list(/obj/effect/landmark/mobcorpse/syndicatesoldier) /mob/living/simple_animal/hostile/syndicate/death() ..() - if(corpse) - new corpse (src.loc) - if(weapon1) - new weapon1 (src.loc) - if(weapon2) - new weapon2 (src.loc) qdel(src) return @@ -45,11 +37,10 @@ melee_damage_upper = 25 icon_state = "syndicatemelee" icon_living = "syndicatemelee" - weapon1 = /obj/item/weapon/melee/energy/sword/saber/red - weapon2 = /obj/item/weapon/shield/energy attacktext = "slashes" attack_sound = 'sound/weapons/bladeslice.ogg' status_flags = 0 + loot = list(/obj/effect/landmark/mobcorpse/syndicatesoldier, /obj/item/weapon/melee/energy/sword/saber/red, /obj/item/weapon/shield/energy) /mob/living/simple_animal/hostile/syndicate/melee/attackby(var/obj/item/O as obj, var/mob/user as mob, params) if(O.force) @@ -71,7 +62,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 @@ -83,8 +74,8 @@ icon_state = "syndicatemeleespace" icon_living = "syndicatemeleespace" name = "Syndicate Commando" - corpse = /obj/effect/landmark/mobcorpse/syndicatecommando speed = 1 + loot = list(/obj/effect/landmark/mobcorpse/syndicatecommando, /obj/item/weapon/melee/energy/sword/saber/red, /obj/item/weapon/shield/energy) /mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(var/movement_dir = 0) return @@ -99,8 +90,7 @@ casingtype = /obj/item/ammo_casing/c45 projectilesound = 'sound/weapons/Gunshot_smg.ogg' projectiletype = /obj/item/projectile/bullet/midbullet2 - - weapon1 = /obj/item/weapon/gun/projectile/automatic/c20r + loot = list(/obj/effect/landmark/mobcorpse/syndicatesoldier, /obj/item/weapon/gun/projectile/automatic/c20r) /mob/living/simple_animal/hostile/syndicate/ranged/space icon_state = "syndicaterangedpsace" @@ -108,8 +98,9 @@ name = "Syndicate Commando" 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) minbodytemp = 0 - corpse = /obj/effect/landmark/mobcorpse/syndicatecommando speed = 1 + loot = list(/obj/effect/landmark/mobcorpse/syndicatecommando, /obj/item/weapon/gun/projectile/automatic/c20r) + /mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(var/movement_dir = 0) return diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index bd39b681978..b47312b15df 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -28,6 +28,7 @@ minbodytemp = 0 faction = list("hostile", "winter") + loot = list(/obj/item/stack/sheet/wood) gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE /mob/living/simple_animal/hostile/tree/FindTarget() @@ -46,5 +47,4 @@ /mob/living/simple_animal/hostile/tree/death() ..() visible_message("\red [src] is hacked into pieces!") - new /obj/item/stack/sheet/wood(loc) qdel(src) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm index 5710005846c..12ede5955ea 100644 --- a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm @@ -20,15 +20,12 @@ melee_damage_lower = 3 melee_damage_upper = 7 - var/weapon1 - /mob/living/simple_animal/hostile/winter/snowman name = "snowman" desc = "A very angry snowman. Doesn't look like it wants to play around..." icon_state = "snowman" icon_living = "snowman" icon_dead = "snowman-dead" - weapon1 = /obj/item/weapon/melee/candy_sword bodytemperature = 73.0 //it's made of snow and hatred, so it's pretty cold. maxbodytemp = 280.15 //at roughly 7 C, these will start melting (dying) from the warmth. Mind over matter or something. @@ -37,10 +34,10 @@ /mob/living/simple_animal/hostile/winter/snowman/death() - if(weapon1 && prob(50)) //50% chance to drop weapon on death, if it has one to drop - new weapon1(get_turf(src)) + if(prob(50)) //50% chance to drop weapon on death, if it has one to drop + loot = list(/obj/item/weapon/melee/candy_sword) if(prob(20)) //chance to become a stationary snowman structure instead of a corpse - new /obj/structure/snowman(get_turf(src)) + loot.Add(/obj/structure/snowman) visible_message("The [src.name] shimmers as its animating magic fades away!") ..() //this is just to make sure it gets properly killed before we qdel it qdel(src) @@ -52,7 +49,6 @@ retreat_distance = 5 minimum_distance = 5 projectiletype = /obj/item/projectile/snowball - weapon1 = null /mob/living/simple_animal/hostile/winter/reindeer name = "reindeer" diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 0e01aa51894..9aff96b1fcf 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -24,11 +24,11 @@ status_flags = 0 faction = list("cult") status_flags = CANPUSH + loot = list(/obj/item/weapon/reagent_containers/food/snacks/ectoplasm) death() ..() - new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm (src.loc) for(var/mob/M in viewers(src, null)) if((M.client && !( M.blinded ))) M.show_message("\red [src] lets out a contented sigh as their form unwinds. ") diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 45f2c6789c9..9eee62d810a 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -71,6 +71,7 @@ var/master_commander = null //holding var for determining who own/controls a sentient simple animal (for sentience potions). var/sentience_type = SENTIENCE_ORGANIC // Sentience type, for slime potions + var/list/loot = list() //list of things spawned at mob's loc when it dies /mob/living/simple_animal/New() @@ -269,8 +270,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 +406,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 @@ -470,6 +468,9 @@ stat(null, "Health: [round((health / maxHealth) * 100)]%") /mob/living/simple_animal/death(gibbed) + if(loot.len) + for(var/i in loot) + new i(loc) health = 0 icon_state = icon_dead stat = DEAD @@ -492,25 +493,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 +672,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_helpers.dm b/code/modules/mob/mob_helpers.dm index 29577af9526..6e0645866d5 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -1,10 +1,3 @@ - -// fun if you want to typecast humans/monkeys/etc without writing long path-filled lines. -/proc/ishuman(A) - if(istype(A, /mob/living/carbon/human)) - return 1 - return 0 - /proc/issmall(A) if(A && istype(A, /mob/living/carbon/human)) var/mob/living/carbon/human/H = A @@ -12,56 +5,6 @@ return 1 return 0 -/proc/isbrain(A) - if(A && istype(A, /mob/living/carbon/brain)) - return 1 - return 0 - -/proc/isalien(A) - if(istype(A, /mob/living/carbon/alien)) - return 1 - return 0 - -/proc/isalienadult(A) - if(istype(A, /mob/living/carbon/alien/humanoid)) - return 1 - return 0 - -/proc/islarva(A) - if(istype(A, /mob/living/carbon/alien/larva)) - return 1 - return 0 - -proc/isfacehugger(A) - if(istype(A, /obj/item/clothing/mask/facehugger)) - return 1 - return 0 - -proc/isembryo(A) - if(istype(A, /obj/item/organ/internal/body_egg/alien_embryo)) - return 1 - return 0 - -/proc/isslime(A) - if(istype(A, /mob/living/carbon/slime)) - return 1 - return 0 - -/proc/isrobot(A) - if(istype(A, /mob/living/silicon/robot)) - return 1 - return 0 - -/proc/isanimal(A) - if(istype(A, /mob/living/simple_animal)) - return 1 - return 0 - -/proc/iscorgi(A) - if(istype(A, /mob/living/simple_animal/pet/corgi)) - return 1 - return 0 - /proc/ispet(A) if(istype(A, /mob/living/simple_animal)) var/mob/living/simple_animal/SA = A @@ -69,46 +12,6 @@ proc/isembryo(A) return 1 return 0 -/proc/iscrab(A) - if(istype(A, /mob/living/simple_animal/crab)) - return 1 - return 0 - -/proc/iscat(A) - if(istype(A, /mob/living/simple_animal/pet/cat)) - return 1 - return 0 - -/proc/ismouse(A) - if(istype(A, /mob/living/simple_animal/mouse)) - return 1 - return 0 - -/proc/isbear(A) - if(istype(A, /mob/living/simple_animal/hostile/bear)) - return 1 - return 0 - -/proc/iscarp(A) - if(istype(A, /mob/living/simple_animal/hostile/carp)) - return 1 - return 0 - -/proc/isbot(A) - if(istype(A, /mob/living/simple_animal/bot)) - return 1 - return 0 - -/proc/isclown(A) - if(istype(A, /mob/living/simple_animal/hostile/retaliate/clown)) - return 1 - return 0 - -/proc/isAI(A) - if(istype(A, /mob/living/silicon/ai)) - return 1 - return 0 - /mob/proc/isSynthetic() return 0 @@ -119,76 +22,6 @@ proc/isembryo(A) return 0 return 1 -/proc/isAIEye(A) - if(istype(A, /mob/camera/aiEye)) - return 1 - return 0 - -/proc/ispAI(A) - if(istype(A, /mob/living/silicon/pai)) - return 1 - return 0 - -/proc/iscarbon(A) - if(istype(A, /mob/living/carbon)) - return 1 - return 0 - -/proc/issilicon(A) - if(istype(A, /mob/living/silicon)) - return 1 - return 0 - -/proc/isSilicon(A) // Bay support - if(istype(A, /mob/living/silicon)) - return 1 - return 0 - -/proc/isliving(A) - if(istype(A, /mob/living)) - return 1 - return 0 - -/proc/isswarmer(A) - if(istype(A, /mob/living/simple_animal/hostile/swarmer)) - return 1 - return 0 - -/proc/isguardian(A) - if(istype(A, /mob/living/simple_animal/hostile/guardian)) - return 1 - return 0 - -/proc/isobserver(A) - if(istype(A, /mob/dead/observer)) - return 1 - return 0 - -/proc/isSpirit(A) - if(istype(A, /mob/spirit)) - return 1 - return 0 - -proc/isovermind(A) - if(istype(A, /mob/camera/blob)) - return 1 - return 0 - -/proc/ismask(A) - if(istype(A, /mob/spirit/mask)) - return 1 - return 0 - -/proc/isAutoAnnouncer(A) - if(istype(A, /mob/living/automatedannouncer)) - return 1 - return 0 - -/proc/isorgan(A) - if(istype(A, /obj/item/organ/external)) - return 1 - return 0 - /proc/isloyal(A) //Checks to see if the person contains a loyalty implant, then checks that the implant is actually inside of them for(var/obj/item/weapon/implant/loyalty/L in A) if(L && L.implanted) @@ -220,14 +53,6 @@ proc/isNonCrewAntag(A) return 1 -proc/isnewplayer(A) - if(istype(A, /mob/new_player)) - return 1 - return 0 - -proc/hasorgans(A) - return ishuman(A) - proc/iscuffed(A) if(istype(A, /mob/living/carbon)) var/mob/living/carbon/C = A @@ -255,10 +80,6 @@ proc/getsensorlevel(A) return U.sensor_mode return SUIT_SENSOR_OFF -/proc/is_admin(var/mob/user) - return check_rights(R_ADMIN, 0, user) != 0 - - /proc/check_zone(zone) if(!zone) return "chest" switch(zone) @@ -412,6 +233,24 @@ proc/Gibberish(t, p)//t is the inputted message, and any value higher than 70 fo return returntext +proc/muffledspeech(phrase) + phrase = html_decode(phrase) + var/leng=lentext(phrase) + var/counter=lentext(phrase) + var/newphrase="" + var/newletter="" + while(counter>=1) + newletter=copytext(phrase,(leng-counter)+1,(leng-counter)+2) + if(newletter in list(" ", "!", "?", ".", ",")) + //do nothing + else if(lowertext(newletter) in list("a", "e", "i", "o", "u", "y")) + newletter = "ph" + else + newletter = "m" + newphrase+="[newletter]" + counter-=1 + return newphrase + /proc/shake_camera(mob/M, duration, strength=1) if(!M || !M.client || M.shakecamera) @@ -537,8 +376,7 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM) return P /proc/get_both_hands(mob/living/carbon/M) - var/list/hands = list(M.l_hand, M.r_hand) - return hands + return list(M.l_hand, M.r_hand) //Direct dead say used both by emote and say 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 a9b10f8224f..a8667567d03 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 ac3dd8af716..ea70bbe88ac 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -319,6 +319,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/drugs.dm b/code/modules/reagents/newchem/drugs.dm index 127a37593d1..20607ac87a4 100644 --- a/code/modules/reagents/newchem/drugs.dm +++ b/code/modules/reagents/newchem/drugs.dm @@ -242,10 +242,6 @@ addiction_chance = 60 metabolization_rate = 0.6 -/datum/reagent/methamphetamine/meth2 //for donk pockets - id = "methamphetamine2" - addiction_chance = 0 - /datum/reagent/methamphetamine/on_mob_life(var/mob/living/M as mob) if(!M) M = holder.my_atom if(prob(5)) @@ -337,9 +333,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/medicine.dm b/code/modules/reagents/newchem/medicine.dm index aca5897735c..33f04d5e6a8 100644 --- a/code/modules/reagents/newchem/medicine.dm +++ b/code/modules/reagents/newchem/medicine.dm @@ -646,11 +646,14 @@ datum/reagent/strange_reagent metabolization_rate = 0.2 datum/reagent/strange_reagent/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume) - if(istype(M, /mob/living/simple_animal)) + if(isanimal(M)) if(method == TOUCH) - if(M.stat == DEAD) - M.revive() - M.visible_message("[M] seems to rise from the dead!") + var/mob/living/simple_animal/SM = M + if(SM.stat == DEAD) + SM.revive() + SM.loot.Cut() //no abusing strange reagent for unlimited farming of resources + SM.visible_message("[M] seems to rise from the dead!") + if(istype(M, /mob/living/carbon)) if(method == INGEST) if(M.stat == DEAD) diff --git a/code/modules/reagents/newchem/other.dm b/code/modules/reagents/newchem/other.dm index 7ef7dff6ff5..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)) 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/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/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index b92aceb4c79..9d67bb22881 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -2,7 +2,7 @@ /obj/item/weapon/reagent_containers/borghypo name = "Cyborg Hypospray" desc = "An advanced chemical synthesizer and injection system, designed for heavy-duty medical equipment." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/hypo.dmi' item_state = "hypo" icon_state = "borghypo" amount_per_transfer_from_this = 5 @@ -23,7 +23,7 @@ /obj/item/weapon/reagent_containers/borghypo/crisis reagent_ids = list("salglu_solution", "epinephrine", "sal_acid") - + /obj/item/weapon/reagent_containers/borghypo/syndicate name = "syndicate cyborg hypospray" desc = "An experimental piece of Syndicate technology used to produce powerful restorative nanites used to very quickly restore injuries of all types. Also metabolizes potassium iodide, for radiation poisoning, and morphine, for offense." diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 902892d3f7e..8538db0b13d 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -25,7 +25,7 @@ to_chat(user, "You finish eating \the [src].") user.visible_message("[user] finishes eating \the [src].") user.unEquip(src) //so icons update :[ - + Post_Consume(M) if(trash) if(ispath(trash,/obj/item)) var/obj/item/TrashItem = new trash(user) @@ -35,6 +35,9 @@ qdel(src) return +/obj/item/weapon/reagent_containers/food/snacks/proc/Post_Consume(mob/living/M) + return + /obj/item/weapon/reagent_containers/food/snacks/attack_self(mob/user as mob) return @@ -756,27 +759,32 @@ desc = "The food of choice for the seasoned traitor." icon_state = "donkpocket" filling_color = "#DEDEAB" + New() ..() reagents.add_reagent("nutriment", 4) - reagents.add_reagent("omnizine", 4) + + Post_Consume(mob/living/M) + M.reagents.add_reagent("omnizine", 15) /obj/item/weapon/reagent_containers/food/snacks/syndidonkpocket name = "Donk-pocket" desc = "This donk-pocket is emitting a small amount of heat." icon_state = "donkpocket" filling_color = "#DEDEAB" - volume = 90 bitesize = 100 //nom the whole thing at once. New() ..() - reagents.add_reagent("omnizine", 15) - reagents.add_reagent("teporone", 15) - reagents.add_reagent("synaptizine", 15) - reagents.add_reagent("salglu_solution", 15) - reagents.add_reagent("salbutamol", 15) - reagents.add_reagent("methamphetamine2", 15) + reagents.add_reagent("nutriment", 1) + + Post_Consume(mob/living/M) + M.reagents.add_reagent("omnizine", 15) + M.reagents.add_reagent("teporone", 15) + M.reagents.add_reagent("synaptizine", 15) + M.reagents.add_reagent("salglu_solution", 15) + M.reagents.add_reagent("salbutamol", 15) + M.reagents.add_reagent("methamphetamine", 15) /obj/item/weapon/reagent_containers/food/snacks/brainburger name = "brainburger" 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/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 22466811e3e..a9181138a85 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -5,7 +5,7 @@ /obj/item/weapon/reagent_containers/hypospray name = "hypospray" desc = "The DeForest Medical Corporation hypospray is a sterile, air-needle autoinjector for rapid administration of drugs to patients." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/obj/hypo.dmi' item_state = "hypo" icon_state = "hypo" amount_per_transfer_from_this = 5 diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index e95e213fd9f..bd8a22cd06f 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -8,7 +8,7 @@ /obj/item/weapon/reagent_containers/syringe name = "Syringe" desc = "A syringe." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/goonstation/objects/syringe.dmi' item_state = "syringe_0" icon_state = "0" amount_per_transfer_from_this = 5 @@ -336,7 +336,7 @@ /obj/item/weapon/reagent_containers/ld50_syringe name = "Lethal Injection Syringe" desc = "A syringe used for lethal injections." - icon = 'icons/obj/syringe.dmi' + icon = 'icons/goonstation/objects/syringe.dmi' item_state = "syringe_0" icon_state = "0" amount_per_transfer_from_this = 50 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/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index b5d44579d07..8337e0ffaf7 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -688,6 +688,14 @@ build_path = /obj/item/weapon/hand_labeler category = list("initial", "Electronics") +/datum/design/floorpainter + name = "Floor painter" + id = "floor_painter" + build_type = AUTOLATHE + materials = list(MAT_METAL = 150, MAT_GLASS = 125) + build_path = /obj/item/device/floor_painter + category = list("initial", "Electronics") + /datum/design/logic_board name = "Logic Circuit" id = "logic_board" 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/helpers.dm b/code/modules/surgery/organs/helpers.dm index 29bd9801b26..a61537f1985 100644 --- a/code/modules/surgery/organs/helpers.dm +++ b/code/modules/surgery/organs/helpers.dm @@ -40,4 +40,9 @@ return O /proc/is_int_organ(atom/A) - return istype(A, /obj/item/organ/internal) \ No newline at end of file + return istype(A, /obj/item/organ/internal) + +/mob/living/carbon/human/proc/get_limb_by_name(limb_name) //Look for a limb with the given limb name in the source mob, and return it if found. + for(var/obj/item/organ/external/O in organs) + if(limb_name == O.limb_name) + return O diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm index 3bce602694a..9c1398c6405 100644 --- a/code/modules/surgery/organs/organ.dm +++ b/code/modules/surgery/organs/organ.dm @@ -176,7 +176,12 @@ var/list/organ_cache = list() /obj/item/organ/proc/rejuvenate() damage = 0 germ_level = 0 - status &= ~ORGAN_DEAD + if(status & ORGAN_ROBOT) //Robotic organs stay robotic. + status = ORGAN_ROBOT + else if (status & ORGAN_ASSISTED) //Assisted organs stay assisted. + status = ORGAN_ASSISTED + else + status = 0 if(!owner) processing_objects |= src diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index ac96bd0f775..d0245c224d9 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -308,14 +308,20 @@ This function completely restores a damaged organ to perfect condition. */ /obj/item/organ/external/rejuvenate() damage_state = "00" - if(status & 128) //Robotic organs stay robotic. Fix because right click rejuvinate makes IPC's organs organic. - status = 128 + if(status & ORGAN_ROBOT) //Robotic organs stay robotic. + status = ORGAN_ROBOT + else if (status & ORGAN_ASSISTED) //Assisted organs stay assisted. + status = ORGAN_ASSISTED else status = 0 germ_level = 0 perma_injury = 0 brute_dam = 0 burn_dam = 0 + open = 0 //Closing all wounds. + wounds.Cut() //Clears all wounds! Good as new. + if(istype(src, /obj/item/organ/external/head) && disfigured) //If their head's disfigured, refigure it. + disfigured = 0 // handle internal organs for(var/obj/item/organ/internal/current_organ in internal_organs) 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/modules/vehicle/ambulance.dm b/code/modules/vehicle/ambulance.dm index 526b1e2c0a9..7d3f9084f5f 100644 --- a/code/modules/vehicle/ambulance.dm +++ b/code/modules/vehicle/ambulance.dm @@ -35,7 +35,8 @@ if(bed && get_dist(oldloc, loc) <= 2) bed.Move(oldloc) bed.dir = Dir - bed.buckled_mob.dir = Dir + if(bed.buckled_mob) + bed.buckled_mob.dir = Dir /obj/structure/stool/bed/amb_trolley name = "ambulance train trolley" 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-4356.yml b/html/changelogs/AutoChangeLog-pr-4356.yml deleted file mode 100644 index 357e2b7a393..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4356.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: FalseIncarnate -delete-after: True -changes: - - 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)" diff --git a/html/changelogs/AutoChangeLog-pr-4357.yml b/html/changelogs/AutoChangeLog-pr-4357.yml deleted file mode 100644 index 24e86b79fdf..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4357.yml +++ /dev/null @@ -1,10 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - 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" 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-4379.yml b/html/changelogs/AutoChangeLog-pr-4379.yml deleted file mode 100644 index 2a0aef9f39e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4379.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Crazylemon64 -delete-after: True -changes: - - bugfix: "Ragin' Mage creation works correctly again." diff --git a/html/changelogs/AutoChangeLog-pr-4414.yml b/html/changelogs/AutoChangeLog-pr-4414.yml new file mode 100644 index 00000000000..d41683f0102 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4414.yml @@ -0,0 +1,4 @@ +author: CrAzYPiLoT +delete-after: True +changes: + - rscadd: "Adds the ability to attach signalers to bear traps. Stealthy hunting!" diff --git a/html/changelogs/AutoChangeLog-pr-4432.yml b/html/changelogs/AutoChangeLog-pr-4432.yml new file mode 100644 index 00000000000..7d222ac5c03 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4432.yml @@ -0,0 +1,4 @@ +author: monster860 +delete-after: True +changes: + - rscadd: "Adds the floor painter. Sprite by FlattestGuitar" diff --git a/html/changelogs/AutoChangeLog-pr-4446.yml b/html/changelogs/AutoChangeLog-pr-4446.yml new file mode 100644 index 00000000000..d3ee88c4301 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4446.yml @@ -0,0 +1,16 @@ +author: KasparoVy +delete-after: True +changes: + - bugfix: "Rejuvenating a mob now unbuckles them correctly (if they're buckled to something)." + - bugfix: "Rejuvenating a mob will no longer remove their hair." + - bugfix: "Rejuvenating a mob will no longer permanently blacken their eyes." + - bugfix: "Rejuvenating a mob will no longer remove their prostheses with fleshy limbs, it will just fix the prostheses." + - bugfix: "Rejuvenating a mob will not remove organs/limbs belonging to other species if said organs/limbs are in the same place(s) as the mob's default organs/limbs would be." + - bugfix: "Fixes a runtime when trying to flip with an object other than a grab in your hand." + - bugfix: "Doing a 'cybernetic repair' procedure on the head of a disfigured IPC will re-figure them." + - tweak: "Rejuvenating a mob will only regrow organs/limbs that are missing (by comparison to the standard organs for their species)." + - tweak: "The regenerate_icons proc will now update skin tone and body accessories properly." + - rscadd: "Organ rejuvenation now clears disfigurement and closes open wounds." + - rscadd: "Rejuvenating a mob will end all in-progress surgeries." + - rscadd: "Vox get their cortical stacks back, since the non-implant ones don't interfere with the Heist game-mode." + - rscadd: "Rejuvenating a long-dead or husked mob will now clear the appropriate mutations." diff --git a/html/changelogs/AutoChangeLog-pr-4447.yml b/html/changelogs/AutoChangeLog-pr-4447.yml new file mode 100644 index 00000000000..29bb7bda7a9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4447.yml @@ -0,0 +1,6 @@ +author: QuinnAggeler +delete-after: True +changes: + - rscadd: "Species disguise variable for clothing items" + - rscadd: "Species disguise string, \"High-tech robot,\" for cardborg suit and helmet" + - tweak: "ABSTRACT flagged clothing items will not be displayed on examination" 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-4479.yml b/html/changelogs/AutoChangeLog-pr-4479.yml new file mode 100644 index 00000000000..680a08d2cd5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4479.yml @@ -0,0 +1,4 @@ +author: Fox McCloud +delete-after: True +changes: + - tweak: "Donk pockets have more omnizine, but only upon fully consuming the donk pocket" diff --git a/html/changelogs/AutoChangeLog-pr-4480.yml b/html/changelogs/AutoChangeLog-pr-4480.yml new file mode 100644 index 00000000000..88b0a03c694 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4480.yml @@ -0,0 +1,6 @@ +author: Fox McCloud +delete-after: True +changes: + - tweak: "swarmers will drop an artificial bluespace crystal on death" + - tweak: "Orion Trail guards now drop an energy shield and C20R on death" + - tweak: "Reviving simple animals with strange reagent will prevent them from dropping any further loot" 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/goonstation/objects/syringe.dmi b/icons/goonstation/objects/syringe.dmi new file mode 100644 index 00000000000..4bde6be96bd Binary files /dev/null and b/icons/goonstation/objects/syringe.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/device.dmi b/icons/obj/device.dmi index 3874da51a64..338b56148ee 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.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/hypo.dmi b/icons/obj/hypo.dmi new file mode 100644 index 00000000000..fe42acbe4d2 Binary files /dev/null and b/icons/obj/hypo.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index db105c191d2..a22bb625198 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/reagentfillings.dmi index 94e2f2e7d27..42ba9cf7f29 100644 Binary files a/icons/obj/reagentfillings.dmi and b/icons/obj/reagentfillings.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/syringe.dmi b/icons/obj/syringe.dmi deleted file mode 100644 index 1621a9d8f2d..00000000000 Binary files a/icons/obj/syringe.dmi and /dev/null differ diff --git a/icons/obj/syringefilling.dmi b/icons/obj/syringefilling.dmi index 74f72313b91..7bb9d675437 100644 Binary files a/icons/obj/syringefilling.dmi and b/icons/obj/syringefilling.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 8b24cc343ce..347982ee137 100644 --- a/paradise.dme +++ b/paradise.dme @@ -723,6 +723,7 @@ #include "code\game\objects\items\devices\debugger.dm" #include "code\game\objects\items\devices\flash.dm" #include "code\game\objects\items\devices\flashlight.dm" +#include "code\game\objects\items\devices\floor_painter.dm" #include "code\game\objects\items\devices\guitar.dm" #include "code\game\objects\items\devices\laserpointer.dm" #include "code\game\objects\items\devices\lightreplacer.dm" @@ -859,6 +860,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" @@ -2008,6 +2010,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