diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 48ccd7f83e6..38453d4f526 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -2690,6 +2690,7 @@ "aZL" = (/obj/item/weapon/restraints/handcuffs/pinkcuffs,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/brig) "aZM" = (/obj/structure/stool/bed/chair,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/brig) "aZN" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/fsmaint2) +"aZO" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/obj/item/weapon/twohanded/required/kirbyplants,/obj/structure/sign/bobross{pixel_y = 32},/turf/simulated/floor/wood,/area/crew_quarters/captain) "aZV" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor/wood,/area/crew_quarters/bar) "aZW" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area/maintenance/fsmaint2) "aZX" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/junction{tag = "icon-pipe-j1 (EAST)"; icon_state = "pipe-j1"; dir = 4},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/fsmaint2) @@ -3979,7 +3980,6 @@ "byW" = (/obj/machinery/ai_status_display{pixel_y = 32},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/carpet,/area/crew_quarters/captain) "byX" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/power/apc{cell_type = 5000; dir = 1; name = "north bump Important Area"; pixel_x = 0; pixel_y = 24},/turf/simulated/floor/wood,/area/crew_quarters/captain) "byY" = (/obj/machinery/status_display{pixel_x = 0; pixel_y = 32},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/carpet,/area/crew_quarters/captain) -"byZ" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/obj/item/weapon/twohanded/required/kirbyplants,/turf/simulated/floor/wood,/area/crew_quarters/captain) "bza" = (/obj/structure/disposalpipe/segment,/obj/machinery/door/firedoor,/turf/simulated/floor/plasteel{dir = 8; icon_state = "bluecorner"},/area/hallway/primary/central/ne) "bzb" = (/obj/machinery/door/firedoor,/turf/simulated/floor/plasteel,/area/hallway/primary/central/ne) "bzc" = (/obj/structure/sign/directions/evac{dir = 4},/obj/structure/sign/directions/medical{dir = 4; pixel_y = 7},/obj/structure/sign/directions/science{dir = 4},/turf/simulated/wall,/area/crew_quarters/bar) @@ -9107,7 +9107,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabrNbtvbtybtCbtDbtDbtzbtDbtDbtDbtzbrQaSdaSdaSdaToboRbqrbrUbtFbtGbrUbtBbtAbtHbtEbqrbtLbtMbtIblQblMbtObtPbtKbtJbtQbtNbtSbtRbtRbtRbtUbtTblMbnKbsdbtYbtZbtVbubblTblTblTblTblTbucbudbtWbufbugbnTbnObssbgSbgSbgSbtXbuebuabuibuhbujbqSbunbukbumbulbupbuoburbuqbutbusbuubuhbuwbuvbuybuxbuAbuzbuEbuEbuBbhqbuCaUSbmqbuDbuIbpKbmqbuFbuGbmqbuHbuMbpKbmqbogbofbofbofboibofbuJbofbsWbrobuKbebbuPbrrboBboAboAboBbrubuLbebbuNbuQbuObuSbuRbuUbuTbuWbuVbuVbuVbuVbuVbuVbuXbuZbuYboJboJboJboJboJboJbvdbvabvcbvbbjKbjKbjKbvebltbjKbvgbqnbwDbvhcUBbjRblDblAbeCblCbnbblAbeCblCbnbblAbeCblCblDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabvibvjbvjbvjbvjbvjbvjbvjbvjbvjbvjbvfbvlaOQbvlaSfboRbqrbvmbrUbvnbvnbvnbvkbrUbvobqrbvqbvrbtIbvsbvsbvsbvsbvpbvsbvtbnDbvvbvubvwbvwbvybvxblMbvzbvBbvAbvDbvCbvFbvGbvHbvIbvHbvJbvJbvJbvJbvJbvKbvEbnObvLbvNbvMbvPbvObvRbvQbvTbvSbuobvUbvVbvXbvXbvXbvXbvWbvXbvZbwabwbbvYbvUbwdbwcbmcbwebwgbwfbwibwhbwjbhqbhqbsNbmqbwkbmqbmqbmqaZVbmqbmqbwmbwmbmqbmqbwlbofbofbwnbwobofbofbofbwqbwpbwrbebbqabrrboBboBboBboBbrubwsbebbwtbwvbwvbwwbwvbwubljbljbljbljbwybljbljbljbwzbvaboJboJboJboJboJboJboJbvdbvabvcbvbbjKboMboMboNboMbjKbwxbjRbwBbwAbwCbjRbnbblAbeCblCbnbblAbeCblCbnbblAbeCblCbnbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwFbwEbwGbwHbwIbwIbwJbwIbwIbwIbwJbrQaSdaSdaSdbwKblFbwLbrUbwMbvnbvnbvnbvkbwMbrUbqrbwNbwObtIbvsbwPbwQbwRbwSbvsbwUbwTbwVblMbwWbwXbwZbwYblMbnKbxabxbbxbbxcbxbbxbbxbbxbbxebxdbxdbxdbxfbxdbxgbxhbxibxjbxkbxlbxlbxlbxlbxlbxmbxmbxnbxmbvXbvXbxobxpbxqbxrbxtbxsbxobxubvXbxvbxwbxvbxvbxvbxvbxvbxvbxvbwjbhqbhqaUSbxxbmqbxybxzbmqbxAbmqbxBbxDbxCbmqbxEbdTbxFbxGbdTbdTbxHbxJbxIbxJbdTbdTbebblbbxLbxMbxMbxMbxMbxLbxNbebbxObwvbwvbwwbxPbaubxQbxRbxSbxTbxUbxVbxWbxXbxYaYPbxZbcDbyaboJboJbyabcDbybaYPbycbvbbjKbqlbqlbqmbqlbjKbvgbqnbwDbvhcUBbjRbqoblAbeCblCbqoblAbeCblCbqoblAbeCblCbqoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwFbrObrObrQbrObrObrObrRbrObrObydaabaSdbyebndbyfbqrbtFbtFbtFbrUbyhbygbyjbyibqrbykbylbtIbvsbymbvsbynbyobvsbyqbypbyrblMbwWbwXbwZbskblMbnKbxabxbbytbysbyubyvbywbxbbyybyxbyAbyzbyBbyBbyBbyCbyEbyDbyFbxlbyGbyHbyIbyJbyLbyKbyMbyNbvXbyObxqbxqbyPbyQbyPbxqbxqbyRbvXbySbyUbyTbyWbyVbyYbyXbyZbxvbzabzbbzbbzcaUSaUSaUSaUSbzdbsNbzdbzeaUSbdRaUSaUSbdTbdTbdTbdTbzgbzfbzfbzfbzfbzhbzibebbjBbzjbjBbzkbzkbjBbzjbjBbebbxObwvbwvbzlbxPbaubaubaubaubaubtfbaubaubaubauaYPaYOaYQaYQaYQaYQaYQaYQaYPaYPbznbzmbzobxKbjKbjMbjKbjKbzpbjRbjRbjRbjRbqnbicbzqbeCbeCbeCbeCbeCbeCbeCbeCbeCbeCbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabwFbrObrObrQbrObrObrObrRbrObrObydaabaSdbyebndbyfbqrbtFbtFbtFbrUbyhbygbyjbyibqrbykbylbtIbvsbymbvsbynbyobvsbyqbypbyrblMbwWbwXbwZbskblMbnKbxabxbbytbysbyubyvbywbxbbyybyxbyAbyzbyBbyBbyBbyCbyEbyDbyFbxlbyGbyHbyIbyJbyLbyKbyMbyNbvXbyObxqbxqbyPbyQbyPbxqbxqbyRbvXbySbyUbyTbyWbyVbyYbyXaZObxvbzabzbbzbbzcaUSaUSaUSaUSbzdbsNbzdbzeaUSbdRaUSaUSbdTbdTbdTbdTbzgbzfbzfbzfbzfbzhbzibebbjBbzjbjBbzkbzkbjBbzjbjBbebbxObwvbwvbzlbxPbaubaubaubaubaubtfbaubaubaubauaYPaYOaYQaYQaYQaYQaYQaYQaYPaYPbznbzmbzobxKbjKbjMbjKbjKbzpbjRbjRbjRbjRbqnbicbzqbeCbeCbeCbeCbeCbeCbeCbeCbeCbeCbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabjQaLdaSdaSdaSdaMsaMsaMsaMsaMsaMsbzrbzsbqrbqrbqrbqrbqrbqrbztbqrbqrbqrbnKbnKbzwbvsbzubzvbynbzxbvsbzzbzybzAblMbwWbwXbwZbnDblMbnKbxabxbbzDbzBbzCbyvbzCbxbbyybzGbzEbzFbzIbzHbzKbzJbzMbzLbyFbzRbzNbzObzPbzQbzQbzPbzUbzSbvXbzTbxqbxqbyPbzWbyPbxqbxqbzVbwbbzXbAbbzYbzZbAabAdbzYbAcbxvbAlbAebAfbAgbAhbAibAjbAkbAkbAkbAkbAkbAkbAmbAobAnbAkbAkbAqbAkbAkbAkbAkbAkbAkbAkbAkbApbAsbArbArbArbArbArbArbAtbAibAubAvbAvbAxbAwbAybAwbAzbAwbABbAAbACbAwbAFbADbAEbAHbAGbAGbAGbAGbAGbAGbAGbAIbALbAJbAJbAKbAJbBObjKbjKbrIbAMboIbANbrMboIbAObeCbeCbeCbeCbAPbeCbAPbeCbeCbeCbeCaYUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAQbARbARbARbARbASbASbARbARbATaaaaabaSdaUkaSgbAVbAUbAXbAWbAWbAWbAWbAYbAZbBablQbnwbBcbBbbvsbvsbvsbBdbyobvsblMblMblMblMbwWbBebBgbBfblMbBhbBibxbbBjbBkbyvbzCbBlbxbbyybBmbzEbzFbBnbBobBpbzJbBqbzLbyFbzRbBrbBsbBtbBubBvbBwbzUbBxbvXbBybyPbxqbBAbBzbBAbxqbyPbBBbxubBCbzYbzYbzZbBDbAdbzYbBEbxvbBFbAfbAfbAgbAhbAibAkbAkbAkbAkbAkbAkbAkbBGbAkbAkbAkbAkbAkbAkbBHbBIbBIbBIbBIbBIbBIbBIbBIbBIbBIbBIbBIbBIbBIbBJbBKbBLbAGbAGbBMbwvbwvbwvbwvbwvbwwbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbBNbwvbDobBPbjKbjKbBQbjKbjKbjKbjKbBUbjRbqnbjRbjRbjRbqpbjCbBWbBVbjCbBXaYUbBXaYUbBYbBRbBSbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCabCdbCcbBZbCebCbbCbbClbCibARbATaSdaSdaSdaTobCnbCfbCgbCfbCfbCfbCfbChbCtbCjblQblQbCkbCwbvsbwPbCmbCxbzxbvsbCobCpbCoblMblMblMblMbCqblMbCrbCsbxbbCybCubzCbCvbCzbxbbyybzJbCBbzFbBnbBnbCEbzJbCFbzLbyFbzRbCAbBsbBtbCGbCCbBwbzUbCDbvXbCHbCIbxqbCKbCJbCLbxqbCRbCNbCSbCMbCTbCObCPbCQbCUbzYbCVbxvbCYbCXbAfbAgbAhbAibAkbCZbAkbAkbAkbAkbCWbDbbDbbDbbDbbDcbAkbAkbAkbAkbDdbAkbCZbDabAkbAkbDebDgbDfbDhbDibDibDlbDjbDnbDmbwvbwvbwvbwvbwvbwvbwvbDkbDpbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbDrbDqbDqbDsbDubDtbDxbDvbDvbDybDAbEHbmZbAMboIbrMbrMboIbDBdsldsldsldsnbicaaabicbDDbDwbDwbDFbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 499be494056..40f27d0d84f 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -63,13 +63,21 @@ #define THROWN_PROJECTILE_ATTACK 4 #define LEAP_ATTACK 5 +//Embedded objects +#define EMBEDDED_PAIN_CHANCE 15 //Chance for embedded objects to cause pain (damage user) +#define EMBEDDED_ITEM_FALLOUT 5 //Chance for embedded object to fall out (causing pain but removing the object) +#define EMBED_CHANCE 45 //Chance for an object to embed into somebody when thrown (if it's sharp) +#define EMBEDDED_PAIN_MULTIPLIER 2 //Coefficient of multiplication for the damage the item does while embedded (this*item.w_class) +#define EMBEDDED_FALL_PAIN_MULTIPLIER 5 //Coefficient of multiplication for the damage the item does when it falls out (this*item.w_class) +#define EMBEDDED_IMPACT_PAIN_MULTIPLIER 4 //Coefficient of multiplication for the damage the item does when it first embeds (this*item.w_class) +#define EMBED_THROWSPEED_THRESHOLD 4 //The minimum value of an item's throw_speed for it to embed (Unless it has embedded_ignore_throwspeed_threshold set to 1) +#define EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER 8 //Coefficient of multiplication for the damage the item does when removed without a surgery (this*item.w_class) +#define EMBEDDED_UNSAFE_REMOVAL_TIME 30 //A Time in ticks, total removal time = (this*item.w_class) + //Gun Stuff #define SAWN_INTACT 0 #define SAWN_OFF 1 #define WEAPON_LIGHT 0 #define WEAPON_MEDIUM 1 - #define WEAPON_HEAVY 2 - -// Embedded objects -#define EMBED_THROWSPEED_THRESHOLD 15 \ No newline at end of file + #define WEAPON_HEAVY 2 \ No newline at end of file diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index a27e3f8e96a..d708813b139 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -2,9 +2,19 @@ #define isatom(A) istype(A, /atom) #define ismovableatom(A) istype(A, /atom/movable) -// Mobs +// Mobs #define ismegafauna(A) istype(A, /mob/living/simple_animal/hostile/megafauna) +//Objects + +var/list/static/global/pointed_types = typecacheof(list( + /obj/item/weapon/pen, + /obj/item/weapon/screwdriver, + /obj/item/weapon/reagent_containers/syringe, + /obj/item/weapon/kitchen/utensil/fork)) + +#define is_pointed(W) (is_type_in_typecache(W, pointed_types)) + //Turfs #define issimulatedturf(A) istype(A, /turf/simulated) diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 89755d7acf0..f9bae78c35b 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -448,32 +448,32 @@ proc/checkhtml(var/t) // Pencode -/proc/pencode_to_html(text, mob/user, obj/item/weapon/pen/P = null, sign = 1, fields = 1, deffont = PEN_FONT, signfont = SIGNFONT, crayonfont = CRAYON_FONT) - text = replacetext(text, "\n", "
") - text = replacetext(text, "\[center\]", "
") - text = replacetext(text, "\[/center\]", "
") - text = replacetext(text, "\[br\]", "
") +/proc/pencode_to_html(text, mob/user, obj/item/weapon/pen/P = null, format = 1, sign = 1, fields = 1, deffont = PEN_FONT, signfont = SIGNFONT, crayonfont = CRAYON_FONT) text = replacetext(text, "\[b\]", "") text = replacetext(text, "\[/b\]", "") text = replacetext(text, "\[i\]", "") text = replacetext(text, "\[/i\]", "") text = replacetext(text, "\[u\]", "") text = replacetext(text, "\[/u\]", "") - text = replacetext(text, "\[large\]", "") - text = replacetext(text, "\[/large\]", "") if(sign) text = replacetext(text, "\[sign\]", "[user ? user.real_name : "Anonymous"]") if(fields) text = replacetext(text, "\[field\]", "") + if(format) + text = replacetext(text, "\[h1\]", "

