diff --git a/__DEFINES/colors.dm b/__DEFINES/colors.dm index ad5404c0813..201b2a1cbbe 100644 --- a/__DEFINES/colors.dm +++ b/__DEFINES/colors.dm @@ -16,3 +16,8 @@ #define COLOR_GLUE "#FFFFCC" #define COLOR_BEESWAX "#FFB700" #define COLOR_DEFAULT_CANDLE "#BE0000" +#define COLOR_RED "#FF0000" +#define COLOR_GREEN "#00FF00" +#define COLOR_BLUE "#0000FF" + +#define COLOR_MATRIX_ADD(color) list(COLOR_RED, COLOR_GREEN, COLOR_BLUE, color) diff --git a/__DEFINES/limb_defines.dm b/__DEFINES/limb_defines.dm index 3179ab63844..266e7f382d2 100644 --- a/__DEFINES/limb_defines.dm +++ b/__DEFINES/limb_defines.dm @@ -15,3 +15,5 @@ #define UNCUFF_LEGS -1 #define UNCUFF_BOTH 0 #define UNCUFF_HANDS 1 + +#define COSMETIC_ORGAN_TAIL "tail" diff --git a/__DEFINES/setup.dm b/__DEFINES/setup.dm index 559089e54b5..6c6dfeb7b01 100644 --- a/__DEFINES/setup.dm +++ b/__DEFINES/setup.dm @@ -326,6 +326,7 @@ var/MAX_EXPLOSION_RANGE = 32 #define ARM_RIGHT 256 #define HAND_LEFT 512 #define HAND_RIGHT 1024 +#define TAIL 524288 // bitflags for clothing parts @@ -352,6 +353,7 @@ var/MAX_EXPLOSION_RANGE = 32 #define HIDEEARS EARS #define HIDEEYES EYES #define HIDEFACE FACE +#define HIDETAIL TAIL #define HIDEHEADHAIR 65536 #define MASKHEADHAIR 131072 #define HIDEBEARDHAIR BEARD @@ -1006,6 +1008,7 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse #define ACID4WATER 4096 //Acid now acts like water, and vice versa. #define NO_BALD 8192 //cannot lose hair through being shaved/radiation/etc #define RGBSKINTONE 16384 +#define HAS_ICON_SKIN_TONE 32768 var/default_colour_matrix = list(1,0,0,0,\ 0,1,0,0,\ @@ -1252,29 +1255,31 @@ var/default_colour_matrix = list(1,0,0,0,\ //Human Overlays Indexes/////////THIS DEFINES WHAT LAYERS APPEARS ON TOP OF OTHERS #define FIRE_LAYER 1 //If you're on fire (/tg/ shit) #define MUTANTRACE_LAYER 2 //TODO: make part of body? -#define MUTATIONS_LAYER 3 -#define DAMAGE_LAYER 4 -#define UNIFORM_LAYER 5 -#define SHOES_LAYER 6 -#define GLOVES_LAYER 7 -#define EARS_LAYER 8 -#define SUIT_LAYER 9 -#define GLASSES_LAYER 10 -#define BELT_LAYER 11 //Possible make this an overlay of somethign required to wear a belt? -#define SUIT_STORE_LAYER 12 -#define HAIR_LAYER 13 //TODO: make part of head layer? -#define GLASSES_OVER_HAIR_LAYER 14 -#define FACEMASK_LAYER 15 -#define HEAD_LAYER 16 -#define BACK_LAYER 17 //Back should be above head so that headgear doesn't hides backpack when facing north -#define ID_LAYER 18 //IDs should be visible above suits and backpacks -#define HANDCUFF_LAYER 19 -#define MUTUALCUFF_LAYER 20 -#define LEGCUFF_LAYER 21 -#define HAND_LAYER 22 -#define TAIL_LAYER 23 //bs12 specific. this hack is probably gonna come back to haunt me -#define TARGETED_LAYER 24 //BS12: Layer for the target overlay from weapon targeting system -#define TOTAL_LAYERS 24 +#define TAIL_UNDERLIMBS_LAYER 3 +#define LIMBS_LAYER 4 +#define MUTATIONS_LAYER 5 +#define DAMAGE_LAYER 6 +#define UNIFORM_LAYER 7 +#define SHOES_LAYER 8 +#define GLOVES_LAYER 9 +#define EARS_LAYER 10 +#define SUIT_LAYER 11 +#define GLASSES_LAYER 12 +#define BELT_LAYER 13 //Possible make this an overlay of somethign required to wear a belt? +#define SUIT_STORE_LAYER 14 +#define HAIR_LAYER 15 //TODO: make part of head layer? +#define GLASSES_OVER_HAIR_LAYER 16 +#define TAIL_LAYER 17 +#define FACEMASK_LAYER 18 +#define HEAD_LAYER 19 +#define BACK_LAYER 20 //Back should be above head so that headgear doesn't hides backpack when facing north +#define ID_LAYER 21 //IDs should be visible above suits and backpacks +#define HANDCUFF_LAYER 22 +#define MUTUALCUFF_LAYER 23 +#define LEGCUFF_LAYER 24 +#define HAND_LAYER 25 +#define TARGETED_LAYER 26 //BS12: Layer for the target overlay from weapon targeting system +#define TOTAL_LAYERS 26 ////////////////////////////////// //Snake stuff so leaderboard can see it too diff --git a/__DEFINES/span.dm b/__DEFINES/span.dm new file mode 100644 index 00000000000..bf07f4e4fe3 --- /dev/null +++ b/__DEFINES/span.dm @@ -0,0 +1,2 @@ +// Sorted alphabetically +#define span_warning(str) ("" + str + "") diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 920e192fbe0..9fd72b04937 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -1,5 +1,6 @@ -#define EMOTE_VISIBLE 1 -#define EMOTE_AUDIBLE 2 +#define EMOTE_VISIBLE (1<<0) +#define EMOTE_AUDIBLE (1<<1) +#define EMOTE_NO_RUNECHAT (1<<2) /* Emote datums, ported from TG station. */ @@ -66,17 +67,19 @@ if (user.client && M?.client?.prefs.mob_chat_on_map && get_dist(M, user) < M?.client.view) M.create_chat_message(user, null, msg_runechat, "", list("italics")) - if (emote_type == EMOTE_VISIBLE) + if(emote_type & EMOTE_VISIBLE) user.visible_message(msg) - for(var/z0 in GetOpenConnectedZlevels(user)) - for (var/mob/O in viewers(world.view, locate(user.x,user.y,z0))) - if (user.client && O?.client?.prefs.mob_chat_on_map && O.stat != UNCONSCIOUS && !(isinvisible(user))) - O.create_chat_message(user, null, msg_runechat, "", list("italics")) - else + if(!(emote_type & EMOTE_NO_RUNECHAT)) + for(var/z0 in GetOpenConnectedZlevels(user)) + for (var/mob/O in viewers(world.view, locate(user.x,user.y,z0))) + if (user.client && O?.client?.prefs.mob_chat_on_map && O.stat != UNCONSCIOUS && !(isinvisible(user))) + O.create_chat_message(user, null, msg_runechat, "", list("italics")) + else if(emote_type & EMOTE_AUDIBLE) for(var/mob/O in get_hearers_in_view(world.view, user)) O.show_message(msg) - if (user.client && O?.client?.prefs.mob_chat_on_map && O.stat != UNCONSCIOUS && !O.is_deaf()) - O.create_chat_message(user, null, msg_runechat, "", list("italics")) + if(!(emote_type & EMOTE_NO_RUNECHAT)) + if(user.client && O?.client?.prefs.mob_chat_on_map && O.stat != UNCONSCIOUS && !O.is_deaf()) + O.create_chat_message(user, null, msg_runechat, "", list("italics")) var/turf/T = get_turf(user) var/location = T ? "[T.x],[T.y],[T.z]" : "nullspace" diff --git a/code/datums/gamemode/dynamic/dynamic_rulesets_midround.dm b/code/datums/gamemode/dynamic/dynamic_rulesets_midround.dm index 4be4c08f75c..7edaddd1e4a 100644 --- a/code/datums/gamemode/dynamic/dynamic_rulesets_midround.dm +++ b/code/datums/gamemode/dynamic/dynamic_rulesets_midround.dm @@ -564,7 +564,7 @@ return ..() /datum/dynamic_ruleset/midround/from_ghosts/rambler/generate_ruleset_body(mob/applicant) - var/mob/living/carbon/human/frankenstein/new_frank = new(pick(latejoin)) + var/mob/living/carbon/human/frankenstein/new_frank = new(pick(latejoin), no_tail = TRUE) var/gender = pick(MALE, FEMALE) new_frank.randomise_appearance_for(gender) new_frank.key = applicant.key diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm new file mode 100644 index 00000000000..42b72a2f72f --- /dev/null +++ b/code/datums/mutable_appearance.dm @@ -0,0 +1,31 @@ +// Mutable appearances are an inbuilt byond datastructure. Read the documentation on them by hitting F1 in DM. +// Basically use them instead of images for overlays/underlays and when changing an object's appearance if you're doing so with any regularity. +// Unless you need the overlay/underlay to have a different direction than the base object. Then you have to use an image due to a bug. + +// Mutable appearances are children of images, just so you know. + +// Mutable appearances erase template vars on new, because they accept an appearance to copy as an arg +// If we have nothin to copy, we set the float plane +/mutable_appearance/New(mutable_appearance/to_copy) + ..() + if(!to_copy) + plane = FLOAT_PLANE + +/** Helper similar to image() + * + * icon - Our appearance's icon + * icon_state - Our appearance's icon state + * layer - Our appearance's layer + * plane - The plane to use for the appearance. + * alpha - Our appearance's alpha + * appearance_flags - Our appearance's appearance_flags +**/ +/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE) + var/mutable_appearance/appearance = new() + appearance.icon = icon + appearance.icon_state = icon_state + appearance.layer = layer + appearance.plane = plane + appearance.alpha = alpha + appearance.appearance_flags |= appearance_flags + return appearance diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index d60e0e72c1b..afc5660913a 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -12,6 +12,9 @@ var/brute_dam = 0 var/burn_dam = 0 +/obj/item/robot_parts/proc/on_attach(datum/organ/external/attached_site) + return + /obj/item/robot_parts/l_arm name = "robot left arm" desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case." @@ -36,6 +39,40 @@ icon_state = LIMB_RIGHT_LEG part = list(LIMB_RIGHT_LEG,LIMB_RIGHT_FOOT) +/obj/item/robot_parts/tail + name = "robot tail" + desc = "A skeletal appendage wrapped in pseudomuscles, with a low-conductivity case." + icon_state = null + part = list(COSMETIC_ORGAN_TAIL) + var/tail_icon_file = 'icons/mob/tails.dmi' + var/tail_type = "vox" + var/static/list/tail_icons = list() + +/obj/item/robot_parts/tail/New(loc, type_of_tail) + if(type_of_tail) + tail_type = type_of_tail + update_icon() + return ..() + +/obj/item/robot_parts/tail/on_attach(datum/organ/external/tail/attached_site) + attached_site.tail_type = tail_type + +/obj/item/robot_parts/tail/attackby(obj/item/W, mob/user) + if(!ismultitool(W)) + return ..() + var/type_of_tail = input(user, "Configure tail type", "Robotic tail design", "vox") as null|anything in list("vox", "tajaran", "unathi") + tail_type = type_of_tail + update_icon() + +/obj/item/robot_parts/tail/update_icon() + var/returned_tail_icon = tail_icons[tail_type] + if(!returned_tail_icon) + var/icon/new_tail_icon = icon(tail_icon_file, "[tail_type]_robotic_BEHIND", EAST) + new_tail_icon.Shift(EAST, 6) + new_tail_icon.Shift(NORTH, 3) + returned_tail_icon = tail_icons[tail_type] = new_tail_icon + icon = returned_tail_icon + /obj/item/robot_parts/chest name = "robot torso" desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell." diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index e1d100fab90..f0a3937c35c 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -1027,7 +1027,7 @@ var/global/maxStackDepth = 10 permeability_coefficient = 0.02 flags = FPRINT pressure_resistance = 5 * ONE_ATMOSPHERE - body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|HANDS + body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|HANDS|TAIL allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/) slowdown = HARDSUIT_SLOWDOWN_BULKY armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50) diff --git a/code/modules/clothing/spacesuits/captain.dm b/code/modules/clothing/spacesuits/captain.dm index 65ace76c0b2..58fa127e733 100644 --- a/code/modules/clothing/spacesuits/captain.dm +++ b/code/modules/clothing/spacesuits/captain.dm @@ -54,7 +54,7 @@ permeability_coefficient = 0.02 clothing_flags = ONESIZEFITSALL pressure_resistance = 200 * ONE_ATMOSPHERE - body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET + body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|TAIL allowed = list(/obj/item/weapon/tank, /obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy, /obj/item/weapon/gun/projectile, /obj/item/ammo_storage, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_nitrogen) slowdown = HARDSUIT_SLOWDOWN_HIGH armor = list(melee = 65, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50) diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index ce7618f0091..91d7a9ef09f 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -25,7 +25,7 @@ permeability_coefficient = 0.01 flags = FPRINT clothing_flags = PLASMAGUARD - body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|HANDS + body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|HANDS|TAIL slowdown = HARDSUIT_SLOWDOWN_LOW allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/weapon/pen,/obj/item/device/flashlight/pen) armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 9425bf14638..6bb13285842 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -487,7 +487,7 @@ var/list/tag_suits_list = list() icon_state = "strait_jacket" item_state = "strait_jacket" origin_tech = Tc_BIOTECH + "=2" - body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|HANDS + body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|HANDS|TAIL species_fit = list(INSECT_SHAPED) /obj/item/clothing/suit/ianshirt diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 0a08c5f5413..95079c14c0e 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -18,7 +18,7 @@ w_class = W_CLASS_LARGE//bulky item gas_transfer_coefficient = 0.90 permeability_coefficient = 0.50 - body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|HANDS + body_parts_covered = ARMS|LEGS|FULL_TORSO|FEET|HANDS|TAIL allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/weapon/extinguisher,/obj/item/tool/irons,/obj/item/tool/crowbar/halligan) slowdown = HARDSUIT_SLOWDOWN_LOW clothing_flags = ONESIZEFITSALL @@ -85,6 +85,7 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 flags = FPRINT + body_parts_covered = ARMS|LEGS|FULL_TORSO|TAIL slowdown = HARDSUIT_SLOWDOWN_HIGH armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE @@ -157,7 +158,7 @@ w_class = W_CLASS_LARGE//bulky item gas_transfer_coefficient = 0.90 permeability_coefficient = 0.50 - body_parts_covered = FULL_BODY + body_parts_covered = FULL_BODY|TAIL allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen) slowdown = 1.5 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 70a1793e5f8..24c8bc44589 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -75,16 +75,18 @@ if(isobserver(M) && M.client.prefs && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(user))) M.show_message("(Follow) " + msg) - if (emote_type == EMOTE_VISIBLE) + if(emote_type & EMOTE_VISIBLE) user.visible_message(msg) - for(var/mob/O in viewers(world.view, user)) - if (O.client && O?.client?.prefs.mob_chat_on_map && get_dist(O, user) < O?.client.view) - O.create_chat_message(user, null, message, "", list("italics")) - else + if(!(emote_type & EMOTE_NO_RUNECHAT)) + for(var/mob/O in viewers(world.view, user)) + if(O.client && O?.client?.prefs.mob_chat_on_map && get_dist(O, user) < O?.client.view) + O.create_chat_message(user, null, message, "", list("italics")) + else if(emote_type & EMOTE_AUDIBLE) for(var/mob/O in get_hearers_in_view(world.view, user)) O.show_message(msg) - if (O.client && O?.client?.prefs.mob_chat_on_map && get_dist(O, user) < O?.client.view) - O.create_chat_message(user, null, message, "", list("italics")) + if(!(emote_type & EMOTE_NO_RUNECHAT)) + if(O.client && O?.client?.prefs.mob_chat_on_map && get_dist(O, user) < O?.client.view) + O.create_chat_message(user, null, message, "", list("italics")) var/location = T ? "[T.x],[T.y],[T.z]" : "nullspace" log_emote("[user.name]/[user.key] (@[location]): [message]") diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index fcff75175f3..68013d85a65 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -14,6 +14,8 @@ if(prob(100 - E.get_damage())) //Override the current limb status and don't cause an explosion E.droplimb(1, 1) + for(var/datum/organ/external/cosmetic_organ in cosmetic_organs) + cosmetic_organ.droplimb(TRUE, TRUE) var/gib_radius = 0 if(reagents.has_reagent(LUBE)) gib_radius = 6 //Your insides are all lubed, so gibs travel much further diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ad557589825..d23693d0ee5 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -97,7 +97,7 @@ ..(new_loc) initialize_basic_NPC_components() -/mob/living/carbon/human/frankenstein/New(var/new_loc, delay_ready_dna = 0) //Just fuck my shit up: the mob +/mob/living/carbon/human/frankenstein/New(var/new_loc, delay_ready_dna = 0, no_tail = FALSE) //Just fuck my shit up: the mob var/list/valid_species = (all_species - list("Krampus", "Horror", "Manifested")) var/datum/species/new_species = all_species[pick(valid_species)] @@ -109,7 +109,20 @@ for(var/datum/organ/external/E in organs) E.species = all_species[pick(valid_species)] - + var/datum/organ/external/tail/tail_datum = get_cosmetic_organ(COSMETIC_ORGAN_TAIL) + if(no_tail) + tail_datum.droplimb(TRUE, spawn_limb = FALSE) + else + var/list/tailed_species = list() + for(var/species_name in all_species) + var/datum/species/picked_species = all_species[species_name] + if(picked_species.anatomy_flags & HAS_TAIL) + tailed_species += picked_species + var/datum/species/species_with_tail = pick(tailed_species) + tail_datum.fleshify() + tail_datum.create_tail_info(species_with_tail) + tail_datum.species = species_with_tail + tail_datum.update_tail(src, random = TRUE) update_body() /mob/living/carbon/human/mushroom/New(var/new_loc, delay_ready_dna = 0) @@ -167,6 +180,8 @@ obj_overlays[FIRE_LAYER] = new /obj/abstract/Overlays/fire_layer obj_overlays[MUTANTRACE_LAYER] = new /obj/abstract/Overlays/mutantrace_layer + obj_overlays[TAIL_UNDERLIMBS_LAYER] = new /obj/abstract/Overlays/tail_underlimbs_layer + obj_overlays[LIMBS_LAYER] = new /obj/abstract/Overlays/limbs_layer obj_overlays[MUTATIONS_LAYER] = new /obj/abstract/Overlays/mutations_layer obj_overlays[DAMAGE_LAYER] = new /obj/abstract/Overlays/damage_layer obj_overlays[UNIFORM_LAYER] = new /obj/abstract/Overlays/uniform_layer @@ -181,13 +196,13 @@ obj_overlays[BACK_LAYER] = new /obj/abstract/Overlays/back_layer obj_overlays[HAIR_LAYER] = new /obj/abstract/Overlays/hair_layer obj_overlays[GLASSES_OVER_HAIR_LAYER] = new /obj/abstract/Overlays/glasses_over_hair_layer + obj_overlays[TAIL_LAYER] = new /obj/abstract/Overlays/tail_layer obj_overlays[FACEMASK_LAYER] = new /obj/abstract/Overlays/facemask_layer obj_overlays[HEAD_LAYER] = new /obj/abstract/Overlays/head_layer obj_overlays[HANDCUFF_LAYER] = new /obj/abstract/Overlays/handcuff_layer obj_overlays[MUTUALCUFF_LAYER] = new /obj/abstract/Overlays/mutualcuff_layer obj_overlays[LEGCUFF_LAYER] = new /obj/abstract/Overlays/legcuff_layer //obj_overlays[HAND_LAYER] = new /obj/abstract/Overlays/hand_layer - obj_overlays[TAIL_LAYER] = new /obj/abstract/Overlays/tail_layer obj_overlays[TARGETED_LAYER] = new /obj/abstract/Overlays/targeted_layer ..() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index bee1f1fc0ef..d4fd6c8eade 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -307,14 +307,20 @@ This function restores all organs. return -/mob/living/carbon/human/get_organ(var/zone) +/mob/living/carbon/human/get_organ(var/zone, cosmetic = FALSE) RETURN_TYPE(/datum/organ/external) if(!zone) zone = LIMB_CHEST if (zone in list( "eyes", "mouth" )) zone = LIMB_HEAD - return organs_by_name[zone] + var/list/organ_list = organs_by_name.Copy() + if(cosmetic) + organ_list |= cosmetic_organs_by_name + return organ_list[zone] +/mob/living/carbon/human/proc/get_cosmetic_organ(zone) + RETURN_TYPE(/datum/organ/external) + return cosmetic_organs_by_name[zone] //Picks a random usable organ from the organs passed to the arguments //You can feed organ references, or organ strings into this obj diff --git a/code/modules/mob/living/carbon/human/plasmaman/species.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm similarity index 100% rename from code/modules/mob/living/carbon/human/plasmaman/species.dm rename to code/modules/mob/living/carbon/human/species/plasmaman.dm diff --git a/code/modules/mob/living/carbon/human/species/vox.dm b/code/modules/mob/living/carbon/human/species/vox.dm new file mode 100644 index 00000000000..64c3142692a --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/vox.dm @@ -0,0 +1,160 @@ +/datum/species/vox + name = "Vox" + icobase = 'icons/mob/human_races/vox/r_vox.dmi' + deform = 'icons/mob/human_races/vox/r_def_vox.dmi' + known_languages = list(LANGUAGE_VOX) + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/rawchicken/vox + tacklePower = 40 + anatomy_flags = HAS_SWEAT_GLANDS | HAS_ICON_SKIN_TONE | HAS_TAIL + + survival_gear = /obj/item/weapon/storage/box/survival/vox + + primitive = /mob/living/carbon/monkey/vox + + cold_level_1 = 80 + cold_level_2 = 50 + cold_level_3 = 0 + + eyes = "vox_eyes_s" + breath_type = GAS_NITROGEN + + default_mutations = list(M_BEAK, M_TALONS) + flags = PLAYABLE | WHITELISTED + blood_color = VOX_BLOOD + flesh_color = "#808D11" + max_skin_tone = 6 + tail = "green" + tail_icon = 'icons/mob/human_races/vox/tails.dmi' + tail_type = "vox" + footprint_type = /obj/effect/decal/cleanable/blood/tracks/footprints/vox //Bird claws + + uniform_icons = 'icons/mob/species/vox/uniform.dmi' +// fat_uniform_icons = 'icons/mob/uniform_fat.dmi' + gloves_icons = 'icons/mob/species/vox/gloves.dmi' + glasses_icons = 'icons/mob/species/vox/eyes.dmi' +// ears_icons = 'icons/mob/ears.dmi' + shoes_icons = 'icons/mob/species/vox/shoes.dmi' + head_icons = 'icons/mob/species/vox/head.dmi' +// belt_icons = 'icons/mob/belt.dmi' + wear_suit_icons = 'icons/mob/species/vox/suit.dmi' + wear_mask_icons = 'icons/mob/species/vox/masks.dmi' + back_icons = 'icons/mob/species/vox/back.dmi' + + has_mutant_race = 0 + has_organ = list( + "heart" = /datum/organ/internal/heart/vox, + "lungs" = /datum/organ/internal/lungs/vox, + "liver" = /datum/organ/internal/liver, + "kidneys" = /datum/organ/internal/kidney, + "brain" = /datum/organ/internal/brain, + "appendix" = /datum/organ/internal/appendix, + "eyes" = /datum/organ/internal/eyes/vox + ) + + species_intro = "You are a Vox.
\ + You are somewhat more adept at handling the lower pressures of space and colder temperatures.
\ + You have talons with which you can slice others in a fist fight, and a beak which can be used to butcher corpses without the need for finer tools.
\ + However, Oxygen is incredibly toxic to you, in breathing it or consuming it. You can only breathe nitrogen." + +// -- Outfit datums -- +/datum/species/vox/final_equip(var/mob/living/carbon/human/H) + var/tank_slot = slot_s_store + var/tank_slot_name = "suit storage" + if(tank_slot) + H.equip_or_collect(new/obj/item/weapon/tank/nitrogen(H), tank_slot) + else + H.put_in_hands(new/obj/item/weapon/tank/nitrogen(H)) + to_chat(H, "You are now running on nitrogen internals from the [H.s_store] in your [tank_slot_name].") + var/obj/item/weapon/tank/nitrogen/N = H.get_item_by_slot(tank_slot) + if(!N) + N = H.get_item_by_slot(slot_back) + H.internal = N + if (H.internals) + H.internals.icon_state = "internal1" + +/datum/species/vox/makeName(var/gender,var/mob/living/carbon/human/H=null) + var/sounds = rand(3,8) + var/newname = "" + + for(var/i = 1 to sounds) + newname += pick(vox_name_syllables) + return capitalize(newname) + +/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) + if(myhuman != H) + return + updatespeciescolor(H) + H.update_icon() + +/datum/species/vox/updatespeciescolor(mob/living/carbon/human/vox) + var/datum/organ/external/tail/vox_tail = vox.get_cosmetic_organ(COSMETIC_ORGAN_TAIL) + switch(vox.my_appearance.s_tone) + if(VOXEMERALD) + icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxemrl.dmi' + if(VOXAZURE) + icobase = 'icons/mob/human_races/vox/r_voxazu.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxazu.dmi' + if(VOXLGREEN) + icobase = 'icons/mob/human_races/vox/r_voxlgrn.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxlgrn.dmi' + if(VOXGRAY) + icobase = 'icons/mob/human_races/vox/r_voxgry.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxgry.dmi' + if(VOXBROWN) + icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi' + deform = 'icons/mob/human_races/vox/r_def_voxbrn.dmi' + else + icobase = 'icons/mob/human_races/vox/r_vox.dmi' + deform = 'icons/mob/human_races/vox/r_def_vox.dmi' + if(vox_tail && (vox_tail.status & ORGAN_DESTROYED)) + return + vox_tail.update_tail(vox) + +/datum/species/skellington/skelevox // Science never goes too far, it's the public that's too conservative + name = "Skeletal Vox" + icobase = 'icons/mob/human_races/vox/r_voxboney.dmi' + deform = 'icons/mob/human_races/vox/r_voxboney.dmi' //Do bones deform noticeably? + known_languages = list(LANGUAGE_VOX, LANGUAGE_CLATTER) + + survival_gear = /obj/item/weapon/storage/box/survival/vox + + primitive = /mob/living/carbon/monkey/vox/skeletal + + warning_low_pressure = 50 + hazard_low_pressure = 0 + + cold_level_1 = 80 + cold_level_2 = 50 + cold_level_3 = 0 + + eyes = "vox_eyes_s" + + default_mutations = list(M_BEAK, M_TALONS) + + footprint_type = /obj/effect/decal/cleanable/blood/tracks/footprints/vox + + uniform_icons = 'icons/mob/species/vox/uniform.dmi' +// fat_uniform_icons = 'icons/mob/uniform_fat.dmi' + gloves_icons = 'icons/mob/species/vox/gloves.dmi' + glasses_icons = 'icons/mob/species/vox/eyes.dmi' +// ears_icons = 'icons/mob/ears.dmi' + shoes_icons = 'icons/mob/species/vox/shoes.dmi' + head_icons = 'icons/mob/species/vox/head.dmi' +// belt_icons = 'icons/mob/belt.dmi' + wear_suit_icons = 'icons/mob/species/vox/suit.dmi' + wear_mask_icons = 'icons/mob/species/vox/masks.dmi' +// back_icons = 'icons/mob/back.dmi' + + has_organ = list( + "brain" = /datum/organ/internal/brain, + "eyes" = /datum/organ/internal/eyes/vox + ) + +/datum/species/skellington/skelevox/makeName(var/gender,var/mob/living/carbon/human/H=null) + var/sounds = rand(3,8) + var/newname = "" + + for(var/i = 1 to sounds) + newname += pick(vox_name_syllables) + return capitalize(newname) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index c35bc3acf69..00fc82d0af5 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -194,7 +194,8 @@ var/global/list/damage_icon_parts = list() var/g = "m" if(gender == FEMALE) g = "f" - + if(species && species.anatomy_flags & HAS_ICON_SKIN_TONE) + species.updatespeciescolor(src) var/datum/organ/external/chest = get_organ(LIMB_CHEST) stand_icon = chest.get_icon(g,fat) if(!skeleton) @@ -269,7 +270,15 @@ var/global/list/damage_icon_parts = list() mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0) husk_over.Blend(mask, ICON_ADD) stand_icon.Blend(husk_over, ICON_OVERLAY) - + var/datum/organ/external/tail/tail = get_cosmetic_organ(COSMETIC_ORGAN_TAIL) + if(tail && (!(tail.status & ORGAN_DESTROYED) && tail.overlap_overlays)) + var/obj/abstract/Overlays/limbs_overlay = obj_overlays[LIMBS_LAYER] + var/mutable_appearance/stand_icon_image = mutable_appearance(stand_icon) + limbs_overlay.icon = stand_icon_image.icon + limbs_overlay.icon_state = stand_icon_image.icon_state + obj_to_plane_overlay(limbs_overlay, LIMBS_LAYER) + else + overlays -= obj_overlays[LIMBS_LAYER] if(has_head) //Eyes if(!skeleton) @@ -307,7 +316,7 @@ var/global/list/damage_icon_parts = list() stand_icon -= rgb(0,0,0,lowest_alpha) //tail - update_tail_showing(0) + update_tail_layer(FALSE) //HAIR OVERLAY @@ -523,6 +532,7 @@ var/global/list/damage_icon_parts = list() update_inv_mutual_handcuffed(0) update_inv_legcuffed(0) update_inv_pockets(0) + update_tail_layer() QueueUpdateDamageIcon(1) update_icons() //Hud Stuff @@ -1298,10 +1308,7 @@ var/global/list/damage_icon_parts = list() O.pixel_y = species.inventory_offsets["[slot_wear_suit]"]["pixel_y"] * PIXEL_MULTIPLIER obj_to_plane_overlay(O,SUIT_LAYER) //overlays_standing[SUIT_LAYER] = standing - update_tail_showing(0) - else - //overlays_standing[SUIT_LAYER] = null - update_tail_showing(0) + update_tail_layer() if(update_icons) update_icons() @@ -1547,22 +1554,34 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_inv_l_hand(var/update_icons=1) return update_inv_hand(GRASP_LEFT_HAND, update_icons) -/mob/living/carbon/human/proc/update_tail_showing(var/update_icons=1) - //overlays_standing[TAIL_LAYER] = null +/mob/living/carbon/human/proc/update_tail_layer(update_icons = TRUE) + overlays -= obj_overlays[TAIL_UNDERLIMBS_LAYER] overlays -= obj_overlays[TAIL_LAYER] - if(species && species.tail && species.anatomy_flags & HAS_TAIL) - if(!wear_suit || !is_slot_hidden(wear_suit.body_parts_covered, HIDEJUMPSUIT, 0, wear_suit.body_parts_visible_override)) - var/obj/abstract/Overlays/O = obj_overlays[TAIL_LAYER] - O.icon = 'icons/effects/species.dmi' - O.icon_state = "[species.tail]_s" - obj_to_plane_overlay(O,TAIL_LAYER) - //if(!old_tail_state) //only update if we didnt show our tail already - - //overlays_standing[TAIL_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") -// to_chat(src, "update: tail is different") - //else - //overlays_standing[TAIL_LAYER] = null - + var/datum/organ/external/tail/tail_organ = get_cosmetic_organ(COSMETIC_ORGAN_TAIL) + if(!tail_organ || (tail_organ.status & ORGAN_DESTROYED)) + return + if(wear_suit || check_hidden_body_flags(HIDETAIL)) + return + var/tail_file = tail_organ.tail_icon_file + var/tail_icon_state = tail_organ.icon_name + if(!tail_file || !tail_icon_state) + return + var/mutable_appearance/tail_image = mutable_appearance(tail_file, tail_icon_state, layer = -TAIL_LAYER) + if(species.anatomy_flags & MULTICOLOR) + tail_image.color = COLOR_MATRIX_ADD(rgb(multicolor_skin_r, multicolor_skin_g, multicolor_skin_b)) + if(tail_organ.overlap_overlays) // Tail is overlapped by limbs, so we need special tail icon generation + // Gives the underlimbs layer SEW directions since it's overlayed by limbs and just about everything else anyway. + var/mutable_appearance/tail_underlimbs = mutable_appearance(tail_file, "[tail_icon_state]_BEHIND", -TAIL_UNDERLIMBS_LAYER) + var/obj/abstract/Overlays/underlimbs_overlay = obj_overlays[TAIL_UNDERLIMBS_LAYER] + underlimbs_overlay.icon = tail_underlimbs.icon + underlimbs_overlay.icon_state = tail_underlimbs.icon_state + obj_to_plane_overlay(underlimbs_overlay, TAIL_UNDERLIMBS_LAYER) + // North direction sprite before passing that to the tail layer that overlays uniforms and such. + tail_image.icon_state = "[tail_icon_state]_FRONT" + var/obj/abstract/Overlays/tail_overlay = obj_overlays[TAIL_LAYER] + tail_overlay.icon = tail_image.icon + tail_overlay.icon_state = tail_image.icon_state + obj_to_plane_overlay(tail_overlay, TAIL_LAYER) if(update_icons) update_icons() diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm index fac52aed432..4bafdb1aa19 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/species.dm @@ -42,7 +42,10 @@ var/global/list/playable_species = list("Human") var/eyes = "eyes_s" // Icon for eyes. var/primitive // Lesser form, if any (ie. monkey for humans) - var/tail // Name of tail image in species effects icon file. + var/tail // Name of tail icon state + var/tail_icon = 'icons/mob/tails.dmi' + var/tail_type + var/tail_overlapping = TRUE var/list/known_languages = list(LANGUAGE_GALACTIC_COMMON) // Languages that this species innately knows. var/default_language = LANGUAGE_GALACTIC_COMMON // Default language is used when 'say' is used without modifiers. var/attack_verb = "punches" // Empty hand hurt intent verb. @@ -204,9 +207,15 @@ var/global/list/playable_species = list("Human") for(var/datum/organ/I in H.internal_organs) qdel(I) H.internal_organs.len=0 + if(H.cosmetic_organs) + for(var/organ in H.cosmetic_organs) + qdel(organ) + H.cosmetic_organs.len=0 //The rest SHOULD only refer to organs that were already deleted by the above loops, so we can just clear the lists. if(H.organs_by_name) H.organs_by_name.len=0 + if(H.cosmetic_organs_by_name) + H.cosmetic_organs_by_name.len = 0 if(H.internal_organs_by_name) H.internal_organs_by_name.len=0 if(H.grasp_organs) @@ -219,6 +228,7 @@ var/global/list/playable_species = list("Human") //This is a basic humanoid limb setup. H.organs = list() + H.cosmetic_organs = list() H.organs_by_name[LIMB_CHEST] = new/datum/organ/external/chest() H.organs_by_name[LIMB_GROIN] = new/datum/organ/external/groin(H.organs_by_name[LIMB_CHEST]) H.organs_by_name[LIMB_HEAD] = new/datum/organ/external/head(H.organs_by_name[LIMB_CHEST]) @@ -231,6 +241,8 @@ var/global/list/playable_species = list("Human") H.organs_by_name[LIMB_LEFT_FOOT] = new/datum/organ/external/l_foot(H.organs_by_name[LIMB_LEFT_LEG]) H.organs_by_name[LIMB_RIGHT_FOOT] = new/datum/organ/external/r_foot(H.organs_by_name[LIMB_RIGHT_LEG]) + H.cosmetic_organs_by_name[COSMETIC_ORGAN_TAIL] = new/datum/organ/external/tail(H.organs_by_name[LIMB_GROIN], src) + H.internal_organs = list() for(var/organ in has_organ) var/organ_type = has_organ[organ] @@ -245,9 +257,13 @@ var/global/list/playable_species = list("Human") H.organs += OE if(OE.grasp_id) H.grasp_organs += OE - - for(var/datum/organ/external/O in H.organs) - O.owner = H + for(var/organ in H.cosmetic_organs_by_name) + var/datum/organ/external/cosmetic_organ = H.cosmetic_organs_by_name[organ] + H.cosmetic_organs += cosmetic_organ + for(var/datum/organ/external/external_organ in H.organs) + external_organ.owner = H + for(var/datum/organ/external/cosmetic_organ as anything in H.cosmetic_organs) + cosmetic_organ.owner = H /datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. return @@ -385,7 +401,8 @@ var/global/list/playable_species = list("Human") icobase = 'icons/mob/human_races/r_lizard.dmi' deform = 'icons/mob/human_races/r_def_lizard.dmi' known_languages = list(LANGUAGE_UNATHI) - tail = "sogtail" + tail = "unathi" + tail_type = "unathi" attack_verb = "scratches" punch_damage = 2 primitive = /mob/living/carbon/monkey/unathi @@ -467,61 +484,13 @@ var/global/list/playable_species = list("Human") H.drop_all() qdel(src) - -/datum/species/skellington/skelevox // Science never goes too far, it's the public that's too conservative - name = "Skeletal Vox" - icobase = 'icons/mob/human_races/vox/r_voxboney.dmi' - deform = 'icons/mob/human_races/vox/r_voxboney.dmi' //Do bones deform noticeably? - known_languages = list(LANGUAGE_VOX, LANGUAGE_CLATTER) - - survival_gear = /obj/item/weapon/storage/box/survival/vox - - primitive = /mob/living/carbon/monkey/vox/skeletal - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - eyes = "vox_eyes_s" - - default_mutations = list(M_BEAK, M_TALONS) - - footprint_type = /obj/effect/decal/cleanable/blood/tracks/footprints/vox - - uniform_icons = 'icons/mob/species/vox/uniform.dmi' -// fat_uniform_icons = 'icons/mob/uniform_fat.dmi' - gloves_icons = 'icons/mob/species/vox/gloves.dmi' - glasses_icons = 'icons/mob/species/vox/eyes.dmi' -// ears_icons = 'icons/mob/ears.dmi' - shoes_icons = 'icons/mob/species/vox/shoes.dmi' - head_icons = 'icons/mob/species/vox/head.dmi' -// belt_icons = 'icons/mob/belt.dmi' - wear_suit_icons = 'icons/mob/species/vox/suit.dmi' - wear_mask_icons = 'icons/mob/species/vox/masks.dmi' -// back_icons = 'icons/mob/back.dmi' - - has_organ = list( - "brain" = /datum/organ/internal/brain, - "eyes" = /datum/organ/internal/eyes/vox - ) - -/datum/species/skellington/skelevox/makeName(var/gender,var/mob/living/carbon/human/H=null) - var/sounds = rand(3,8) - var/newname = "" - - for(var/i = 1 to sounds) - newname += pick(vox_name_syllables) - return capitalize(newname) - /datum/species/tajaran name = "Tajaran" icobase = 'icons/mob/human_races/r_tajaran.dmi' deform = 'icons/mob/human_races/r_def_tajaran.dmi' known_languages = list(LANGUAGE_CATBEAST, LANGUAGE_MOUSE) - tail = "tajtail" + tail = "tajaran_brown" + tail_type = "tajaran" attack_verb = "scratches" punch_damage = 2 //Claws add 3 damage without gloves, so the total is 5 @@ -536,7 +505,7 @@ var/global/list/playable_species = list("Human") primitive = /mob/living/carbon/monkey/tajara flags = WHITELISTED - anatomy_flags = HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SWEAT_GLANDS + anatomy_flags = HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SWEAT_GLANDS | HAS_ICON_SKIN_TONE default_mutations=list(M_CLAWS) @@ -568,18 +537,20 @@ var/global/list/playable_species = list("Human") updatespeciescolor(H) H.update_icon() -/datum/species/tajaran/updatespeciescolor(var/mob/living/carbon/human/H) - switch(H.my_appearance.s_tone) +/datum/species/tajaran/updatespeciescolor(mob/living/carbon/human/tajaran) + var/datum/organ/external/tail/tajaran_tail = tajaran.get_cosmetic_organ(COSMETIC_ORGAN_TAIL) + switch(tajaran.my_appearance.s_tone) if(CATBEASTBLACK) icobase = 'icons/mob/human_races/r_tajaranblack.dmi' deform = 'icons/mob/human_races/r_def_tajaranblack.dmi' - tail = "tajtailb" - H.my_appearance.h_style = "Black Tajaran Ears" + tajaran.my_appearance.h_style = "Black Tajaran Ears" else icobase = 'icons/mob/human_races/r_tajaran.dmi' deform = 'icons/mob/human_races/r_def_tajaran.dmi' - tail = "tajtail" - H.my_appearance.h_style = "Tajaran Ears" + tajaran.my_appearance.h_style = "Tajaran Ears" + if(tajaran_tail && (tajaran_tail.status & ORGAN_DESTROYED)) + return + tajaran_tail.update_tail(tajaran) /datum/species/tajaran/handle_speech(var/datum/speech/speech, mob/living/carbon/human/H) if (prob(15)) @@ -610,7 +581,7 @@ var/global/list/playable_species = list("Human") primitive = /mob/living/carbon/monkey/grey flags = PLAYABLE | WHITELISTED - anatomy_flags = HAS_LIPS | HAS_SWEAT_GLANDS | ACID4WATER + anatomy_flags = HAS_LIPS | HAS_SWEAT_GLANDS | ACID4WATER | HAS_ICON_SKIN_TONE spells = list(/spell/targeted/telepathy) @@ -736,114 +707,6 @@ var/global/list/playable_species = list("Human") head_icons = 'icons/mob/species/skrell/head.dmi' wear_suit_icons = 'icons/mob/species/skrell/suit.dmi' -/datum/species/vox - name = "Vox" - icobase = 'icons/mob/human_races/vox/r_vox.dmi' - deform = 'icons/mob/human_races/vox/r_def_vox.dmi' - known_languages = list(LANGUAGE_VOX) - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/rawchicken/vox - tacklePower = 40 - anatomy_flags = HAS_SWEAT_GLANDS - - survival_gear = /obj/item/weapon/storage/box/survival/vox - - primitive = /mob/living/carbon/monkey/vox - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - eyes = "vox_eyes_s" - breath_type = GAS_NITROGEN - - default_mutations = list(M_BEAK, M_TALONS) - flags = PLAYABLE | WHITELISTED - - blood_color = VOX_BLOOD - flesh_color = "#808D11" - max_skin_tone = 6 - - footprint_type = /obj/effect/decal/cleanable/blood/tracks/footprints/vox //Bird claws - - uniform_icons = 'icons/mob/species/vox/uniform.dmi' -// fat_uniform_icons = 'icons/mob/uniform_fat.dmi' - gloves_icons = 'icons/mob/species/vox/gloves.dmi' - glasses_icons = 'icons/mob/species/vox/eyes.dmi' -// ears_icons = 'icons/mob/ears.dmi' - shoes_icons = 'icons/mob/species/vox/shoes.dmi' - head_icons = 'icons/mob/species/vox/head.dmi' -// belt_icons = 'icons/mob/belt.dmi' - wear_suit_icons = 'icons/mob/species/vox/suit.dmi' - wear_mask_icons = 'icons/mob/species/vox/masks.dmi' - back_icons = 'icons/mob/species/vox/back.dmi' - - has_mutant_race = 0 - has_organ = list( - "heart" = /datum/organ/internal/heart/vox, - "lungs" = /datum/organ/internal/lungs/vox, - "liver" = /datum/organ/internal/liver, - "kidneys" = /datum/organ/internal/kidney, - "brain" = /datum/organ/internal/brain, - "appendix" = /datum/organ/internal/appendix, - "eyes" = /datum/organ/internal/eyes/vox - ) - - species_intro = "You are a Vox.
\ - You are somewhat more adept at handling the lower pressures of space and colder temperatures.
\ - You have talons with which you can slice others in a fist fight, and a beak which can be used to butcher corpses without the need for finer tools.
\ - However, Oxygen is incredibly toxic to you, in breathing it or consuming it. You can only breathe nitrogen." - -// -- Outfit datums -- -/datum/species/vox/final_equip(var/mob/living/carbon/human/H) - var/tank_slot = slot_s_store - var/tank_slot_name = "suit storage" - if(tank_slot) - H.equip_or_collect(new/obj/item/weapon/tank/nitrogen(H), tank_slot) - else - H.put_in_hands(new/obj/item/weapon/tank/nitrogen(H)) - to_chat(H, "You are now running on nitrogen internals from the [H.s_store] in your [tank_slot_name].") - var/obj/item/weapon/tank/nitrogen/N = H.get_item_by_slot(tank_slot) - if(!N) - N = H.get_item_by_slot(slot_back) - H.internal = N - if (H.internals) - H.internals.icon_state = "internal1" - -/datum/species/vox/makeName(var/gender,var/mob/living/carbon/human/H=null) - var/sounds = rand(3,8) - var/newname = "" - - for(var/i = 1 to sounds) - newname += pick(vox_name_syllables) - return capitalize(newname) - -/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) - if(myhuman != H) - return - updatespeciescolor(H) - H.update_icon() - -/datum/species/vox/updatespeciescolor(var/mob/living/carbon/human/H) - switch(H.my_appearance.s_tone) - if(6) - icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi' - deform = 'icons/mob/human_races/vox/r_def_voxemrl.dmi' - if(5) - icobase = 'icons/mob/human_races/vox/r_voxazu.dmi' - deform = 'icons/mob/human_races/vox/r_def_voxazu.dmi' - if(4) - icobase = 'icons/mob/human_races/vox/r_voxlgrn.dmi' - deform = 'icons/mob/human_races/vox/r_def_voxlgrn.dmi' - if(3) - icobase = 'icons/mob/human_races/vox/r_voxgry.dmi' - deform = 'icons/mob/human_races/vox/r_def_voxgry.dmi' - if(2) - icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi' - deform = 'icons/mob/human_races/vox/r_def_voxbrn.dmi' - else - icobase = 'icons/mob/human_races/vox/r_vox.dmi' - deform = 'icons/mob/human_races/vox/r_def_vox.dmi' - /datum/species/diona name = "Diona" icobase = 'icons/mob/human_races/r_plant.dmi' @@ -1421,4 +1284,4 @@ var/list/has_died_as_golem = list() head_organ.droplimb(1,1) H.drop_all() - qdel(src) \ No newline at end of file + qdel(src) diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 0d378974686..37a9c9cd9f5 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -352,6 +352,9 @@ var/list/animals_with_wings = list( else alert("Unable to use this emote, must be either hearable or visible.") return + var/display_runechat = input("Display Runechat?") as null|anything in list("Yes", "No") + if(display_runechat == "No") + emote_type |= EMOTE_NO_RUNECHAT message = custom_emote else message = params diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index c672b2c41f0..c584fd8102d 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -174,25 +174,25 @@ if(current_species) if(current_species.name == "Vox") switch(s_tone) - if(6) + if(VOXEMERALD) icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi' - if(5) + if(VOXAZURE) icobase = 'icons/mob/human_races/vox/r_voxazu.dmi' - if(4) + if(VOXLGREEN) icobase = 'icons/mob/human_races/vox/r_voxlgrn.dmi' - if(3) + if(VOXGRAY) icobase = 'icons/mob/human_races/vox/r_voxgry.dmi' - if(2) + if(VOXBROWN) icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi' else icobase = 'icons/mob/human_races/vox/r_vox.dmi' else if(current_species.name == "Grey") switch(s_tone) - if(4) + if(GREYBLUE) icobase = 'icons/mob/human_races/grey/r_greyblue.dmi' - if(3) + if(GREYGREEN) icobase = 'icons/mob/human_races/grey/r_greygreen.dmi' - if(2) + if(GREYLIGHT) icobase = 'icons/mob/human_races/grey/r_greylight.dmi' else icobase = 'icons/mob/human_races/grey/r_grey.dmi' @@ -230,7 +230,31 @@ var/icon/temp = new /icon(o_icobase, "[name]") preview_icon.Blend(temp, ICON_OVERLAY) - + //Tail + if(current_species && (current_species.anatomy_flags & HAS_TAIL)) + var/tail_icon_state = current_species.tail + if(current_species.name == "Vox") + switch(s_tone) + if(VOXEMERALD) + tail_icon_state = "emerald" + if(VOXAZURE) + tail_icon_state = "azure" + if(VOXLGREEN) + tail_icon_state = "lightgreen" + if(VOXGRAY) + tail_icon_state = "grey" + if(VOXBROWN) + tail_icon_state = "brown" + else + tail_icon_state = "green" + if(current_species.name == "Tajaran") + switch(s_tone) + if(CATBEASTBLACK) + tail_icon_state = "tajaran_black" + else + tail_icon_state = "tajaran_brown" + var/icon/temp_tail_icon = icon(current_species.tail_icon, "[tail_icon_state]_BEHIND") + preview_icon.Blend(temp_tail_icon, ICON_UNDERLAY) // Skin tone if(current_species && (current_species.anatomy_flags & HAS_SKIN_TONE)) if (s_tone >= 0) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index e16afd28040..e64081c17eb 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -78,7 +78,9 @@ W.time_inflicted = world.time /mob/living/carbon/human/var/list/organs = list() +/mob/living/carbon/human/var/list/cosmetic_organs = list() /mob/living/carbon/human/var/list/datum/organ/external/organs_by_name = list() //Map organ names to organs +/mob/living/carbon/human/var/list/datum/organ/external/cosmetic_organs_by_name = list() /mob/living/carbon/human/var/list/datum/organ/internal/internal_organs_by_name = list() //So internal organs have less ickiness too /mob/living/carbon/human/var/list/grasp_organs = list() diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 7ff4b2fc0db..055e3df562b 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -50,7 +50,7 @@ var/wound_update_accuracy = 1 var/has_fat = 0 //Has a _fat variant - + var/cosmetic_only = FALSE var/grasp_id = 0 //Does this organ affect other grasping organs? var/can_grasp = 0 //Can this organ actually grasp something? @@ -154,6 +154,8 @@ droplimb(1, spawn_limb = 0, display_message = FALSE) /datum/organ/external/proc/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list()) + if(cosmetic_only) + return if(owner?.status_flags & GODMODE) return 0 //godmode if((brute <= 0) && (burn <= 0)) @@ -277,6 +279,8 @@ return result /datum/organ/external/proc/heal_damage(brute, burn, internal = 0, robo_repair = 0) + if(cosmetic_only) + return if(is_robotic() && !robo_repair) //This item can't fix robotic limbs return @@ -330,6 +334,8 @@ owner.updatehealth() /datum/organ/external/proc/createwound(var/type = CUT, var/damage) + if(cosmetic_only) + return if(!damage || damage < 0) //We weren't passed a damage value, or it's negative for some reason return @@ -409,7 +415,6 @@ return 0 /datum/organ/external/process() - //Process wounds, doing healing etc. Only do this every few ticks to save processing power if(owner.life_tick % wound_update_accuracy == 0) update_wounds() @@ -448,7 +453,6 @@ //Cancer growth for external organs is simple, it grows, hurts, damages, and suddenly grows out of control //Limb cancer is relatively benign until it grows large, then it cripples you and metastases /datum/organ/external/handle_cancer() - if(..()) return 1 @@ -500,6 +504,8 @@ Note that amputating the affected organ does in fact remove the infection from t */ /datum/organ/external/proc/update_germs() + if(cosmetic_only) + return if(!is_existing() || !is_organic()) //Needs to be organic and existing germ_level = 0 return @@ -590,7 +596,8 @@ Note that amputating the affected organ does in fact remove the infection from t //Updating wounds. Handles wound natural healing, internal bleedings and infections /datum/organ/external/proc/update_wounds() - + if(cosmetic_only) + return if(!is_organic()) //Non-organic limbs don't heal or get worse return @@ -748,7 +755,7 @@ Note that amputating the affected organ does in fact remove the infection from t if(body_part == (UPPER_TORSO || LOWER_TORSO)) //We can't lose either, those cannot be amputated and will cause extremely serious problems return - var/datum/species/species = src.species || owner.species + var/datum/species/species = src.species || owner?.species var/obj/item/organ/external/organ //Dropped limb object if(override) @@ -837,7 +844,8 @@ Note that amputating the affected organ does in fact remove the infection from t //Throw organs around var/randomdir = pick(cardinal) step(organ, randomdir) - + if(!owner) + return organ owner.update_body(1) owner.handle_organs(1) @@ -873,7 +881,7 @@ Note that amputating the affected organ does in fact remove the infection from t O.removed(owner,owner) O.loc = headloc QDEL_NULL(organ) - + organ?.update_icon() return organ /datum/organ/external/proc/get_organ_item() @@ -941,6 +949,8 @@ Note that amputating the affected organ does in fact remove the infection from t return rval /datum/organ/external/proc/clamp_wounds() //Inconsistent with the other names but clamp is a reserved word now + if(cosmetic_only) + return var/rval = 0 src.status &= ~ORGAN_BLEEDING for(var/datum/wound/W in wounds) @@ -958,6 +968,8 @@ Note that amputating the affected organ does in fact remove the infection from t return rval /datum/organ/external/proc/fracture() + if(cosmetic_only) + return if(owner?.status_flags & GODMODE) return 0 //godmode var/datum/species/species = src.species || owner.species @@ -1053,7 +1065,7 @@ Note that amputating the affected organ does in fact remove the infection from t src.status = organ.status src.brute_dam = organ.brute_dam src.burn_dam = organ.burn_dam - + on_attach(organ) owner.butchering_drops += organ.butchering_drops //Transfer any internal_organs from the organ item to the body @@ -1086,7 +1098,7 @@ Note that amputating the affected organ does in fact remove the infection from t else if(istype(I, /obj/item/robot_parts)) //Robotic limb var/obj/item/robot_parts/R = I - + R.on_attach(src) src.robotize() src.sabotaged = R.sabotaged @@ -1103,6 +1115,9 @@ Note that amputating the affected organ does in fact remove the infection from t owner.updatehealth() owner.UpdateDamageIcon() +/datum/organ/external/proc/on_attach() + return + /datum/organ/external/proc/mutate() src.status |= ORGAN_MUTATED owner.update_body() @@ -1247,6 +1262,85 @@ Note that amputating the affected organ does in fact remove the infection from t body_part = LOWER_TORSO vital = 1 +/datum/organ/external/tail + name = COSMETIC_ORGAN_TAIL + display_name = "tail" + icon_name = "tail" + max_damage = 75 + min_broken_damage = 30 + body_part = TAIL + cosmetic_only = TRUE + var/tail_icon_file = 'icons/mob/tails.dmi' + var/tail_type + var/overlap_overlays = TRUE + +/datum/organ/external/tail/New(datum/organ/external/parent, datum/species/passed_species) + if(passed_species && (!(passed_species.anatomy_flags & HAS_TAIL))) + droplimb(TRUE, spawn_limb = FALSE) + return + create_tail_info(passed_species) + return ..() + +/datum/organ/external/tail/proc/create_tail_info(datum/species/passed_species, obj/item/organ/external/tail/tail_item) + icon_name = passed_species?.tail || tail_item?.tail_state_name + tail_icon_file = passed_species?.tail_icon || tail_item?.tail_icon_file + tail_type = passed_species?.tail_type || tail_item?.tail_type + overlap_overlays = passed_species?.tail_overlapping || tail_item?.tail_overlapping + +/datum/organ/external/tail/generate_dropped_organ(current_organ) + if(!current_organ) + if(is_robotic()) + current_organ = new /obj/item/robot_parts/tail(owner.loc, tail_type) + else + current_organ = new /obj/item/organ/external/tail(owner.loc, owner, src) + return current_organ + +/datum/organ/external/tail/on_attach(obj/item/organ/external/tail/tail_item) + create_tail_info(tail_item = tail_item) + +/datum/organ/external/tail/proc/update_tail(mob/living/carbon/human/tail_owner, skin_tone, random = FALSE) + if(!skin_tone) + skin_tone = tail_owner?.my_appearance.s_tone || owner?.my_appearance.s_tone + if(is_robotic(src)) + icon_name = "[tail_type]_robotic" + else + switch(tail_type) + if("vox") + if(random) + skin_tone = rand(1, 6) + switch(skin_tone) + if(VOXEMERALD) + icon_name = "emerald" + if(VOXAZURE) + icon_name = "azure" + if(VOXLGREEN) + icon_name = "lightgreen" + if(VOXGRAY) + icon_name = "grey" + if(VOXBROWN) + icon_name = "brown" + else + icon_name = "green" + if("tajaran") + if(random) + skin_tone = rand(1, 2) + switch(skin_tone) + if(CATBEASTBLACK) + icon_name = "tajaran_black" + else + icon_name = "tajaran_brown" + var/mob/living/carbon/human/tail_haver = tail_owner || owner + tail_haver?.update_tail_layer() + +/datum/organ/external/tail/robotize() + tail_icon_file = initial(tail_icon_file) + ..() + if(owner) + update_tail(owner) + +/datum/organ/external/tail/peggify() + return + //=====Legs====== /datum/organ/external/l_leg @@ -1607,6 +1701,7 @@ Note that amputating the affected organ does in fact remove the infection from t ..(loc) if(!istype(H)) return + post_creation(source) if(H.dna) owner_dna = H.dna.Clone() if(!blood_DNA) @@ -1641,6 +1736,9 @@ Note that amputating the affected organ does in fact remove the infection from t //The reason why B isn't just transferred from H.butchering_drops to src.butchering_drops is: //on examine(), each butchering drop's "desc_modifier()" is added to the description. This adds stuff like "he HAS NO TEETH AT ALL!!!" to the resulting description. +/obj/item/organ/external/proc/post_creation(datum/organ/external/organ_datum) + return + /obj/item/organ/external/examine(mob/user) ..() @@ -1675,8 +1773,6 @@ Note that amputating the affected organ does in fact remove the infection from t to_chat(user, "[butchery]") /obj/item/organ/external/update_icon(mob/living/carbon/human/H) - ..() - if(!H && !species) return @@ -1804,6 +1900,34 @@ Note that amputating the affected organ does in fact remove the infection from t if(B) B.infest_limb(src) +/obj/item/organ/external/tail + name = "tail" + part = COSMETIC_ORGAN_TAIL + w_class = W_CLASS_SMALL + var/tail_icon_file + var/tail_type + var/tail_icon_key + var/tail_state_name + var/tail_overlapping = TRUE + var/static/list/tail_organ_icons = list() + +/obj/item/organ/external/tail/post_creation(datum/organ/external/tail/organ_datum) + tail_icon_file = organ_datum.tail_icon_file + tail_state_name = organ_datum.icon_name + tail_type = organ_datum.tail_type + tail_overlapping = organ_datum.overlap_overlays + update_icon() + +/obj/item/organ/external/tail/update_icon() + tail_icon_key = "[tail_state_name]_[tail_type]" + var/returned_tail_icon = tail_organ_icons[tail_icon_key] + if(!returned_tail_icon) + var/icon/new_tail_icon = icon(tail_icon_file, "[tail_state_name]_BEHIND", EAST) + new_tail_icon.Shift(EAST, 6) + new_tail_icon.Shift(NORTH, 3) + returned_tail_icon = tail_organ_icons[tail_icon_key] = new_tail_icon + icon = returned_tail_icon + /obj/item/organ/external/head dir = NORTH name = LIMB_HEAD @@ -2030,6 +2154,8 @@ Note that amputating the affected organ does in fact remove the infection from t return FALSE /datum/organ/external/send_to_past(var/duration) + if(cosmetic_only) + return ..() var/static/list/resettable_vars = list( "damage_state", diff --git a/code/modules/overlays/mobs.dm b/code/modules/overlays/mobs.dm index 700dd55adeb..02db8a62942 100644 --- a/code/modules/overlays/mobs.dm +++ b/code/modules/overlays/mobs.dm @@ -9,6 +9,12 @@ /obj/abstract/Overlays/mutantrace_layer layer = FLOAT_LAYER - (TOTAL_LAYERS - MUTANTRACE_LAYER) +/obj/abstract/Overlays/tail_underlimbs_layer + layer = FLOAT_LAYER - (TOTAL_LAYERS - TAIL_UNDERLIMBS_LAYER) + +/obj/abstract/Overlays/limbs_layer + layer = FLOAT_LAYER - (TOTAL_LAYERS - LIMBS_LAYER) + /obj/abstract/Overlays/mutations_layer layer = FLOAT_LAYER - (TOTAL_LAYERS - MUTATIONS_LAYER) @@ -45,6 +51,9 @@ /obj/abstract/Overlays/glasses_over_hair_layer layer = FLOAT_LAYER - (TOTAL_LAYERS - GLASSES_OVER_HAIR_LAYER) +/obj/abstract/Overlays/tail_layer + layer = FLOAT_LAYER - (TOTAL_LAYERS - TAIL_LAYER) + /obj/abstract/Overlays/facemask_layer layer = FLOAT_LAYER - (TOTAL_LAYERS - FACEMASK_LAYER) @@ -69,9 +78,6 @@ /obj/abstract/Overlays/hand_layer layer = FLOAT_LAYER - (TOTAL_LAYERS - HAND_LAYER) -/obj/abstract/Overlays/tail_layer - layer = FLOAT_LAYER - (TOTAL_LAYERS - TAIL_LAYER) - /obj/abstract/Overlays/targeted_layer layer = FLOAT_LAYER - (TOTAL_LAYERS - TARGETED_LAYER) @@ -84,6 +90,8 @@ /* var/obj/abstract/Overlays/fire_layer/fire_layer = new var/obj/abstract/Overlays/mutantrace_layer/mutantrace_layer = new + var/obj/abstract/Overlays/tail_underlimbs_layer/tail_underlimbs_layer = new + var/obj/abstract/Overlays/limbs_layer/limbs_layer = new var/obj/abstract/Overlays/mutations_layer/mutations_layer = new var/obj/abstract/Overlays/damage_layer/damage_layer = new var/obj/abstract/Overlays/uniform_layer/uniform_layer = new @@ -98,12 +106,12 @@ var/obj/abstract/Overlays/back_layer/back_layer = new var/obj/abstract/Overlays/hair_layer/hair_layer = new var/obj/abstract/Overlays/glasses_over_hair_layer/glasses_over_hair_layer = new + var/obj/abstract/Overlays/tail_layer/tail_layer = new var/obj/abstract/Overlays/facemask_layer/facemask_layer = new var/obj/abstract/Overlays/head_layer/head_layer = new var/obj/abstract/Overlays/handcuff_layer/handcuff_layer = new var/obj/abstract/Overlays/legcuff_layer/legcuff_layer = new var/obj/abstract/Overlays/l_hand_layer/l_hand_layer = new var/obj/abstract/Overlays/r_hand_layer/r_hand_layer = new - var/obj/abstract/Overlays/tail_layer/tail_layer = new var/obj/abstract/Overlays/targeted_layer/targeted_layer = new */ diff --git a/code/modules/research/designs/robot.dm b/code/modules/research/designs/robot.dm index 03b7616d649..3228574da5f 100644 --- a/code/modules/research/designs/robot.dm +++ b/code/modules/research/designs/robot.dm @@ -58,6 +58,16 @@ category = "Robot" materials = list(MAT_IRON=15000) +/datum/design/robot/tail + name = "Cyborg Component (Robot tail)" + desc = "Used to build a Robot tail." + id = "robot_tail" + req_tech = list(Tc_ENGINEERING = 1) + build_type = MECHFAB + build_path = /obj/item/robot_parts/tail + category = "Robot" + materials = list(MAT_IRON=15000) + /datum/design/robot/head name = "Cyborg Component (Robot head)" desc = "Used to build a Robot head." @@ -198,4 +208,4 @@ build_type = MECHFAB build_path = /obj/item/robot_parts/robot_component/armour/reinforced category = "Robot_Part" - materials = list(MAT_IRON=5000, MAT_DIAMOND=5000) \ No newline at end of file + materials = list(MAT_IRON=5000, MAT_DIAMOND=5000) diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index fab84860e83..2daff4596d3 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -5,6 +5,7 @@ /datum/surgery_step/generic/ can_infect = 1 + supports_cosmetic_organs = TRUE var/painful=1 /datum/surgery_step/generic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -14,7 +15,7 @@ return 0 if (!hasorgans(target)) return 0 - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if (affected == null) return 0 if (affected.status & ORGAN_DESTROYED) @@ -40,7 +41,6 @@ ) priority = 0.1 //so the tool checks for this step before /generic/cut_open - duration = 4 SECONDS /datum/surgery_step/generic/cut_with_laser/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -48,29 +48,30 @@ if(target.species && (target.species.anatomy_flags & NO_SKIN)) to_chat(user, "[target] has no skin!") return 0 - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) return affected.open == 0 && target_zone != "mouth" /datum/surgery_step/generic/cut_with_laser/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] starts the bloodless incision on [target]'s [affected.display_name] with \the [tool].", \ "You start the bloodless incision on [target]'s [affected.display_name] with \the [tool].") target.custom_pain("You feel a horrible, searing pain in your [affected.display_name]!",1, scream=TRUE) ..() /datum/surgery_step/generic/cut_with_laser/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] has made a bloodless incision on [target]'s [affected.display_name] with \the [tool].", \ "You have made a bloodless incision on [target]'s [affected.display_name] with \the [tool].",) //Could be cleaner ... affected.open = 1 - affected.status |= ORGAN_BLEEDING + if(!affected.cosmetic_only) + affected.status |= ORGAN_BLEEDING affected.createwound(CUT, 1) affected.clamp_wounds() //spread_germs_to_organ(affected, user) //a laser scalpel shouldn't spread germs. /datum/surgery_step/generic/cut_with_laser/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user]'s hand slips as the blade sputters, searing a long gash in [target]'s [affected.display_name] with \the [tool]!", \ "Your hand slips as the blade sputters, searing a long gash in [target]'s [affected.display_name] with \the [tool]!") affected.createwound(CUT, 7.5) @@ -88,7 +89,6 @@ ) priority = 0.1 //so the tool checks for this step before /generic/cut_open - duration = 8 SECONDS /datum/surgery_step/generic/incision_manager/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -97,11 +97,11 @@ to_chat(user, "[target] has no skin!") return 0 - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) return affected.open == 0 && target_zone != "mouth" /datum/surgery_step/generic/incision_manager/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] starts to construct a prepared incision on and within [target]'s [affected.display_name] with \the [tool].", \ "You start to construct a prepared incision on and within [target]'s [affected.display_name] with \the [tool].") target.custom_pain("You feel a horrible, searing pain in your [affected.display_name] as it is pushed apart!",1, scream=TRUE) @@ -111,18 +111,19 @@ ..() /datum/surgery_step/generic/incision_manager/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] has constructed a prepared incision on and within [target]'s [affected.display_name] with \the [tool].", \ "You have constructed a prepared incision on and within [target]'s [affected.display_name] with \the [tool].",) affected.open = 1 - affected.status |= ORGAN_BLEEDING + if(!affected.cosmetic_only) + affected.status |= ORGAN_BLEEDING affected.createwound(CUT, 1) affected.clamp_wounds() affected.open = 2 tool.icon_state = "[initial(tool.icon_state)]_off" /datum/surgery_step/generic/incision_manager/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user]'s hand jolts as the system sparks, ripping a gruesome hole in [target]'s [affected.display_name] with \the [tool]!", \ "Your hand jolts as the system sparks, ripping a gruesome hole in [target]'s [affected.display_name] with \the [tool]!") affected.createwound(CUT, 20) @@ -148,7 +149,6 @@ ) priority = 0 - duration = 4 SECONDS /datum/surgery_step/generic/cut_open/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -157,28 +157,29 @@ to_chat(user, "[target] has no skin!") return 0 - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if(. && !affected.open && target_zone != "mouth") return . return 0 /datum/surgery_step/generic/cut_open/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] starts the incision on [target]'s [affected.display_name] with \the [tool].", \ "You start the incision on [target]'s [affected.display_name] with \the [tool].") target.custom_pain("You feel a horrible pain as if from a sharp knife in your [affected.display_name]!",1, scream=TRUE) ..() /datum/surgery_step/generic/cut_open/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] has made an incision on [target]'s [affected.display_name] with \the [tool].", \ "You have made an incision on [target]'s [affected.display_name] with \the [tool].",) affected.open = 1 - affected.status |= ORGAN_BLEEDING + if(!affected.cosmetic_only) + affected.status |= ORGAN_BLEEDING affected.createwound(CUT, 1) /datum/surgery_step/generic/cut_open/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user]'s hand slips, slicing open [target]'s [affected.display_name] in the wrong place with \the [tool]!", \ "Your hand slips, slicing open [target]'s [affected.display_name] in the wrong place with \the [tool]!") affected.createwound(CUT, 10) @@ -193,7 +194,7 @@ /obj/item/weapon/talisman = 70, /obj/item/device/assembly/mousetrap = 20, ) - + supports_cosmetic_organs = FALSE duration = 3 SECONDS /datum/surgery_step/generic/clamp_bleeders/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -234,7 +235,6 @@ /obj/item/tool/crowbar = 75, /obj/item/weapon/kitchen/utensil/fork = 50 ) - duration = 3 SECONDS /datum/surgery_step/generic/retract_skin/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -243,11 +243,11 @@ to_chat(user, "[target] has no skin!") return 0 - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) return affected.open == 1 //&& !(affected.status & ORGAN_BLEEDING) /datum/surgery_step/generic/retract_skin/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) var/msg = "[user] starts to pry open the incision on [target]'s [affected.display_name] with \the [tool]." var/self_msg = "You start to pry open the incision on [target]'s [affected.display_name] with \the [tool]." if (target_zone == LIMB_CHEST) @@ -261,7 +261,7 @@ ..() /datum/surgery_step/generic/retract_skin/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) var/msg = "[user] keeps the incision open on [target]'s [affected.display_name] with \the [tool]." var/self_msg = "You keep the incision open on [target]'s [affected.display_name] with \the [tool]." if (target_zone == LIMB_CHEST) @@ -274,7 +274,7 @@ affected.open = 2 /datum/surgery_step/generic/retract_skin/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) var/msg = "[user]'s hand slips, tearing the edges of the incision on [target]'s [affected.display_name] with \the [tool]!" var/self_msg = "Your hand slips, tearing the edges of the incision on [target]'s [affected.display_name] with \the [tool]!" if (target_zone == LIMB_CHEST) @@ -303,7 +303,6 @@ /obj/item/weapon/lighter = 50, /obj/item/tool/weldingtool = 25, ) - duration = 3 SECONDS /datum/surgery_step/generic/cauterize/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -312,18 +311,18 @@ to_chat(user, "[target] has no skin!") return 0 - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) return affected.open && target_zone != "mouth" /datum/surgery_step/generic/cauterize/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] is beginning to cauterize the incision on [target]'s [affected.display_name] with \the [tool]." , \ "You are beginning to cauterize the incision on [target]'s [affected.display_name] with \the [tool].") target.custom_pain("Your [affected.display_name] is being burned!",1, scream=TRUE) ..() /datum/surgery_step/generic/cauterize/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] cauterizes the incision on [target]'s [affected.display_name] with \the [tool].", \ "You cauterize the incision on [target]'s [affected.display_name] with \the [tool].") affected.open = 0 @@ -331,7 +330,7 @@ affected.status &= ~ORGAN_BLEEDING /datum/surgery_step/generic/cauterize/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user]'s hand slips, leaving a small burn on [target]'s [affected.display_name] with \the [tool]!", \ "Your hand slips, leaving a small burn on [target]'s [affected.display_name] with \the [tool]!") target.apply_damage(3, BURN, affected) @@ -345,7 +344,6 @@ /obj/item/weapon/kitchen/utensil/knife/large/butch = 75, /obj/item/weapon/hatchet = 75, ) - duration = 11 SECONDS /datum/surgery_step/generic/cut_limb/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -353,7 +351,7 @@ return 0 if (!hasorgans(target)) return 0 - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if (affected == null) return 0 if (affected.status & ORGAN_DESTROYED) @@ -363,14 +361,14 @@ return target_zone != LIMB_CHEST && target_zone != LIMB_GROIN && target_zone != LIMB_HEAD /datum/surgery_step/generic/cut_limb/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] is beginning to cut off [target]'s [affected.display_name] with \the [tool]." , \ "You are beginning to cut off [target]'s [affected.display_name] with \the [tool].") target.custom_pain("Your [affected.display_name] is being ripped apart!",1, scream=TRUE) ..() /datum/surgery_step/generic/cut_limb/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] cuts off [target]'s [affected.display_name] with \the [tool].", \ "You cut off [target]'s [affected.display_name] with \the [tool].") affected.open = 0 //Resets surgery status on limb, should prevent conflicting/phantom surgery @@ -397,7 +395,7 @@ ) priority = 0.1 //Tries to inject biofoam before other steps - + supports_cosmetic_organs = FALSE duration = 1 SECONDS /datum/surgery_step/generic/injectfoam/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) diff --git a/code/modules/surgery/robolimbs.dm b/code/modules/surgery/robolimbs.dm index a900f2b11bd..86d9c9dd68f 100644 --- a/code/modules/surgery/robolimbs.dm +++ b/code/modules/surgery/robolimbs.dm @@ -5,10 +5,12 @@ /datum/surgery_step/limb can_infect = 1 + supports_cosmetic_organs = TRUE + /datum/surgery_step/limb/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if (!hasorgans(target)) return 0 - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if (!affected || affected.name == LIMB_HEAD) return 0 if (!(affected.status & ORGAN_DESTROYED)) @@ -38,19 +40,19 @@ duration = 8 SECONDS /datum/surgery_step/limb/cut/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] starts cutting away flesh where [target]'s [affected.display_name] used to be with \the [tool].", \ "You start cutting away flesh where [target]'s [affected.display_name] used to be with \the [tool].") ..() /datum/surgery_step/limb/cut/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] cuts away flesh where [target]'s [affected.display_name] used to be with \the [tool].", \ "You cut away flesh where [target]'s [affected.display_name] used to be with \the [tool].") affected.status |= ORGAN_CUT_AWAY /datum/surgery_step/limb/cut/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if (affected.parent) affected = affected.parent user.visible_message("[user]'s hand slips, cutting [target]'s [affected.display_name] open!", \ @@ -70,23 +72,23 @@ duration = 8 SECONDS /datum/surgery_step/limb/mend/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) return ..() && affected.status & ORGAN_CUT_AWAY /datum/surgery_step/limb/mend/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] is beginning to reposition flesh and nerve endings where [target]'s [affected.display_name] used to be with [tool].", \ "You start repositioning flesh and nerve endings where [target]'s [affected.display_name] used to be with [tool].") ..() /datum/surgery_step/limb/mend/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] has finished repositioning flesh and nerve endings where [target]'s [affected.display_name] used to be with [tool].", \ "You have finished repositioning flesh and nerve endings where [target]'s [affected.display_name] used to be with [tool].") affected.open = 3 /datum/surgery_step/limb/mend/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if (affected.parent) affected = affected.parent user.visible_message("[user]'s hand slips, tearing flesh on [target]'s [affected.display_name]!", \ @@ -114,17 +116,17 @@ duration = 6 SECONDS /datum/surgery_step/limb/prepare/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) return ..() && affected.open == 3 /datum/surgery_step/limb/prepare/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] starts adjusting area around [target]'s [affected.display_name] with \the [tool].", \ "You start adjusting area around [target]'s [affected.display_name] with \the [tool].") ..() /datum/surgery_step/limb/prepare/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] has finished adjusting the area around [target]'s [affected.display_name] with \the [tool].", \ "You have finished adjusting the area around [target]'s [affected.display_name] with \the [tool].") affected.status |= ORGAN_ATTACHABLE @@ -133,7 +135,7 @@ affected.open = 0 /datum/surgery_step/limb/prepare/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if (affected.parent) affected = affected.parent user.visible_message("[user]'s hand slips, searing [target]'s [affected.display_name]!", \ @@ -147,15 +149,13 @@ allowed_tools = list( /obj/item/robot_parts = 100, ) - can_infect = 0 - duration = 8 SECONDS /datum/surgery_step/limb/attach/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/robot_parts/p = tool - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if(!(affected.status & ORGAN_ATTACHABLE) || !istype(p)) return 0 //not even ready for this and we're assuming they're using a fucking robot part! if (p.part) @@ -167,19 +167,19 @@ return ..() /datum/surgery_step/limb/attach/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] starts attaching [tool] where [target]'s [affected.display_name] used to be.", \ "You start attaching [tool] where [target]'s [affected.display_name] used to be.") /datum/surgery_step/limb/attach/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] has attached [tool] where [target]'s [affected.display_name] used to be.", \ "You have attached [tool] where [target]'s [affected.display_name] used to be.") affected.attach(tool) /datum/surgery_step/limb/attach/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user]'s hand slips, damaging connectors on [target]'s [affected.display_name]!", \ "Your hand slips, damaging connectors on [target]'s [affected.display_name]!") target.apply_damage(10, BRUTE, affected) @@ -193,7 +193,7 @@ ) can_infect = 0 - + supports_cosmetic_organs = FALSE duration = 8 SECONDS /datum/surgery_step/limb/attach_plank/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -236,7 +236,7 @@ /datum/surgery_step/limb/attach_flesh/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/o = tool - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) if(!(affected.status & ORGAN_ATTACHABLE) || !istype(o)) return 0 if (o.part) @@ -249,19 +249,19 @@ return ..() /datum/surgery_step/limb/attach_flesh/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] starts attaching [tool] where [target]'s [affected.display_name] used to be.", \ "You start attaching [tool] where [target]'s [affected.display_name] used to be.") /datum/surgery_step/limb/attach_flesh/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user] has attached [tool] where [target]'s [affected.display_name] used to be.", \ "You have attached [tool] where [target]'s [affected.display_name] used to be.") affected.attach(tool) /datum/surgery_step/limb/attach_flesh/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/external/affected = target.get_organ(target_zone, cosmetic = TRUE) user.visible_message("[user]'s hand slips, damaging connectors on [target]'s [affected.display_name]!", \ "Your hand slips, damaging connectors on [target]'s [affected.display_name]!") target.apply_damage(10, BRUTE, affected) diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index c3c6d92bd8f..a162bd5790a 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -10,7 +10,7 @@ var/list/disallowed_species = null var/duration = 0 - + var/supports_cosmetic_organs = FALSE var/list/mob/doing_surgery = list() //who's doing this RIGHT NOW // evil infection stuff that will make everyone hate me @@ -65,7 +65,7 @@ if (can_infect && affected) spread_germs_to_organ(affected, user) - if(!(affected.status & (ORGAN_ROBOT|ORGAN_PEG)))//robot organs and pegs can't spread diseases or splatter blood + if((!(affected.status & (ORGAN_ROBOT|ORGAN_PEG))) && !affected.cosmetic_only)//robot organs and pegs can't spread diseases or splatter blood var/block = user.check_contact_sterility(HANDS) var/bleeding = user.check_bodypart_bleeding(HANDS) target.oneway_contact_diseases(user,block,bleeding)//potentially spreads diseases from us to them, wear latex gloves! @@ -108,7 +108,7 @@ return null /proc/spread_germs_to_organ(datum/organ/external/E, mob/living/carbon/human/user) - if(!istype(user) || !istype(E)) + if(!istype(user) || !istype(E) || E.cosmetic_only) return var/germ_level = user.germ_level @@ -131,8 +131,19 @@ clumsy = 1 var/target_area = user.zone_sel ? user.zone_sel.selecting : get_random_zone_sel() + if(target_area == LIMB_GROIN) + var/groin_or_tail = input(user, "Groin or tail?", "Choose Target Zone", "Groin") as null|anything in list("Groin", "Tail") + switch(groin_or_tail) + if("Groin") + target_area = LIMB_GROIN + if("Tail") + target_area = COSMETIC_ORGAN_TAIL for(var/datum/surgery_step/S in surgery_steps) + if(ishuman(M)) + var/mob/living/carbon/human/human_target = M + if((target_area in human_target.cosmetic_organs_by_name) && !S.supports_cosmetic_organs) + continue //check if tool is right or close enough and if this step is possible sleep_fail = 0 if(S.tool_quality(tool)) diff --git a/icons/effects/species.dmi b/icons/effects/species.dmi index dea7af2b0ef..f7ca464f73e 100644 Binary files a/icons/effects/species.dmi and b/icons/effects/species.dmi differ diff --git a/icons/mob/human_races/vox/r_def_vox.dmi b/icons/mob/human_races/vox/r_def_vox.dmi index 6f2497be47d..cacf1d90fd1 100644 Binary files a/icons/mob/human_races/vox/r_def_vox.dmi and b/icons/mob/human_races/vox/r_def_vox.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxazu.dmi b/icons/mob/human_races/vox/r_def_voxazu.dmi index 886a726fb30..c0394361dc5 100644 Binary files a/icons/mob/human_races/vox/r_def_voxazu.dmi and b/icons/mob/human_races/vox/r_def_voxazu.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxbrn.dmi b/icons/mob/human_races/vox/r_def_voxbrn.dmi index e2b48f1959a..af7be19bd18 100644 Binary files a/icons/mob/human_races/vox/r_def_voxbrn.dmi and b/icons/mob/human_races/vox/r_def_voxbrn.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxemrl.dmi b/icons/mob/human_races/vox/r_def_voxemrl.dmi index 339bd6f2f0e..c9e622a1d6a 100644 Binary files a/icons/mob/human_races/vox/r_def_voxemrl.dmi and b/icons/mob/human_races/vox/r_def_voxemrl.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxgry.dmi b/icons/mob/human_races/vox/r_def_voxgry.dmi index ecf93b8adda..d3b4f5e2824 100644 Binary files a/icons/mob/human_races/vox/r_def_voxgry.dmi and b/icons/mob/human_races/vox/r_def_voxgry.dmi differ diff --git a/icons/mob/human_races/vox/r_def_voxlgrn.dmi b/icons/mob/human_races/vox/r_def_voxlgrn.dmi index a3c5076f62a..cdcdc187263 100644 Binary files a/icons/mob/human_races/vox/r_def_voxlgrn.dmi and b/icons/mob/human_races/vox/r_def_voxlgrn.dmi differ diff --git a/icons/mob/human_races/vox/r_vox.dmi b/icons/mob/human_races/vox/r_vox.dmi index 994aa4d3684..92bfe552a84 100644 Binary files a/icons/mob/human_races/vox/r_vox.dmi and b/icons/mob/human_races/vox/r_vox.dmi differ diff --git a/icons/mob/human_races/vox/r_voxazu.dmi b/icons/mob/human_races/vox/r_voxazu.dmi index e8283333af6..8ad3b14c35b 100644 Binary files a/icons/mob/human_races/vox/r_voxazu.dmi and b/icons/mob/human_races/vox/r_voxazu.dmi differ diff --git a/icons/mob/human_races/vox/r_voxbrn.dmi b/icons/mob/human_races/vox/r_voxbrn.dmi index 22a1291294d..b9c791e57c9 100644 Binary files a/icons/mob/human_races/vox/r_voxbrn.dmi and b/icons/mob/human_races/vox/r_voxbrn.dmi differ diff --git a/icons/mob/human_races/vox/r_voxemrl.dmi b/icons/mob/human_races/vox/r_voxemrl.dmi index 7651192eea6..7f754b65c70 100644 Binary files a/icons/mob/human_races/vox/r_voxemrl.dmi and b/icons/mob/human_races/vox/r_voxemrl.dmi differ diff --git a/icons/mob/human_races/vox/r_voxgry.dmi b/icons/mob/human_races/vox/r_voxgry.dmi index c552bfd7ea8..e347a1aa794 100644 Binary files a/icons/mob/human_races/vox/r_voxgry.dmi and b/icons/mob/human_races/vox/r_voxgry.dmi differ diff --git a/icons/mob/human_races/vox/r_voxlgrn.dmi b/icons/mob/human_races/vox/r_voxlgrn.dmi index 3a11997d4da..21997d08b0d 100644 Binary files a/icons/mob/human_races/vox/r_voxlgrn.dmi and b/icons/mob/human_races/vox/r_voxlgrn.dmi differ diff --git a/icons/mob/human_races/vox/tails.dmi b/icons/mob/human_races/vox/tails.dmi new file mode 100644 index 00000000000..9cd42af7f60 Binary files /dev/null and b/icons/mob/human_races/vox/tails.dmi differ diff --git a/icons/mob/tails.dmi b/icons/mob/tails.dmi new file mode 100644 index 00000000000..91984884058 Binary files /dev/null and b/icons/mob/tails.dmi differ diff --git a/vgstation13.dme b/vgstation13.dme index b749fcc0b24..7009e6cb34a 100644 --- a/vgstation13.dme +++ b/vgstation13.dme @@ -71,6 +71,7 @@ #include "__DEFINES\simple_animal_defines.dm" #include "__DEFINES\snow.dm" #include "__DEFINES\sort.dm" +#include "__DEFINES\span.dm" #include "__DEFINES\spell_defines.dm" #include "__DEFINES\striketeam_defines.dm" #include "__DEFINES\stylesheet.dm" @@ -296,6 +297,7 @@ #include "code\datums\mind.dm" #include "code\datums\mixed.dm" #include "code\datums\modules.dm" +#include "code\datums\mutable_appearance.dm" #include "code\datums\next_map.dm" #include "code\datums\periodic_news.dm" #include "code\datums\profiling.dm" @@ -1986,7 +1988,8 @@ #include "code\modules\mob\living\carbon\human\life\handle_statis_bag.dm" #include "code\modules\mob\living\carbon\human\life\handle_stomach.dm" #include "code\modules\mob\living\carbon\human\life\life_helpers.dm" -#include "code\modules\mob\living\carbon\human\plasmaman\species.dm" +#include "code\modules\mob\living\carbon\human\species\plasmaman.dm" +#include "code\modules\mob\living\carbon\human\species\vox.dm" #include "code\modules\mob\living\carbon\monkey\combat.dm" #include "code\modules\mob\living\carbon\monkey\death.dm" #include "code\modules\mob\living\carbon\monkey\diona.dm"