") + text = replacetext(text, "\[/h1\]", "

") + text = replacetext(text, "\[h2\]", "

") + text = replacetext(text, "\[/h2\]", "

") + text = replacetext(text, "\[h3\]", "

") + text = replacetext(text, "\[/h3\]", "

") + text = replacetext(text, "\n", "
") + text = replacetext(text, "\[center\]", "
") + text = replacetext(text, "\[/center\]", "
") + text = replacetext(text, "\[br\]", "
") + text = replacetext(text, "\[large\]", "") + text = replacetext(text, "\[/large\]", "") - text = replacetext(text, "\[h1\]", "

") - text = replacetext(text, "\[/h1\]", "

") - text = replacetext(text, "\[h2\]", "

") - text = replacetext(text, "\[/h2\]", "

") - text = replacetext(text, "\[h3\]", "

") - text = replacetext(text, "\[/h3\]", "

") - - if(istype(P, /obj/item/toy/crayon)) // If it is a crayon, and he still tries to use these, make them empty! + if(istype(P, /obj/item/toy/crayon) || !format) // If it is a crayon, and he still tries to use these, make them empty! text = replacetext(text, "\[*\]", "") text = replacetext(text, "\[hr\]", "") text = replacetext(text, "\[small\]", "") @@ -485,7 +485,7 @@ proc/checkhtml(var/t) text = replacetext(text, "\[row\]", "") text = replacetext(text, "\[cell\]", "") text = replacetext(text, "\[logo\]", "") - + if(istype(P, /obj/item/toy/crayon)) text = "[text]" else // They are using "not a crayon" - formatting is OK and such text = replacetext(text, "\[*\]", "
  • ") @@ -501,9 +501,10 @@ proc/checkhtml(var/t) text = replacetext(text, "\[row\]", "") text = replacetext(text, "\[cell\]", "") text = replacetext(text, "\[logo\]", "") - + if(P) text = "[text]" - + else + text = "[text]" text = copytext(text, 1, MAX_PAPER_MESSAGE_LEN) return text diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index dba28dcb914..e5e9116eeb7 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1081,6 +1081,21 @@ proc/get_mob_with_client_list() return get_turf(location) +//For objects that should embed, but make no sense being is_sharp or is_pointed() +//e.g: rods +var/list/can_embed_types = typecacheof(list( + /obj/item/stack/rods, + /obj/item/pipe)) + +/proc/can_embed(obj/item/W) + if(is_sharp(W)) + return 1 + if(is_pointed(W)) + return 1 + + if(is_type_in_typecache(W, can_embed_types)) + return 1 + //Quick type checks for some tools var/global/list/common_tools = list( /obj/item/stack/cable_coil, @@ -1194,22 +1209,6 @@ var/global/list/common_tools = list( return 1 return 0 -//Returns 1 if the given item is capable of popping things like balloons, inflatable barriers, or cutting police tape. -/proc/can_puncture(obj/item/W as obj) // For the record, WHAT THE HELL IS THIS METHOD OF DOING IT? - if(!istype(W)) return 0 - if(!W) return 0 - if(W.sharp) return 1 - return ( \ - W.sharp || \ - istype(W, /obj/item/weapon/screwdriver) || \ - istype(W, /obj/item/weapon/pen) || \ - istype(W, /obj/item/weapon/weldingtool) || \ - istype(W, /obj/item/weapon/lighter/zippo) || \ - istype(W, /obj/item/weapon/match) || \ - istype(W, /obj/item/clothing/mask/cigarette) || \ - istype(W, /obj/item/weapon/shovel) \ - ) - /proc/is_surgery_tool(obj/item/W as obj) return ( \ istype(W, /obj/item/weapon/scalpel) || \ diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 5ebe1f9ac6d..1d5d419ba82 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -235,6 +235,12 @@ or something covering your eyes." desc = "All that alcohol you've been drinking is impairing your speech, motor skills, and mental cognition. Make sure to act like it." icon_state = "drunk" +/obj/screen/alert/embeddedobject + name = "Embedded Object" + desc = "Something got lodged into your flesh and is causing major bleeding. It might fall out with time, but surgery is the safest way. \ + If you're feeling frisky, click yourself in help intent to pull the object out." + icon_state = "embeddedobject" + /obj/screen/alert/embeddedobject/Click() if(isliving(usr)) var/mob/living/carbon/human/M = usr diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm index 32472fe1ec0..7524e7f31d6 100644 --- a/code/datums/spells/summonitem.dm +++ b/code/datums/spells/summonitem.dm @@ -79,6 +79,14 @@ add_logs(target, C, "magically debrained", addition="INTENT: [uppertext(target.a_intent)]")*/ if(C.stomach_contents && item_to_retrive in C.stomach_contents) C.stomach_contents -= item_to_retrive + for(var/X in C.bodyparts) + var/obj/item/organ/external/part = X + if(item_to_retrive in part.embedded_objects) + part.embedded_objects -= item_to_retrive + to_chat(C, "The [item_to_retrive] that was embedded in your [part] has mysteriously vanished. How fortunate!") + if(!C.has_embedded_objects()) + C.clear_alert("embeddedobject") + break else if(istype(item_to_retrive.loc,/obj/machinery/portable_atmospherics/)) //Edge cases for moved machinery diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index ef3b4a4e278..5475cd7d57e 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -737,6 +737,14 @@ var/list/uplink_items = list() cost = 17 excludefrom = list(/datum/game_mode/nuclear) +/datum/uplink_item/stealthy_weapons/throwingweapons + name = "Box of Throwing Weapons" + desc = "A box of shurikens and reinforced bolas from ancient Earth martial arts. They are highly effective \ + throwing weapons. The bolas can knock a target down and the shurikens will embed into limbs." + reference = "STK" + item = /obj/item/weapon/storage/box/syndie_kit/throwing_weapons + cost = 3 + /datum/uplink_item/stealthy_weapons/edagger name = "Energy Dagger" desc = "A dagger made of energy that looks and functions as a pen when off." diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index c16a883e00d..441af094558 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -414,9 +414,6 @@ else M.stop_pulling() - if(user.pinned.len) - failure = 1 - user.visible_message("[user.name] takes a huge leap!") playsound(user.loc, 'sound/weapons/thudswoosh.ogg', 50, 1) if(failure) diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index e159aa44247..32a6a58cbb3 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -211,11 +211,11 @@ /obj/effect/proc_holder/spell/targeted/remotetalk/choose_targets(mob/user = usr) var/list/targets = new /list() var/list/validtargets = new /list() - for(var/mob/M in view(user.client.view, user)) + var/turf/T = get_turf(user) + for(var/mob/M in range(14, T)) if(M && M.mind) if(M == user) continue - validtargets += M if(!validtargets.len) @@ -237,14 +237,15 @@ if(!say) return say = strip_html(say) + say = pencode_to_html(say, usr, format = 0, fields = 0) for(var/mob/living/target in targets) log_say("Project Mind: [key_name(user)]->[key_name(target)]: [say]") if(REMOTE_TALK in target.mutations) - target.show_message("You hear [user.real_name]'s voice: [say]") + target.show_message("You hear [user.real_name]'s voice: [say]") else - target.show_message("You hear a voice that seems to echo around the room: [say]") - user.show_message("You project your mind into [target.real_name]: [say]") + target.show_message("You hear a voice that seems to echo around the room: [say]") + user.show_message("You project your mind into [target.name]: [say]") for(var/mob/dead/observer/G in player_list) G.show_message("Telepathic message from [user] ([ghost_follow_link(user, ghost=G)]) to [target] ([ghost_follow_link(target, ghost=G)]): [say]") diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 5fd98986332..9077f623a2c 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -39,10 +39,6 @@ var/obj/item/organ/external/O = H.bodyparts_by_name[organ_name] if(!O) continue - for(var/obj/item/weapon/shard/shrapnel/s in O.implants) - O.implants -= s - H.contents -= s - qdel(s) O.brute_dam = 0 O.burn_dam = 0 O.damage_state = "00" @@ -58,6 +54,7 @@ for(var/obj/item/organ/internal/IO in H.internal_organs) IO.damage = 0 IO.trace_chemicals.Cut() + H.remove_all_embedded_objects() H.updatehealth() to_chat(user, "We have regenerated.") diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 801ab1c138d..7ec4240769d 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -40,6 +40,7 @@ w_class = WEIGHT_CLASS_SMALL force = 15 throwforce = 25 + embed_chance = 75 var/cooldown = 0 /obj/item/weapon/melee/cultblade/dagger/afterattack(mob/living/target as mob, mob/living/carbon/human/user as mob) diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index a9975618435..a98090d186a 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -361,11 +361,6 @@ host = M forceMove(M) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/head = H.get_organ("head") - head.implants += src - host.status_flags |= PASSEMOTES RemoveBorerActions() @@ -746,11 +741,6 @@ controlling = FALSE - if(ishuman(host)) - var/mob/living/carbon/human/H = host - var/obj/item/organ/external/head = H.get_organ("head") - head.implants -= src - reset_perspective(null) machine = null diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index cf9946319a8..c6f3b4c4280 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -779,7 +779,7 @@ var/global/list/multiverse = list() to_chat(target, "You suddenly feel very hot") target.bodytemperature += 50 GiveHint(target) - else if(can_puncture(I)) + else if(is_pointed(I)) to_chat(target, "You feel a stabbing pain in [parse_zone(user.zone_sel.selecting)]!") target.Weaken(2) GiveHint(target) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 41dc37ab43f..6d7264e9256 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -398,7 +398,7 @@ organData["broken"] = E.min_broken_damage var/shrapnelData[0] - for(var/obj/I in E.implants) + for(var/obj/I in E.embedded_objects) var/shrapnelSubData[0] shrapnelSubData["name"] = I.name @@ -605,7 +605,7 @@ infected = "Septic:" var/unknown_body = 0 - for(var/I in e.implants) + for(var/I in e.embedded_objects) unknown_body++ if(unknown_body || e.hidden) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index ae198664806..294dda0d674 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -4,7 +4,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d name = "item" icon = 'icons/obj/items.dmi' var/discrete = 0 // used in item_attack.dm to make an item not show an attack message to viewers - var/no_embed = 0 // For use in item_attack.dm var/image/blood_overlay = null //this saves our blood splatter overlay, which will be processed not to go over the edges of the sprite var/blood_overlay_color = null var/item_state = null @@ -63,6 +62,17 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d var/mob/thrownby = null + //So items can have custom embedd values + //Because customisation is king + var/embed_chance = EMBED_CHANCE + var/embedded_fall_chance = EMBEDDED_ITEM_FALLOUT + var/embedded_pain_chance = EMBEDDED_PAIN_CHANCE + var/embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does while embedded (this*w_class) + var/embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class) + var/embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when first embedded (this*w_class) + var/embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class) + var/embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME //A time in ticks, multiplied by the w_class. + var/toolspeed = 1 // If this item is a tool, the speed multiplier /* Species-specific sprites, concept stolen from Paradise//vg/. diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm index 5f55a5acdcc..dccc8f041f6 100644 --- a/code/game/objects/items/latexballoon.dm +++ b/code/game/objects/items/latexballoon.dm @@ -59,5 +59,5 @@ var/obj/item/weapon/tank/T = W blow(T, user) return - if(is_sharp(W) || is_hot(W) || can_puncture(W)) + if(is_sharp(W) || is_hot(W) || is_pointed(W)) burst() diff --git a/code/game/objects/items/policetape.dm b/code/game/objects/items/policetape.dm index 56fd5eadbad..bea99b5d98b 100644 --- a/code/game/objects/items/policetape.dm +++ b/code/game/objects/items/policetape.dm @@ -174,7 +174,7 @@ var/list/tape_roll_applications = list() breaktape(/obj/item/weapon/wirecutters,user) /obj/item/tape/proc/breaktape(obj/item/weapon/W as obj, mob/user as mob) - if(user.a_intent == INTENT_HELP && ((!can_puncture(W) && src.allowed(user)))) + if(user.a_intent == INTENT_HELP && ((!is_pointed(W) && src.allowed(user)))) to_chat(user, "You can't break the [src] with that!") return user.visible_message("[user] breaks the [src]!", "You break the [src]!") diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index 9faba432ccf..1633dfeda7c 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -98,7 +98,6 @@ throw_range = 6 materials = list(MAT_METAL=12000) attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - no_embed = 1 sharp = 1 /obj/item/weapon/kitchen/knife/suicide_act(mob/user) diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 992cd301547..54aee1e285d 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -6,7 +6,6 @@ var/w_class_on = WEIGHT_CLASS_BULKY var/icon_state_on = "axe1" var/list/attack_verb_on = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - no_embed = 1 // Physically impossible for energy weapons to embed themselves into people, this should fix that. -- Dave hitsound = 'sound/weapons/blade1.ogg' // Probably more appropriate than the previous hitsound. -- Dave usesound = 'sound/weapons/blade1.ogg' toolspeed = 1 @@ -25,6 +24,7 @@ force = force_on throwforce = throwforce_on hitsound = 'sound/weapons/blade1.ogg' + throw_speed = 4 if(attack_verb_on.len) attack_verb = attack_verb_on if(!item_color) @@ -38,6 +38,7 @@ force = initial(force) throwforce = initial(throwforce) hitsound = initial(hitsound) + throw_speed = initial(throw_speed) if(attack_verb_on.len) attack_verb = list() icon_state = initial(icon_state) @@ -84,6 +85,8 @@ throw_speed = 3 throw_range = 5 hitsound = "swing_hit" + embed_chance = 75 + embedded_impact_pain_multiplier = 10 armour_penetration = 35 origin_tech = "combat=3;magnets=4;syndicate=4" block_chance = 50 diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm index 2eab01868c8..be2336d6a37 100644 --- a/code/game/objects/items/weapons/shards.dm +++ b/code/game/objects/items/weapons/shards.dm @@ -87,28 +87,4 @@ if(affecting.take_damage(5, 0)) H.UpdateDamageIcon() H.updatehealth() - ..() - -// Shrapnel - -/obj/item/weapon/shard/shrapnel - name = "shrapnel" - icon = 'icons/obj/shards.dmi' - icon_state = "shrapnellarge" - desc = "A bunch of tiny bits of shattered metal." - -/obj/item/weapon/shard/shrapnel/New() - - src.icon_state = pick("shrapnellarge", "shrapnelmedium", "shrapnelsmall") - switch(src.icon_state) - if("shrapnelsmall") - src.pixel_x = rand(-12, 12) - src.pixel_y = rand(-12, 12) - if("shrapnelmedium") - src.pixel_x = rand(-8, 8) - src.pixel_y = rand(-8, 8) - if("shrapnellarge") - src.pixel_x = rand(-5, 5) - src.pixel_y = rand(-5, 5) - else - return + ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 9efc5f625a6..c5f32121d4f 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -157,6 +157,22 @@ new /obj/item/weapon/grenade/empgrenade(src) new /obj/item/weapon/implanter/emp/(src) +/obj/item/weapon/storage/box/syndie_kit/throwing_weapons + name = "boxed throwing kit" + can_hold = list(/obj/item/weapon/throwing_star, /obj/item/weapon/restraints/legcuffs/bola/tactical) + max_combined_w_class = 16 + max_w_class = WEIGHT_CLASS_NORMAL + +/obj/item/weapon/storage/box/syndie_kit/throwing_weapons/New() + ..() + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/throwing_star(src) + new /obj/item/weapon/restraints/legcuffs/bola/tactical(src) + new /obj/item/weapon/restraints/legcuffs/bola/tactical(src) + /obj/item/weapon/storage/box/syndie_kit/sarin name = "Sarin Gas Grenades" diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index ac1e984808b..87197426495 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -208,7 +208,6 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 75 sharp = 1 - no_embed = 1 // Like with the single-handed esword, this shouldn't be embedding in people. /obj/item/weapon/twohanded/dualsaber/New() blade_color = pick("red", "blue", "green", "purple") @@ -495,7 +494,6 @@ origin_tech = "materials=6;syndicate=4" attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered") sharp = 1 - no_embed = 1 /obj/item/weapon/twohanded/chainsaw/update_icon() if(wielded) @@ -534,7 +532,6 @@ icon_state = "mjollnir0" flags = CONDUCT slot_flags = SLOT_BACK - no_embed = 1 force = 5 force_unwielded = 5 force_wielded = 20 @@ -599,7 +596,6 @@ icon_state = "mjollnir0" flags = CONDUCT slot_flags = SLOT_BACK - no_embed = 1 force = 5 force_unwielded = 5 force_wielded = 25 @@ -647,7 +643,6 @@ icon_state = "knighthammer0" flags = CONDUCT slot_flags = SLOT_BACK - no_embed = 1 force = 5 force_unwielded = 5 force_wielded = 30 diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index d6dbdaae075..753a8073313 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -127,6 +127,20 @@ obj/item/weapon/wirerod/attackby(obj/item/I, mob/user, params) qdel(I) qdel(src) +/obj/item/weapon/throwing_star + name = "throwing star" + desc = "An ancient weapon still used to this day due to it's ease of lodging itself into victim's body parts" + icon_state = "throwingstar" + item_state = "eshield0" + force = 2 + throwforce = 20 //This is never used on mobs since this has a 100% embed chance. + throw_speed = 4 + embedded_pain_multiplier = 4 + w_class = WEIGHT_CLASS_SMALL + embed_chance = 100 + embedded_fall_chance = 0 //Hahaha! + sharp = 1 + materials = list(MAT_METAL=500, MAT_GLASS=500) /obj/item/weapon/spear/kidan icon_state = "kidanspear" diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index 14f1357af87..2cdcfc18376 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -96,7 +96,7 @@ /obj/structure/inflatable/attackby(obj/item/weapon/W as obj, mob/user as mob, params) if(!istype(W)) return - if(can_puncture(W)) + if(is_pointed(W)) visible_message("[user] pierces [src] with [W]!") deflate(1) if(W.damtype == BRUTE || W.damtype == BURN) diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index 3f4eea3dbf4..b1cf367ba1f 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -182,10 +182,15 @@ icon_state = "nuke" /obj/structure/sign/clown - name = "\improper mech painting" + name = "\improper clown painting" desc = "A painting of the clown and mime. Awwww." icon_state = "clown" +/obj/structure/sign/bobross + name = "\improper calming painting" + desc = "We don't make mistakes, just happy little accidents." + icon_state = "bob" + /obj/structure/sign/singulo name = "\improper singulo painting" desc = "A mesmerizing painting of a singularity. It seems to suck you in..." diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 9e40914da9b..5f3cc4dec2b 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -2154,7 +2154,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts else if(status == "cyborg") if(rlimb_data[name]) - O.robotize(rlimb_data[name]) + O.robotize(rlimb_data[name], convert_all = 0) else O.robotize() else diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index da181368cc5..f1fb29ed645 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -978,10 +978,6 @@ else M.stop_pulling() - if(wearer.pinned.len) - to_chat(src, "Your host is pinned to a wall by [wearer.pinned[1]]!") - return 0 - // AIs are a bit slower than regular and ignore move intent. wearer_move_delay = world.time + ai_controlled_move_delay diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 43b89d315d9..a5340ed91bc 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -952,17 +952,17 @@ /obj/item/clothing/suit/tailcoat name = "victorian tailcoat" - desc = "a fancy victorian tailcoat." + desc = "A fancy victorian tailcoat." icon_state = "tailcoat" item_state = "tailcoat" /obj/item/clothing/suit/victcoat name = "ladies victorian coat" - desc = "a fancy victorian coat." + desc = "A fancy victorian coat." icon_state = "ladiesvictoriancoat" item_state = "ladiesvictoriancoat" /obj/item/clothing/suit/victcoat/red name = "ladies red victorian coat" icon_state = "ladiesredvictoriancoat" - item_state = "ladiesredvictoriancoat" \ No newline at end of file + item_state = "ladiesredvictoriancoat" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 4fa40404c46..8066deb3074 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -791,10 +791,10 @@ /obj/item/clothing/under/victdress name = "black victorian dress" - desc = "a victorian style dress, fancy!." + desc = "A victorian style dress, fancy!" icon_state = "victorianblackdress" - item_state = "Victorianblackdress" - item_color = "Victorianblackdress" + item_state = "victorianblackdress" + item_color = "victorianblackdress" body_parts_covered = UPPER_TORSO|LOWER_TORSO /obj/item/clothing/under/victdress/red @@ -805,7 +805,7 @@ /obj/item/clothing/under/victsuit name = "victorian suit" - desc = "a victorian style suit, fancy!." + desc = "A victorian style suit, fancy!" icon_state = "victorianvest" item_state = "victorianvest" item_color = "victorianvest" diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 98fe9fad27f..8b98dac200d 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -137,6 +137,7 @@ var/list/event_last_fired = list() new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Sentience", /datum/event/sentience, 50), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50)) ) diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm new file mode 100644 index 00000000000..cfa0d24d98e --- /dev/null +++ b/code/modules/events/sentience.dm @@ -0,0 +1,47 @@ +/datum/event/sentience + +/datum/event/sentience/start() + var/ghostmsg = "Do you want to awaken as a sentient being?" + var/list/candidates = pollCandidates(ghostmsg, ROLE_SENTIENT, 1) + var/list/potential = list() + var/sentience_type = SENTIENCE_ORGANIC + + for(var/mob/living/simple_animal/L in living_mob_list) + var/turf/T = get_turf(L) + if (T.z != 1) + continue + if(!(L in player_list) && !L.mind && (L.sentience_type == sentience_type)) + potential += L + + var/mob/living/simple_animal/SA = pick(potential) + var/mob/SG = pick(candidates) + + if(!SA || !SG) //if you can't find either a simple animal or a player, end + return FALSE + + var/sentience_report = "[command_name()] Medium-Priority Update" + + var/data = pick("scans from our long-range sensors", "our sophisticated probabilistic models", "our omnipotence", "the communications traffic on your station", "energy emissions we detected", "\[REDACTED\]", "Steve") + var/pets = pick("animals", "pets", "simple animals", "lesser lifeforms", "\[REDACTED\]") + var/strength = pick("human", "skrell", "vox", "grey", "diona", "IPC", "tajaran", "vulpakanin", "kidan", "plasmaman", "drask", + "slime", "monkey", "moderate", "lizard", "security", "command", "clown", "mime", "low", "very low", "greytide", "catgirl", "\[REDACTED\]") + + sentience_report += "

    Based on [data], we believe that one of the station's [pets] has developed [strength] level intelligence, and the ability to communicate." + + + + SA.key = SG.key + SA.universal_speak = 1 + SA.sentience_act() + SA.maxHealth = max(SA.maxHealth, 200) + SA.health = SA.maxHealth + SA.del_on_death = FALSE + greet_sentient(SA) + print_command_report(sentience_report, "[command_name()] Update") + +/datum/event/sentience/proc/greet_sentient(var/mob/living/carbon/human/M) + to_chat(M, "Hello world!") + to_chat(M, "Due to freak radiation, you have gained \ + human level intelligence and the ability to speak and understand \ + human language!") + diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 36d84b0f72d..d591c8b4a1c 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -96,6 +96,9 @@ return (copytext(message, length(message)) == "!") ? 2 : 1 /datum/language/proc/broadcast(mob/living/speaker, message, speaker_mask) + if(!check_can_speak(speaker)) + return FALSE + log_say("[key_name(speaker)]: ([name]) [message]") if(!speaker_mask) @@ -114,6 +117,9 @@ /datum/language/proc/check_special_condition(mob/other, mob/living/speaker) return TRUE +/datum/language/proc/check_can_speak(mob/living/speaker) + return TRUE + /datum/language/proc/get_spoken_verb(msg_end) switch(msg_end) if("!") @@ -290,10 +296,30 @@ flags = RESTRICTED | HIVEMIND /datum/language/grey/broadcast(mob/living/speaker, message, speaker_mask) + var/their = "their" + if(speaker.gender == "female") + their = "her" + if(speaker.gender == "male") + their = "his" + + speaker.visible_message("[speaker] touches [their] fingers to [their] temple.") ..(speaker,message,speaker.real_name) +/datum/language/grey/check_can_speak(mob/living/speaker) + if(ishuman(speaker)) + var/mob/living/carbon/human/S = speaker + var/obj/item/organ/external/rhand = S.get_organ("r_hand") + var/obj/item/organ/external/lhand = S.get_organ("l_hand") + if((!rhand || !rhand.is_usable()) && (!lhand || !lhand.is_usable())) + to_chat(speaker,"You can't communicate without the ability to use your hands!") + return FALSE + if(speaker.incapacitated(ignore_lying = 1)) + to_chat(speaker,"You can't communicate while unable to move your hands to your head!") + return FALSE + return TRUE + /datum/language/grey/check_special_condition(mob/living/carbon/human/other, mob/living/carbon/human/speaker) - if(other in range(7, speaker)) + if(atoms_share_level(other, speaker)) return TRUE return FALSE diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 7a12b570201..daeebf8442f 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -71,9 +71,9 @@ var/obj/item/organ/internal/brain/B = src if(!special) var/mob/living/simple_animal/borer/borer = owner.has_brain_worms() - if(borer) - borer.detach() //Should remove borer if the brain is removed - RR + borer.leave_host() //Should remove borer if the brain is removed - RR + if(owner.mind && !non_primary)//don't transfer if the owner does not have a mind. B.transfer_identity(user) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 1407fba6998..708016df353 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -244,6 +244,10 @@ if(status == "") status = "OK" src.show_message(text("\t []My [] is [].",status=="OK"?"":"",org.name,status),1) + + for(var/obj/item/I in org.embedded_objects) + to_chat(src, "\t There is \a [I] embedded in your [org.name]!") + if(staminaloss) if(staminaloss > 30) to_chat(src, "You're completely exhausted.") diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index bbc45bf3ce0..beaca58d74d 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -90,8 +90,10 @@ if(src) qdel(src) /mob/living/carbon/human/death(gibbed) - if(stat == DEAD) return - if(healths) healths.icon_state = "health5" + if(stat == DEAD) + return + if(healths) + healths.icon_state = "health5" if(!gibbed) emote("deathgasp") //let the world KNOW WE ARE DEAD @@ -102,21 +104,8 @@ set_heartattack(FALSE) //Handle species-specific deaths. - if(species) species.handle_death(src) - - //Handle brain slugs. - var/obj/item/organ/external/head = get_organ("head") - var/mob/living/simple_animal/borer/B - - if(istype(head)) - for(var/I in head.implants) - if(istype(I,/mob/living/simple_animal/borer)) - B = I - if(B) - if(B.controlling && B.host == src) - B.detach() - - verbs -= /mob/living/carbon/proc/release_control + if(species) + species.handle_death(src) callHook("death", list(src, gibbed)) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 693973ab42d..961ee9ffd0b 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -382,6 +382,9 @@ else wound_flavor_text["[temp.limb_name]"] = "" + for(var/obj/item/I in temp.embedded_objects) + msg += "[t_He] [t_has] \a [bicon(I)] [I] embedded in [t_his] [temp.name]!\n" + //Handles the text strings being added to the actual description. //If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext. var/display_chest = 0 @@ -438,9 +441,6 @@ if(display_gloves) msg += "[src] has blood running from under [t_his] gloves!\n" - - for(var/implant in get_visible_implants(0)) - msg += "[src] has \a [implant] sticking out of [t_his] flesh!\n" if(digitalcamo) msg += "[t_He] [t_is] repulsively uncanny!\n" if(!(skipface || ( wear_mask && ( wear_mask.flags_inv & HIDEFACE || wear_mask.flags_cover & MASKCOVERSMOUTH) ) ) && is_thrall(src) && in_range(user,src)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 55993dbf5f5..5d521d8316f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -8,7 +8,6 @@ //why are these here and not in human_defines.dm //var/list/hud_list[10] var/datum/species/species //Contains icon generation and language information, set during New(). - var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call. /mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna = 0) @@ -700,6 +699,28 @@ if(G && G.pickpocket) thief_mode = 1 + if(href_list["embedded_object"]) + var/obj/item/organ/external/L = locate(href_list["embedded_limb"]) in bodyparts + if(!L) + return + var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects + if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore + return + var/time_taken = I.embedded_unsafe_removal_time*I.w_class + usr.visible_message("[usr] attempts to remove [I] from their [L.name].","You attempt to remove [I] from your [L.name]... (It will take [time_taken/10] seconds.)") + if(do_after(usr, time_taken, needhand = 1, target = src)) + if(!I || !L || I.loc != src || !(I in L.embedded_objects)) + return + L.embedded_objects -= I + L.take_damage(I.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus. + I.forceMove(get_turf(src)) + usr.put_in_hands(I) + usr.emote("scream") + usr.visible_message("[usr] successfully rips [I] out of their [L.name]!","You successfully remove [I] from your [L.name].") + if(!has_embedded_objects()) + clear_alert("embeddedobject") + return + if(href_list["item"]) var/slot = text2num(href_list["item"]) if(slot in check_obscured_slots()) @@ -1348,16 +1369,6 @@ else ..() -/mob/living/carbon/human/get_visible_implants(var/class = 0) - - var/list/visible_implants = list() - for(var/obj/item/organ/external/organ in bodyparts) - for(var/obj/item/weapon/O in organ.implants) - if(!istype(O,/obj/item/weapon/implant) && (O.w_class > class) && !istype(O,/obj/item/weapon/shard/shrapnel)) - visible_implants += O - - return(visible_implants) - /mob/living/carbon/human/generate_name() name = species.makeName(gender,src) real_name = name @@ -1365,29 +1376,6 @@ dna.real_name = name return name -/mob/living/carbon/human/proc/handle_embedded_objects() - - for(var/obj/item/organ/external/organ in bodyparts) - if(organ.status & ORGAN_SPLINTED) //Splints prevent movement. - continue - for(var/obj/item/weapon/O in organ.implants) - if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad. - // All kinds of embedded objects cause bleeding. - var/msg = null - switch(rand(1,3)) - if(1) - msg ="A spike of pain jolts your [organ.name] as you bump [O] inside." - if(2) - msg ="Your movement jostles [O] in your [organ.name] painfully." - if(3) - msg ="[O] in your [organ.name] twists painfully as you move." - to_chat(src, msg) - - organ.take_damage(rand(1,3), 0, 0) - if(!(organ.status & ORGAN_ROBOT)) //There is no blood in protheses. - organ.status |= ORGAN_BLEEDING - src.adjustToxLoss(rand(1,3)) - /mob/living/carbon/human/verb/check_pulse() set category = null set name = "Check pulse" diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index ef7cfef5e31..fe70c2aa887 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -8,7 +8,7 @@ emp_act */ -/mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone) +/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone) if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) if(check_reflect(def_zone)) // Checks if you've passed a reflection% check @@ -41,19 +41,6 @@ emp_act . = bullet_act(P, "chest") //act on chest instead return - //Shrapnel - if(P.damage_type == BRUTE) - var/armor = getarmor_organ(organ, "bullet") - if((P.embed && prob(20 + max(P.damage - armor, -10)))) - var/obj/item/weapon/shard/shrapnel/SP = new() - (SP.name) = "[P.name] shrapnel" - if(P.ammo_casing && P.ammo_casing.caliber) - (SP.desc) = "[SP.desc] It looks like it is a [P.ammo_casing.caliber] caliber round." - else - (SP.desc) = "[SP.desc] The round's caliber is unidentifiable." - (SP.loc) = organ - organ.embed(SP) - organ.add_autopsy_data(P.name, P.damage) // Add the bullet's name to the autopsy data return (..(P , def_zone)) @@ -295,21 +282,6 @@ emp_act if(Iforce > 10 || Iforce >= 5 && prob(33)) forcesay(hit_appends) //forcesay checks stat already -/* //Melee weapon embedded object code. Commented out, as most people on the forums seem to find this annoying and think it does not contribute to general gameplay. - Dave - if(I.damtype == BRUTE && !I.is_robot_module()) - var/damage = I.force - if(armor) - damage /= armor+1 - - //blunt objects should really not be embedding in things unless a huge amount of force is involved - var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3) - var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class - - //Sharp objects will always embed if they do enough damage. - if(((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance))) && (I.no_embed == 0) ) - affecting.embed(I) - return 1*/ - //this proc handles being hit by a thrown atom /mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0) var/obj/item/I @@ -323,24 +295,19 @@ emp_act hitpush = 0 skipcatch = 1 blocked = 1 - /*else if(I) + else if(I) if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD) - if(!I.is_robot_module()) - var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].", I.armour_penetration) //I guess "melee" is the best fit here - var/sharp = is_sharp(I) - var/damage = throwpower * (I.throw_speed / 5) - if(armor) - damage /= armor + 1 - - //blunt objects should really not be embedding in things unless a huge amount of force is involved - var/embed_chance = sharp? damage / I.w_class : damage/(I.w_class * 3) - var/embed_threshold = sharp? 5 * I.w_class : 15 * I.w_class - - //Sharp objects will always embed if they do enough damage. - //Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold - - if(((sharp && prob(damage / (10 * I.w_class) * 100)) || (damage > embed_threshold && prob(embed_chance))) && (I.no_embed == 0)) - affecting.embed(I)*/ + if(can_embed(I)) + if(prob(I.embed_chance)) + throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) + var/obj/item/organ/external/L = pick(bodyparts) + L.embedded_objects |= I +// I.add_mob_blood(src)//it embedded itself in you, of course it's bloody! + I.forceMove(src) + L.take_damage(I.w_class*I.embedded_impact_pain_multiplier) + visible_message("[I] embeds itself in [src]'s [L.name]!","[I] embeds itself in your [L.name]!") + hitpush = 0 + skipcatch = 1 //can't catch the now embedded item return ..() /mob/living/carbon/human/proc/bloody_hands(var/mob/living/source, var/amount = 2) @@ -419,5 +386,5 @@ emp_act /mob/living/carbon/human/water_act(volume, temperature, source) ..() - if(temperature >= 330) bodytemperature = bodytemperature + (temperature - bodytemperature) - if(temperature <= 280) bodytemperature = bodytemperature - (bodytemperature - temperature) + species.water_act(src,volume,temperature,source) + diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index f51ba71bff8..d375028b545 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -40,6 +40,10 @@ if(!client) species.handle_npc(src) + if(stat != DEAD) + //Stuff jammed in your limbs hurts + handle_embedded_objects() + if(stat == DEAD) handle_decay() @@ -813,13 +817,6 @@ blinded = 1 stat = UNCONSCIOUS - if(embedded_flag && !(mob_master.current_cycle % 10)) - var/list/E - E = get_visible_implants(0) - if(!E.len) - embedded_flag = 0 - - //Vision //god knows why this is here var/obj/item/organ/vision if(species.vision_organ) @@ -932,6 +929,22 @@ adjustToxLoss(-3) lastpuke = 0 +/mob/living/carbon/human/proc/handle_embedded_objects() + for(var/X in bodyparts) + var/obj/item/organ/external/BP = X + for(var/obj/item/I in BP.embedded_objects) + if(prob(I.embedded_pain_chance)) + BP.take_damage(I.w_class*I.embedded_pain_multiplier) + to_chat(src, "[I] embedded in your [BP.name] hurts!") + + if(prob(I.embedded_fall_chance)) + BP.take_damage(I.w_class*I.embedded_fall_pain_multiplier) + BP.embedded_objects -= I + I.forceMove(get_turf(src)) + visible_message("[I] falls out of [name]'s [BP.name]!","[I] falls out of your [BP.name]!") + if(!has_embedded_objects()) + clear_alert("embeddedobject") + /mob/living/carbon/human/handle_changeling() if(mind) if(mind.changeling) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 9dff4bdcfef..8f547b7db15 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -399,9 +399,6 @@ if(has_gravity(H)) gravity = 1 - if(H.embedded_flag) - H.handle_embedded_objects() //Moving with objects stuck in you can cause bad times. - if(!ignoreslow && gravity) if(slowdown) . = slowdown @@ -741,3 +738,9 @@ It'll return null if the organ doesn't correspond, so include null checks when u if(H.see_override) //Override all H.see_invisible = H.see_override + +/datum/species/proc/water_act(mob/living/carbon/human/M, volume, temperature, source) + if(temperature >= 330) + M.bodytemperature = M.bodytemperature + (temperature - M.bodytemperature) + if(temperature <= 280) + M.bodytemperature = M.bodytemperature - (M.bodytemperature - temperature) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index 150f2d647bc..370bd63d466 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -753,6 +753,11 @@ genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED) ..() +/datum/species/grey/water_act(var/mob/living/carbon/C, volume, temperature, source) + ..() + C.take_organ_damage(5,min(volume,20)) + C.emote("scream") + /datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H) var/speech_pref = H.client.prefs.speciesprefs if(speech_pref) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 90003c12e65..7215c05a8e2 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -512,6 +512,7 @@ human_mob.restore_blood() human_mob.shock_stage = 0 human_mob.decaylevel = 0 + human_mob.remove_all_embedded_objects() restore_all_organs() surgeries.Cut() //End all surgeries. diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index 16c8f1a3ef0..3454a6597ab 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -260,10 +260,6 @@ stored_comms["glass"]++ else if(istype(W,/obj/item/ammo_casing)) stored_comms["metal"]++ - else if(istype(W,/obj/item/weapon/shard/shrapnel)) - stored_comms["metal"]++ - stored_comms["metal"]++ - stored_comms["metal"]++ else if(istype(W,/obj/item/weapon/shard)) stored_comms["glass"]++ stored_comms["glass"]++ diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 226e568f09e..aadd5a74c1b 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1052,104 +1052,6 @@ var/list/slot_equipment_priority = list( \ /mob/proc/get_species() return "" -/mob/proc/get_visible_implants(var/class = 0) - var/list/visible_implants = list() - for(var/obj/item/O in embedded) - if(O.w_class > class) - visible_implants += O - return visible_implants - -/mob/proc/yank_out_object() - set category = "Object" - set name = "Yank out object" - set desc = "Remove an embedded item at the cost of bleeding and pain." - set src in view(1) - - if(!isliving(usr) || usr.next_move > world.time) - return - usr.changeNext_move(CLICK_CD_RESIST) - - if(usr.stat == 1) - to_chat(usr, "You are unconcious and cannot do that!") - return - - if(usr.restrained()) - to_chat(usr, "You are restrained and cannot do that!") - return - - var/mob/S = src - var/mob/U = usr - var/list/valid_objects = list() - var/self = null - - if(S == U) - self = 1 // Removing object from yourself. - - valid_objects = get_visible_implants(0) - if(!valid_objects.len) - if(self) - to_chat(src, "You have nothing stuck in your body that is large enough to remove.") - else - to_chat(U, "[src] has nothing stuck in their wounds that is large enough to remove.") - return - - var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects - - if(self) - visible_message("[usr] appears to be trying to extract an object from their body.") - to_chat(src, "You attempt to get a good grip on [selection] in your body.") - else - visible_message("[usr] attempts to get a good grip on [selection] in [S]'s body.") - to_chat(U, "You attempt to get a good grip on [selection] in [S]'s body.") - - if(!do_after(U, 80, target = S)) - return - if(!selection || !S || !U) - return - - if(self) - visible_message("[src] rips [selection] out of their body.","You rip [selection] out of your body.") - else - visible_message("[usr] rips [selection] out of [src]'s body.","[usr] rips [selection] out of your body.") - valid_objects = get_visible_implants(0) - if(valid_objects.len == 1) //Yanking out last object - removing verb. - src.verbs -= /mob/proc/yank_out_object - - if(ishuman(src)) - - var/mob/living/carbon/human/H = src - var/obj/item/organ/external/affected - - for(var/obj/item/organ/external/organ in H.bodyparts) //Grab the organ holding the implant. - for(var/obj/item/weapon/O in organ.implants) - if(O == selection) - affected = organ - - affected.implants -= selection - H.shock_stage+=10 - - if(prob(10)) //I'M SO ANEMIC I COULD JUST -DIE-. - var/datum/wound/internal_bleeding/I = new () - affected.wounds += I - H.custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 1) - - if(ishuman(U)) - var/mob/living/carbon/human/human_user = U - human_user.bloody_hands(H) - - selection.forceMove(get_turf(src)) - if(!(U.l_hand && U.r_hand)) - U.put_in_hands(selection) - - for(var/obj/item/weapon/O in pinned) - if(O == selection) - pinned -= O - if(!pinned.len) - anchored = 0 - return 1 - - - /mob/dead/observer/verb/respawn() set name = "Respawn as NPC" set category = "Ghost" diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 700e5d912e7..3b187232d77 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -53,8 +53,6 @@ var/lastpuke = 0 var/unacidable = 0 var/can_strip = 1 - var/list/pinned = list() //List of things pinning this creature to walls (see living_defense.dm) - var/list/embedded = list() //Embedded items, since simple mobs don't have organs. var/list/languages = list() // For speaking/listening. var/list/abilities = list() // For species-derived or admin-given powers. var/list/speak_emote = list("says") // Verbs used when speaking. Defaults to 'say' if speak_emote is null. diff --git a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm index 20c4e92fd98..a868c0958ea 100644 --- a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm +++ b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm @@ -43,7 +43,7 @@ if(!istype(file)) data["error"] = "I/O ERROR: Unable to open file." else - data["filedata"] = pencode_to_html(file.stored_data, sign = 0, fields = 0) + data["filedata"] = pencode_to_html(file.stored_data, format = 1, sign = 0, fields = 0) data["filename"] = "[file.filename].[file.filetype]" else if(!computer || !HDD) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 250abe3d682..cd5b065b3ca 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -203,7 +203,7 @@ /obj/item/weapon/paper/proc/parsepencode(var/t, var/obj/item/weapon/pen/P, mob/user as mob) - t = pencode_to_html(t, usr, P, TRUE, TRUE, deffont, signfont, crayonfont) + t = pencode_to_html(t, usr, P, TRUE, TRUE, TRUE, deffont, signfont, crayonfont) //Count the fields var/laststart = 1 diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 0c16fefce1e..d93281f2468 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -158,6 +158,7 @@ w_class = initial(w_class) name = initial(name) hitsound = initial(hitsound) + embed_chance = initial(embed_chance) throwforce = initial(throwforce) playsound(user, 'sound/weapons/saberoff.ogg', 5, 1) to_chat(user, "[src] can now be concealed.") @@ -168,6 +169,7 @@ w_class = WEIGHT_CLASS_NORMAL name = "energy dagger" hitsound = 'sound/weapons/blade1.ogg' + embed_chance = 100 //rule of cool throwforce = 35 playsound(user, 'sound/weapons/saberon.ogg', 5, 1) to_chat(user, "[src] is now active.") diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm index c7eaed9f7a8..18101968d6f 100644 --- a/code/modules/projectiles/guns/alien.dm +++ b/code/modules/projectiles/guns/alien.dm @@ -99,6 +99,5 @@ flag = "bullet" pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE - embed = 0 weaken = 5 stun = 5 diff --git a/code/modules/projectiles/guns/throw/crossbow.dm b/code/modules/projectiles/guns/throw/crossbow.dm index de90891bbd9..00bafd296ce 100644 --- a/code/modules/projectiles/guns/throw/crossbow.dm +++ b/code/modules/projectiles/guns/throw/crossbow.dm @@ -169,8 +169,6 @@ /obj/item/weapon/arrow/rod/removed() if(superheated) // The rod has been superheated - we don't want it to be useable when removed from the bow. visible_message("[src] shatters into a scattering of overstressed metal shards as it leaves the crossbow.") - var/obj/item/weapon/shard/shrapnel/S = new /obj/item/weapon/shard/shrapnel - S.loc = get_turf(src) qdel(src) #undef XBOW_TENSION_20 diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 4a3afd18684..20957e18786 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -48,7 +48,6 @@ var/drowsy = 0 var/stamina = 0 var/jitter = 0 - var/embed = 0 // whether or not the projectile can embed itself in the mob var/forcedodge = 0 //to pass through everything var/dismemberment = 0 //The higher the number, the greater the bonus to dismembering. 0 will not dismember at all. diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index d8c8138ad56..41ee674bc01 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -4,7 +4,6 @@ damage = 60 damage_type = BRUTE flag = "bullet" - embed = 1 hitsound_wall = "ricochet" /obj/item/projectile/bullet/weakbullet //beanbag, heavy stamina damage @@ -13,10 +12,8 @@ stamina = 80 /obj/item/projectile/bullet/weakbullet/rubber //beanbag that shells that don't embed - embed = 0 /obj/item/projectile/bullet/weakbullet/booze - embed = 0 /obj/item/projectile/bullet/weakbullet/booze/on_hit(atom/target, blocked = 0) if(..(target, blocked)) @@ -43,7 +40,6 @@ icon_state = "bullet-r" /obj/item/projectile/bullet/weakbullet2/rubber //detective's bullets that don't embed - embed = 0 /obj/item/projectile/bullet/weakbullet3 damage = 20 @@ -53,7 +49,6 @@ damage = 5 stamina = 30 icon_state = "bullet-r" - embed = 0 /obj/item/projectile/bullet/toxinbullet damage = 15 @@ -141,7 +136,6 @@ name = "rubber pellet" damage = 3 stamina = 25 - embed = 0 icon_state = "bullet-r" /obj/item/projectile/bullet/stunshot//taser slugs for shotguns, nothing special @@ -152,7 +146,6 @@ stutter = 5 jitter = 20 range = 7 - embed = 0 icon_state = "spark" color = "#FFFF00" @@ -203,7 +196,6 @@ stun = 5 forcedodge = 1 nodamage = 1 - embed = 0 pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE hitsound = 'sound/items/bikehorn.ogg' icon = 'icons/obj/hydroponics/harvest.dmi' @@ -237,7 +229,6 @@ name = "dart" icon_state = "cbbolt" damage = 6 - embed = 0 var/piercing = 0 /obj/item/projectile/bullet/dart/New() @@ -299,7 +290,6 @@ name = "cap" damage = 0 nodamage = 1 - embed = 0 /obj/item/projectile/bullet/cap/fire() loc = null diff --git a/code/modules/projectiles/projectile/force.dm b/code/modules/projectiles/projectile/force.dm index 4e5c6d27700..4d62550a852 100644 --- a/code/modules/projectiles/projectile/force.dm +++ b/code/modules/projectiles/projectile/force.dm @@ -4,7 +4,6 @@ icon_state = "ice_1" damage = 20 flag = "energy" - embed = 1 /obj/item/projectile/forcebolt/strong name = "force bolt" diff --git a/code/modules/projectiles/projectile/reusable.dm b/code/modules/projectiles/projectile/reusable.dm index dbe00614d55..c66913651a3 100644 --- a/code/modules/projectiles/projectile/reusable.dm +++ b/code/modules/projectiles/projectile/reusable.dm @@ -35,7 +35,6 @@ ammo_type = /obj/item/ammo_casing/caseless/foam_dart range = 10 var/obj/item/weapon/pen/pen = null - embed = 0 log_override = TRUE//it won't log even when there's a pen inside, but since the damage will be so low, I don't think there's any point in making it any more complex /obj/item/projectile/bullet/reusable/foam_dart/handle_drop() diff --git a/code/modules/reagents/chemistry/reagents/water.dm b/code/modules/reagents/chemistry/reagents/water.dm index 70d2a9f76c0..773d03c6006 100644 --- a/code/modules/reagents/chemistry/reagents/water.dm +++ b/code/modules/reagents/chemistry/reagents/water.dm @@ -20,10 +20,65 @@ drink_desc = "The father of all refreshments." /datum/reagent/water/reaction_mob(mob/living/M, method=TOUCH, volume) -// Put out fire if(method == TOUCH) + // Put out fire M.adjust_fire_stacks(-(volume / 10)) M.ExtinguishMob() + if(ishuman(M)) + + var/mob/living/carbon/human/H = M + + if(H.get_species() != "Grey") //God this is so gross I hate it. + return + + if(volume > 25) + + if(H.wear_mask) + to_chat(H, "Your mask protects you from the water!") + return + + if(H.head) + to_chat(H, "Your helmet protects you from the water!") + return + + if(!M.unacidable) + if(prob(75)) + var/obj/item/organ/external/affecting = H.get_organ("head") + if(affecting) + affecting.take_damage(5, 10) + H.UpdateDamageIcon() + H.emote("scream") + else + M.take_organ_damage(5,10) + else + M.take_organ_damage(5,10) + + if(method == INGEST) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + + if(H.get_species() != "Grey") + return + + if(volume < 10) + to_chat(M, "The watery solvent substance stings you, but isn't concentrated enough to harm you!") + + if(volume >=10 && volume <=25) + if(!H.unacidable) + M.take_organ_damage(0,min(max(volume-10,2)*2,20)) + M.emote("scream") + + + if(volume > 25) + if(!M.unacidable) + if(prob(75)) + var/obj/item/organ/external/affecting = H.get_organ("head") + if(affecting) + affecting.take_damage(0, 20) + H.UpdateDamageIcon() + H.emote("scream") + else + M.take_organ_damage(0,20) /datum/reagent/water/reaction_turf(turf/simulated/T, volume) if(!istype(T)) diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/cavity_implant.dm similarity index 53% rename from code/modules/surgery/implant.dm rename to code/modules/surgery/cavity_implant.dm index 498976c4635..bd82e7192ae 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/cavity_implant.dm @@ -1,10 +1,3 @@ -//Procedures in this file: Putting items in body cavity. Implant removal. Items removal. - - -////////////////////////////////////////////////////////////////// -// ITEM PLACEMENT SURGERY // -////////////////////////////////////////////////////////////////// - /datum/surgery/cavity_implant name = "Cavity Implant/Removal" steps = list(/datum/surgery_step/generic/cut_open,/datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/open_encased/saw, @@ -199,198 +192,15 @@ affected.wounds += I affected.owner.custom_pain("You feel something rip in your [affected.name]!", 1) user.drop_item() - target.internal_organs += tool + affected.hidden = tool tool.forceMove(affected) return 1 else if(IC) user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "You pull [IC] out of [target]'s [target_zone].") user.put_in_hands(IC) - target.internal_organs -= IC + affected.hidden = null return 1 else to_chat(user, "You don't find anything in [target]'s [target_zone].") - return 0 - - -////////////////////////////////////////////////////////////////// -// IMPLANT/ITEM REMOVAL SURGERY // -////////////////////////////////////////////////////////////////// - -/datum/surgery/cavity_implant_rem - name = "Implant Removal" - steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin,/datum/surgery_step/cavity/implant_removal,/datum/surgery_step/cavity/close_space,/datum/surgery_step/generic/cauterize/) - possible_locs = list("chest")//head is for borers..i can put it elsewhere - -/datum/surgery/cavity_implant_rem/synth - name = "Implant Removal" - steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/cavity/implant_removal,/datum/surgery_step/robotics/external/close_hatch) - possible_locs = list("chest")//head is for borers..i can put it elsewhere - -/datum/surgery/cavity_implant_rem/can_start(mob/user, mob/living/carbon/human/target) - if(!istype(target)) - return 0 - var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) - if(!affected) - return 0 - if(affected.status & ORGAN_ROBOT) - return 0 - return 1 - -/datum/surgery/cavity_implant_rem/synth/can_start(mob/user, mob/living/carbon/human/target) - if(!istype(target)) - return 0 - var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) - if(!affected) - return 0 - if(!(affected.status & ORGAN_ROBOT)) - return 0 - - return 1 - -/datum/surgery_step/cavity/implant_removal - name = "extract implant" - allowed_tools = list( - /obj/item/weapon/hemostat = 100, \ - /obj/item/weapon/wirecutters = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - var/obj/item/weapon/implant/I = null - time = 64 - -/datum/surgery_step/cavity/implant_removal/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - I = locate(/obj/item/weapon/implant) in target - user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \ - "You start poking around inside [target]'s [affected.name] with \the [tool]." ) - target.custom_pain("The pain in your [affected.name] is living hell!",1) - ..() - -/datum/surgery_step/cavity/implant_removal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - I = locate(/obj/item/weapon/implant) in target - if(I && (target_zone == "chest")) //implant removal only works on the chest. - user.visible_message("[user] takes something out of [target]'s [affected.name] with \the [tool].", \ - "You take [I] out of [target]'s [affected.name]s with \the [tool]." ) - - I.removed(target) - - var/obj/item/weapon/implantcase/case - - if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase)) - case = user.get_item_by_slot(slot_l_hand) - else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase)) - case = user.get_item_by_slot(slot_r_hand) - else - case = locate(/obj/item/weapon/implantcase) in get_turf(target) - - if(case && !case.imp) - case.imp = I - I.loc = case - case.update_icon() - user.visible_message("[user] places [I] into [case]!", "You place [I] into [case].") - else - qdel(I) - return 1 - else - user.visible_message(" [user] could not find anything inside [target]'s [affected.name], and pulls \the [tool] out.", \ - "You could not find anything inside [target]'s [affected.name].") - return 1 - -/datum/surgery_step/cavity/implant_removal/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - ..() - var/obj/item/organ/external/chest/affected = target.get_organ(target_zone) - if(affected.implants.len) - var/fail_prob = 10 - fail_prob += 100 - tool_quality(tool) - if(prob(fail_prob)) - var/obj/item/weapon/implant/imp = affected.implants[1] - user.visible_message(" Something beeps inside [target]'s [affected.name]!") - playsound(imp.loc, 'sound/items/countdown.ogg', 75, 1, -3) - spawn(25) - imp.activate() - return 0 - - -////////////////////////////////////////////////////////////////// -// EMBEDDED ITEM REOMOVAL // -////////////////////////////////////////////////////////////////// - -/datum/surgery/embedded_removal - name = "Removal of Embedded Objects" - steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/remove_object, /datum/surgery_step/generic/cauterize) - possible_locs = list("r_arm","l_arm","r_leg","l_leg","r_hand","r_foot","l_hand","l_foot","groin","chest","head") - -/datum/surgery/embedded_removal/synth - steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch, /datum/surgery_step/remove_object, /datum/surgery_step/robotics/external/close_hatch) - possible_locs = list("r_arm","l_arm","r_leg","l_leg","r_hand","r_foot","l_hand","l_foot","groin","chest","head") - - -/datum/surgery/embedded_removal/can_start(mob/user, mob/living/carbon/human/target) - if(!istype(target)) - return 0 - var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) - if(!affected) - return 0 - if(affected.status & ORGAN_ROBOT) - return 0 - return 1 - -/datum/surgery/embedded_removal/synth/can_start(mob/user, mob/living/carbon/human/target) - if(!istype(target)) - return 0 - var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) - if(!affected) - return 0 - if(!(affected.status & ORGAN_ROBOT)) - return 0 - return 1 - -/datum/surgery_step/remove_object - name = "remove embedded objects" - time = 32 - allowed_tools = list( - /obj/item/weapon/scalpel/laser/manager = 100, \ - /obj/item/weapon/hemostat = 100, \ - /obj/item/stack/cable_coil = 75, \ - /obj/item/device/assembly/mousetrap = 20 - ) - var/obj/item/organ/external/L = null - - -/datum/surgery_step/remove_object/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) - L = target.get_organ(target_zone) - if(L) - user.visible_message("[user] looks for objects embedded in [target]'s [target_zone].", "You look for objects embedded in [target]'s [target_zone]...") - else - user.visible_message("[user] looks for [target]'s [target_zone].", "You look for [target]'s [target_zone]...") - - -/datum/surgery_step/remove_object/end_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) - if(L) - if(ishuman(target)) - var/mob/living/carbon/human/H = target - var/objects = 0 - for(var/obj/item/I in L.implants) - if(!istype(I,/obj/item/weapon/implant)) - objects++ - I.forceMove(get_turf(H)) - L.implants -= I - - //Handle possessive brain borers. - if(H.has_brain_worms() && target_zone == "head")//remove worms outside the loop - var/mob/living/simple_animal/borer/worm = H.has_brain_worms() - if(worm.controlling) - target.release_control() - worm.detach() - worm.leave_host() - user.visible_message("a slug like creature wiggles out of [H]'s [target_zone]!") - - if(objects > 0) - user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L.limb_name]!", "You sucessfully remove [objects] objects from [H]'s [L.limb_name].") - else - to_chat(user, "You find no objects embedded in [H]'s [L.limb_name]!") - else - to_chat(user, "You can't find [target]'s [target_zone], let alone any objects embedded in it!") - - return 1 + return 0 \ No newline at end of file diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm new file mode 100644 index 00000000000..7b04be81e1d --- /dev/null +++ b/code/modules/surgery/implant_removal.dm @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////// +// IMPLANT REMOVAL SURGERY // +////////////////////////////////////////////////////////////////// + +/datum/surgery/implant_removal + name = "Implant Removal" + steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin,/datum/surgery_step/extract_implant,/datum/surgery_step/generic/cauterize) + possible_locs = list("chest") + +/datum/surgery/implant_removal/synth + name = "Implant Removal" + steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/extract_implant,/datum/surgery_step/robotics/external/close_hatch) + possible_locs = list("chest") + +/datum/surgery/implant_removal/can_start(mob/user, mob/living/carbon/human/target) + if(!istype(target)) + return 0 + var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) + if(!affected) + return 0 + if(affected.status & ORGAN_ROBOT) + return 0 + return 1 + +/datum/surgery/implant_removal/synth/can_start(mob/user, mob/living/carbon/human/target) + if(!istype(target)) + return 0 + var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) + if(!affected) + return 0 + if(!(affected.status & ORGAN_ROBOT)) + return 0 + + return 1 + +/datum/surgery_step/extract_implant + name = "extract implant" + allowed_tools = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 65) + time = 64 + var/obj/item/weapon/implant/I = null + +/datum/surgery_step/extract_implant/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + I = locate(/obj/item/weapon/implant) in target + user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \ + "You start poking around inside [target]'s [affected.name] with \the [tool]." ) + target.custom_pain("The pain in your [affected.name] is living hell!",1) + ..() + +/datum/surgery_step/extract_implant/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + I = locate(/obj/item/weapon/implant) in target + if(I && (target_zone == "chest")) //implant removal only works on the chest. + user.visible_message("[user] takes something out of [target]'s [affected.name] with \the [tool].", \ + "You take [I] out of [target]'s [affected.name]s with \the [tool]." ) + + I.removed(target) + + var/obj/item/weapon/implantcase/case + + if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase)) + case = user.get_item_by_slot(slot_l_hand) + else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase)) + case = user.get_item_by_slot(slot_r_hand) + else + case = locate(/obj/item/weapon/implantcase) in get_turf(target) + + if(case && !case.imp) + case.imp = I + I.forceMove(case) + case.update_icon() + user.visible_message("[user] places [I] into [case]!", "You place [I] into [case].") + else + qdel(I) + else + user.visible_message(" [user] could not find anything inside [target]'s [affected.name], and pulls \the [tool] out.", \ + "You could not find anything inside [target]'s [affected.name].") + return 1 \ No newline at end of file diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index 174076c5fab..773508c88ea 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -52,4 +52,7 @@ qdel(tool) + affected.open = 0 + affected.germ_level = 0 + affected.status &= ~ORGAN_BLEEDING return 1 \ No newline at end of file diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index 28c43071b2c..b43b7ad1c64 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -59,7 +59,7 @@ var/encased // Needs to be opened with a saw to access the organs. var/obj/item/hidden = null - var/list/implants = list() + var/list/embedded_objects = list() // how often wounds should be updated, a higher number means less often var/wound_update_accuracy = 1 @@ -105,7 +105,7 @@ QDEL_LIST(wounds) - QDEL_LIST(implants) + QDEL_LIST(embedded_objects) QDEL_NULL(hidden) @@ -363,12 +363,6 @@ This function completely restores a damaged organ to perfect condition. for(var/obj/item/organ/external/EO in contents) EO.rejuvenate() - // remove embedded objects and drop them on the floor - for(var/obj/implanted_object in implants) - if(!istype(implanted_object,/obj/item/weapon/implant)) // We don't want to remove REAL implants. Just shrapnel etc. - implanted_object.loc = owner.loc - implants -= implanted_object - owner.updatehealth() update_icon() if(!owner) @@ -911,20 +905,6 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/proc/is_malfunctioning() return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam) && !tough) -/obj/item/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0) - if(!owner || loc != owner) - return - if(!silent) - owner.visible_message("\The [W] sticks in the wound!") - implants += W - owner.embedded_flag = 1 - owner.verbs += /mob/proc/yank_out_object - W.add_blood(owner) - if(ismob(W.loc)) - var/mob/living/H = W.loc - H.drop_item() - W.loc = owner - /obj/item/organ/external/proc/open_enough_for_surgery() return (encased ? (open == 3) : (open == 2)) @@ -935,14 +915,17 @@ Note that amputating the affected organ does in fact remove the infection from t var/is_robotic = status & ORGAN_ROBOT var/mob/living/carbon/human/victim = owner + for(var/obj/item/I in embedded_objects) + embedded_objects -= I + I.forceMove(src) + if(!owner.has_embedded_objects()) + owner.clear_alert("embeddedobject") + . = ..() status |= ORGAN_DESTROYED victim.bad_external_organs -= src - for(var/implant in implants) //todo: check if this can be left alone - qdel(implant) - // Attached organs also fly off. if(!ignore_children) for(var/obj/item/organ/external/O in children) @@ -1022,3 +1005,22 @@ Note that amputating the affected organ does in fact remove the infection from t ..() // Parent call loads in the DNA if(data["dna"]) sync_colour_to_dna() + +//Remove all embedded objects from all limbs on the carbon mob +/mob/living/carbon/human/proc/remove_all_embedded_objects() + var/turf/T = get_turf(src) + + for(var/X in bodyparts) + var/obj/item/organ/external/L = X + for(var/obj/item/I in L.embedded_objects) + L.embedded_objects -= I + I.forceMove(T) + + clear_alert("embeddedobject") + +/mob/living/carbon/human/proc/has_embedded_objects() + . = 0 + for(var/X in bodyparts) + var/obj/item/organ/external/L = X + for(var/obj/item/I in L.embedded_objects) + return 1 \ No newline at end of file diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 420d56de43d..32badd09ec0 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -159,6 +159,11 @@ else if(implement_type in implements_extract) current_type = "extract" var/list/organs = target.get_organs_zone(target_zone) + var/mob/living/simple_animal/borer/B = target.has_brain_worms() + if(target_zone == "head" && B) + user.visible_message("[user] begins to extract [B] from [target]'s [parse_zone(target_zone)].", + "You begin to extract [B] from [target]'s [parse_zone(target_zone)]...") + return TRUE if(!organs.len) to_chat(user, "There are no removeable organs in [target]'s [parse_zone(target_zone)]!") return -1 @@ -262,6 +267,13 @@ I.status &= ~ORGAN_CUT_AWAY else if(current_type == "extract") + var/mob/living/simple_animal/borer/B = target.has_brain_worms() + if(target_zone == "head" && B && B.host == target) + user.visible_message("[user] successfully extracts [B] from [target]'s [parse_zone(target_zone)]!", + "You successfully extract [B] from [target]'s [parse_zone(target_zone)].") + add_logs(user, target, "surgically removed [B] from", addition="INTENT: [uppertext(user.a_intent)]") + B.leave_host() + return FALSE if(I && I.owner == target) user.visible_message(" [user] has separated and extracts [target]'s [I] with [tool].", " You have separated and extracted [target]'s [I] with [tool].") diff --git a/code/modules/surgery/remove_embedded_object.dm b/code/modules/surgery/remove_embedded_object.dm new file mode 100644 index 00000000000..d7fe8b7fb53 --- /dev/null +++ b/code/modules/surgery/remove_embedded_object.dm @@ -0,0 +1,65 @@ +/datum/surgery/embedded_removal + name = "Removal of Embedded Objects" + steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/remove_object,/datum/surgery_step/generic/cauterize) + possible_locs = list("head", "chest", "l_arm", "l_hand", "r_arm", "r_hand","r_leg", "r_foot", "l_leg", "l_foot", "groin") + +/datum/surgery/embedded_removal/synth + steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/remove_object,/datum/surgery_step/robotics/external/close_hatch) + +/datum/surgery/embedded_removal/can_start(mob/user, mob/living/carbon/human/target) + if(!istype(target)) + return 0 + var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) + if(!affected) + return 0 + if(affected.status & ORGAN_ROBOT) + return 0 + return 1 + +/datum/surgery/embedded_removal/synth/can_start(mob/user, mob/living/carbon/human/target) + if(!istype(target)) + return 0 + var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting) + if(!affected) + return 0 + if(!(affected.status & ORGAN_ROBOT)) + return 0 + + return 1 + +/datum/surgery_step/remove_object + name = "Remove Embedded Objects" + time = 32 + accept_hand = 1 + var/obj/item/organ/external/L = null + + +/datum/surgery_step/remove_object/begin_step(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + L = surgery.organ_ref + if(L) + user.visible_message("[user] looks for objects embedded in [target]'s [parse_zone(user.zone_sel.selecting)].", "You look for objects embedded in [target]'s [parse_zone(user.zone_sel.selecting)]...") + else + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_sel.selecting)].", "You look for [target]'s [parse_zone(user.zone_sel.selecting)]...") + + +/datum/surgery_step/remove_object/end_step(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(L) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + var/objects = 0 + for(var/obj/item/I in L.embedded_objects) + objects++ + I.forceMove(get_turf(H)) + L.embedded_objects -= I + if(!H.has_embedded_objects()) + H.clear_alert("embeddedobject") + + if(objects > 0) + user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L]!", "You successfully remove [objects] objects from [H]'s [L.name].") + else + to_chat(user, "You find no objects embedded in [H]'s [L]!") + + else + to_chat(user, "You can't find [target]'s [parse_zone(user.zone_sel.selecting)], let alone any objects embedded in it!") + + return 1 \ No newline at end of file diff --git a/code/world.dm b/code/world.dm index 34d61dbbc21..e293058cdf6 100644 --- a/code/world.dm +++ b/code/world.dm @@ -244,6 +244,27 @@ var/world_topic_spam_protect_time = world.timeofday for(var/client/C in clients) to_chat(C, "PR: [input["announce"]]") + else if("kick" in input) + /* + We have a kick request over coms. + Only needed portion is the ckey + */ + if(!key_valid) + return keySpamProtect(addr) + + var/client/C + + for(var/client/K in clients) + if(K.ckey == input["kick"]) + C = K + break + if(!C) + return "No client with that name on server" + + del(C) + + return "Kick Successful" + /proc/keySpamProtect(var/addr) if(world_topic_spam_protect_ip == addr && abs(world_topic_spam_protect_time - world.time) < 50) spawn(50) diff --git a/html/changelog.html b/html/changelog.html index 70f2ffdb953..baba4a216ef 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,37 @@ -->
    +

    30 June 2017

    +

    fludd12 updated:

    + + +

    29 June 2017

    +

    Fox McCloud updated:

    + +

    Kluys updated:

    + + +

    28 June 2017

    +

    Fox McCloud updated:

    + +

    Purpose2 and Re-Opened by Fethas updated:

    + +

    27 June 2017

    Alexshreds updated: