From ab032b6737a62a6dcf6cd259c1bd47b5fc7fc061 Mon Sep 17 00:00:00 2001 From: tigercat2000 Date: Thu, 25 Oct 2018 01:07:27 -0700 Subject: [PATCH] SSoverlays for human icons, mostly works Closer to working 100% But legitimately /tg/ icons Move lighting to it's own plane, fix observers Fix humans layering over other objects incorrectly Nyaaaaa~ --- code/__DEFINES/misc.dm | 70 +- code/__DEFINES/mobs.dm | 1 + code/game/dna/genes/disabilities.dm | 2 +- .../gamemodes/changeling/powers/revive.dm | 3 +- .../gamemodes/changeling/powers/shriek.dm | 2 +- code/game/gamemodes/vampire/vampire_powers.dm | 2 +- code/game/gamemodes/wizard/artefact.dm | 2 +- code/game/mecha/equipment/weapons/weapons.dm | 2 +- .../game/objects/items/weapons/clown_items.dm | 2 +- .../items/weapons/grenades/flashbang.dm | 23 +- code/modules/admin/verbs/freeze.dm | 10 +- code/modules/client/preference/preferences.dm | 18 +- code/modules/clothing/ears/ears.dm | 1 + code/modules/lighting/lighting_overlay.dm | 1 + code/modules/mob/dead/observer/observer.dm | 3 +- code/modules/mob/living/carbon/alien/alien.dm | 1 + .../living/carbon/alien/humanoid/humanoid.dm | 7 +- .../mob/living/carbon/alien/humanoid/life.dm | 8 - .../mob/living/carbon/alien/larva/larva.dm | 6 +- .../mob/living/carbon/alien/larva/life.dm | 8 - code/modules/mob/living/carbon/brain/brain.dm | 7 +- .../mob/living/carbon/brain/brain_item.dm | 6 - code/modules/mob/living/carbon/human/human.dm | 12 +- code/modules/mob/living/carbon/human/life.dm | 14 - .../living/carbon/human/species/_species.dm | 13 +- .../mob/living/carbon/human/species/human.dm | 9 +- .../mob/living/carbon/human/update_icons.dm | 668 ++++++++---------- code/modules/mob/living/carbon/slime/life.dm | 7 - code/modules/mob/living/carbon/slime/slime.dm | 5 +- .../mob/living/carbon/update_status.dm | 6 + code/modules/mob/living/life.dm | 9 - code/modules/mob/living/living.dm | 3 +- code/modules/mob/living/silicon/silicon.dm | 8 +- .../mob/living/simple_animal/simple_animal.dm | 8 +- code/modules/mob/living/status_procs.dm | 30 - code/modules/mob/living/update_status.dm | 6 +- .../mob/new_player/sprite_accessories.dm | 44 +- code/modules/mob/status_procs.dm | 14 +- code/modules/mob/update_status.dm | 2 +- .../reagents/chemistry/reagents/medicine.dm | 16 +- .../chemistry/recipes/pyrotechnics.dm | 47 +- code/modules/surgery/organs/ears.dm | 76 ++ code/modules/surgery/organs/organ_internal.dm | 7 +- code/modules/surgery/organs/vocal_cords.dm | 2 +- icons/obj/surgery.dmi | Bin 36413 -> 37002 bytes paradise.dme | 1 + 46 files changed, 581 insertions(+), 611 deletions(-) create mode 100644 code/modules/surgery/organs/ears.dm diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 1f0768ba9b0..d87150ad2de 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -204,40 +204,44 @@ #define MFOAM_IRON 2 //Human Overlays Indexes///////// -#define MUTANTRACE_LAYER 1 -#define TAIL_UNDERLIMBS_LAYER 2 //Tail split-rendering. -#define LIMBS_LAYER 3 -#define MARKINGS_LAYER 4 -#define UNDERWEAR_LAYER 5 -#define MUTATIONS_LAYER 6 -#define H_DAMAGE_LAYER 7 -#define UNIFORM_LAYER 8 -#define ID_LAYER 9 -#define SHOES_LAYER 10 -#define GLOVES_LAYER 11 -#define EARS_LAYER 12 -#define SUIT_LAYER 13 -#define BELT_LAYER 14 //Possible make this an overlay of somethign required to wear a belt? -#define SUIT_STORE_LAYER 15 -#define BACK_LAYER 16 -#define HEAD_ACCESSORY_LAYER 17 +#define BODY_LAYER 37 +#define MUTANTRACE_LAYER 36 +#define TAIL_UNDERLIMBS_LAYER 35 //Tail split-rendering. +#define LIMBS_LAYER 34 +#define INTORGAN_LAYER 33 +#define MARKINGS_LAYER 32 +#define UNDERWEAR_LAYER 31 +#define MUTATIONS_LAYER 30 +#define H_DAMAGE_LAYER 29 +#define UNIFORM_LAYER 28 +#define ID_LAYER 27 +#define SHOES_LAYER 26 +#define GLOVES_LAYER 25 +#define EARS_LAYER 24 +#define SUIT_LAYER 23 +#define BELT_LAYER 22 //Possible make this an overlay of somethign required to wear a belt? +#define SUIT_STORE_LAYER 21 +#define BACK_LAYER 20 +#define HEAD_ACCESSORY_LAYER 19 #define FHAIR_LAYER 18 -#define GLASSES_LAYER 19 -#define HAIR_LAYER 20 //TODO: make part of head layer? -#define HEAD_ACC_OVER_LAYER 21 //Select-layer rendering. -#define FHAIR_OVER_LAYER 22 //Select-layer rendering. -#define GLASSES_OVER_LAYER 23 //Select-layer rendering. -#define TAIL_LAYER 24 //bs12 specific. this hack is probably gonna come back to haunt me -#define FACEMASK_LAYER 25 -#define HEAD_LAYER 26 -#define COLLAR_LAYER 27 -#define HANDCUFF_LAYER 28 -#define LEGCUFF_LAYER 29 -#define L_HAND_LAYER 30 -#define R_HAND_LAYER 31 -#define TARGETED_LAYER 32 //BS12: Layer for the target overlay from weapon targeting system -#define FIRE_LAYER 33 //If you're on fire -#define TOTAL_LAYERS 33 +#define GLASSES_LAYER 17 +#define HAIR_LAYER 16 //TODO: make part of head layer? +#define HEAD_ACC_OVER_LAYER 15 //Select-layer rendering. +#define FHAIR_OVER_LAYER 14 //Select-layer rendering. +#define GLASSES_OVER_LAYER 13 //Select-layer rendering. +#define TAIL_LAYER 12 //bs12 specific. this hack is probably gonna come back to haunt me +#define FACEMASK_LAYER 11 +#define HEAD_LAYER 10 +#define COLLAR_LAYER 9 +#define HANDCUFF_LAYER 8 +#define LEGCUFF_LAYER 7 +#define L_HAND_LAYER 6 +#define R_HAND_LAYER 5 +#define TARGETED_LAYER 4 //BS12: Layer for the target overlay from weapon targeting system +#define FIRE_LAYER 3 //If you're on fire +#define MISC_LAYER 2 +#define FROZEN_LAYER 1 +#define TOTAL_LAYERS 37 ///Access Region Codes/// #define REGION_ALL 0 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 580cb85d696..139b029f55e 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -143,6 +143,7 @@ #define STATUS_UPDATE_NONE 0 #define STATUS_UPDATE_ALL (~0) +#define UNHEALING_EAR_DAMAGE 100 //Human sub-species #define isshadowling(A) (is_species(A, /datum/species/shadow/ling)) diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm index b346a3fecd9..2f6bf234de2 100644 --- a/code/game/dna/genes/disabilities.dm +++ b/code/game/dna/genes/disabilities.dm @@ -147,7 +147,7 @@ /datum/dna/gene/disability/deaf/activate(var/mob/M, var/connected, var/flags) ..() - M.EarDeaf(1) + M.MinimumDeafTicks(1) /datum/dna/gene/disability/nearsighted name="Nearsightedness" diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 9993388afec..147fdd2d327 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -16,8 +16,7 @@ user.radiation = 0 user.SetEyeBlind(0, FALSE) user.SetEyeBlurry(0, FALSE) - user.SetEarDamage(0) - user.SetEarDeaf(0) + user.RestoreEars() user.heal_overall_damage(user.getBruteLoss(), user.getFireLoss(), updating_health = FALSE) user.CureBlind(FALSE) user.CureDeaf() diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm index 5185b61e508..1c60013fbb8 100644 --- a/code/game/gamemodes/changeling/powers/shriek.dm +++ b/code/game/gamemodes/changeling/powers/shriek.dm @@ -11,7 +11,7 @@ for(var/mob/living/M in get_mobs_in_view(4, user)) if(iscarbon(M)) if(!M.mind || !M.mind.changeling) - M.AdjustEarDeaf(30) + M.MinimumDeafTicks(30) M.AdjustConfused(20) M.Jitter(50) else diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index 6d82f6c48e1..c45da8ac279 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -265,7 +265,7 @@ continue to_chat(C, "You hear a ear piercing shriek and your senses dull!") C.Weaken(4) - C.AdjustEarDeaf(20) + C.MinimumDeafTicks(20) C.Stuttering(20) C.Stun(4) C.Jitter(150) diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index 4c0aaac77da..18aba4ca69f 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -785,7 +785,7 @@ var/global/list/multiverse = list() else if(istype(I,/obj/item/bikehorn)) to_chat(target, "HONK") target << 'sound/items/AirHorn.ogg' - target.AdjustEarDeaf(3) + target.MinimumDeafTicks(3) GiveHint(target) cooldown = world.time +cooldown_time return diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 6d83b8fa927..011b2c6fab8 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -212,7 +212,7 @@ to_chat(M, "HONK") M.SetSleeping(0) M.Stuttering(20) - M.AdjustEarDeaf(30) + M.MinimumDeafTicks(30) M.Weaken(3) if(prob(30)) M.Stun(10) diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index 895c2809cca..165a61baa75 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -68,6 +68,6 @@ for(M in ohearers(7, T)) if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M - if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs) || H.ear_deaf) + if(!H.can_hear()) continue M.emote("flip") diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index 3e9336fc5a7..884265ec55b 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -59,13 +59,16 @@ if(!ear_safety) M.Stun(max(10/distance, 3)) M.Weaken(max(10/distance, 3)) - M.EarDeaf(15) - M.AdjustEarDamage(rand(0, 5)) - if(M.ear_damage >= 15) - to_chat(M, "Your ears start to ring badly!") - if(prob(M.ear_damage - 5)) - to_chat(M, "You can't hear anything!") - M.BecomeDeaf() - else - if(M.ear_damage >= 5) - to_chat(M, "Your ears start to ring!") + M.AdjustEarDamage(rand(0, 5), 15) + if(iscarbon(M)) + var/mob/living/carbon/C = M + var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears) + if(istype(ears)) + if(ears.ear_damage >= 15) + to_chat(M, "Your ears start to ring badly!") + if(prob(ears.ear_damage - 5)) + to_chat(M, "You can't hear anything!") + M.BecomeDeaf() + else + if(ears.ear_damage >= 5) + to_chat(M, "Your ears start to ring!") diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm index 8dc852e9221..de91530eabe 100644 --- a/code/modules/admin/verbs/freeze.dm +++ b/code/modules/admin/verbs/freeze.dm @@ -26,14 +26,15 @@ var/global/list/frozen_mob_list = list() /mob/living/var/frozen = null //used for preventing attacks on admin-frozen mobs /mob/living/var/admin_prev_sleeping = 0 //used for keeping track of previous sleeping value with admin freeze -/mob/living/proc/admin_Freeze(var/client/admin) +/mob/living/proc/admin_Freeze(var/client/admin, skip_overlays = FALSE) if(istype(admin)) to_chat(src, "You have been frozen by [key_name(admin)]") message_admins("[key_name_admin(admin)] froze [key_name_admin(src)]") log_admin("[key_name(admin)] froze [key_name(src)]") var/obj/effect/overlay/adminoverlay/AO = new - src.overlays += AO + if(skip_overlays) + src.overlays += AO anchored = 1 frozen = AO @@ -42,14 +43,15 @@ var/global/list/frozen_mob_list = list() if(!(src in frozen_mob_list)) frozen_mob_list += src -/mob/living/proc/admin_unFreeze(var/client/admin) +/mob/living/proc/admin_unFreeze(var/client/admin, skip_overlays = FALSE) if(istype(admin)) to_chat(src, "You have been unfrozen by [key_name(admin)]") message_admins("[key_name_admin(admin)] unfroze [key_name_admin(src)]") log_admin("[key_name(admin)] unfroze [key_name(src)]") anchored = 0 - overlays -= frozen + if(skip_overlays) + overlays -= frozen frozen = null SetSleeping(admin_prev_sleeping) admin_prev_sleeping = null diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index e0ab0087b97..9d13b58d3e3 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -1195,18 +1195,18 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("age") age = rand(AGE_MIN, AGE_MAX) if("hair") - if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) + if(species in list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) h_colour = rand_hex_color() if("secondary_hair") - if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) + if(species in list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) h_sec_colour = rand_hex_color() if("h_style") h_style = random_hair_style(gender, species, robohead) if("facial") - if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) + if(species in list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) f_colour = rand_hex_color() if("secondary_facial") - if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) + if(species in list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Machine", "Wryn", "Vulpkanin", "Vox")) f_sec_colour = rand_hex_color() if("f_style") f_style = random_facial_hair_style(gender, species, robohead) @@ -1276,7 +1276,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(new_age) age = max(min(round(text2num(new_age)), AGE_MAX),AGE_MIN) if("species") - var/list/new_species = list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin") + var/list/new_species = list("Human", "Felinid", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin") var/prev_species = species // var/whitelisted = 0 @@ -1407,14 +1407,14 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts b_type = new_b_type if("hair") - if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) //Species that have hair. (No HAS_HAIR flag) + if(species in list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) //Species that have hair. (No HAS_HAIR flag) var/input = "Choose your character's hair colour:" var/new_hair = input(user, input, "Character Preference", h_colour) as color|null if(new_hair) h_colour = new_hair if("secondary_hair") - if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) + if(species in list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) var/datum/sprite_accessory/hair_style = GLOB.hair_styles_public_list[h_style] if(hair_style.secondary_theme && !hair_style.no_sec_colour) var/new_hair = input(user, "Choose your character's secondary hair colour:", "Character Preference", h_sec_colour) as color|null @@ -1609,13 +1609,13 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts body_accessory = (new_body_accessory == "None") ? null : new_body_accessory if("facial") - if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) //Species that have facial hair. (No HAS_HAIR_FACIAL flag) + if(species in list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) //Species that have facial hair. (No HAS_HAIR_FACIAL flag) var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference", f_colour) as color|null if(new_facial) f_colour = new_facial if("secondary_facial") - if(species in list("Human", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) + if(species in list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Machine", "Vulpkanin", "Vox")) var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[f_style] if(facial_hair_style.secondary_theme && !facial_hair_style.no_sec_colour) var/new_facial = input(user, "Choose your character's secondary facial-hair colour:", "Character Preference", f_sec_colour) as color|null diff --git a/code/modules/clothing/ears/ears.dm b/code/modules/clothing/ears/ears.dm index 672df573858..2e3a1d40bda 100644 --- a/code/modules/clothing/ears/ears.dm +++ b/code/modules/clothing/ears/ears.dm @@ -4,6 +4,7 @@ icon_state = "earmuffs" item_state = "earmuffs" flags = EARBANGPROTECT + flags_2 = HEALS_EARS_2 strip_delay = 15 put_on_delay = 25 burn_state = FLAMMABLE diff --git a/code/modules/lighting/lighting_overlay.dm b/code/modules/lighting/lighting_overlay.dm index dd28f990322..a8f87338ae8 100644 --- a/code/modules/lighting/lighting_overlay.dm +++ b/code/modules/lighting/lighting_overlay.dm @@ -6,6 +6,7 @@ anchored = 1 icon = LIGHTING_ICON layer = LIGHTING_LAYER + plane = LIGHTING_PLANE invisibility = INVISIBILITY_LIGHTING color = LIGHTING_BASE_MATRIX icon_state = "light1" diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 26f77a31adc..065e5c4611e 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -48,8 +48,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi if(ishuman(body)) var/mob/living/carbon/human/H = body - icon = H.stand_icon - overlays = H.overlays_standing + appearance = H.appearance else icon = body.icon icon_state = body.icon_state diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index dea7c447191..6982d7f41c0 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -27,6 +27,7 @@ verbs += /mob/living/verb/lay_down alien_organs += new /obj/item/organ/internal/brain/xeno alien_organs += new /obj/item/organ/internal/xenos/hivenode + alien_organs += new /obj/item/organ/internal/ears for(var/obj/item/organ/internal/I in alien_organs) I.insert(src) ..() diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index da47f8c80b5..00aacd91b09 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -63,15 +63,12 @@ f_loss += 60 - AdjustEarDamage(30) - AdjustEarDeaf(120) - + AdjustEarDamage(30, 120) if(3.0) b_loss += 30 if(prob(50) && !shielded) Paralyse(1) - AdjustEarDamage(15) - AdjustEarDeaf(60) + AdjustEarDamage(15, 60) take_overall_damage(b_loss, f_loss) diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index 7771f1f5f90..6012a8fb7f3 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -78,14 +78,6 @@ else if(eye_blurry) //blurry eyes heal slowly AdjustEyeBlurry(-1) - //Ears - if(disabilities & DEAF) //disabled-deaf, doesn't get better on its own - EarDeaf(1) - else if(ear_deaf) //deafness, heals slowly over time - AdjustEarDeaf(-1) - else if(ear_damage < 25) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs - AdjustEarDamage(-0.05) - if(stuttering) AdjustStuttering(-1) diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index d0deac3e132..0b8aa891dde 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -56,15 +56,13 @@ f_loss += 60 - AdjustEarDamage(30) - AdjustEarDeaf(120) + AdjustEarDamage(30, 120) if(3.0) b_loss += 30 if(prob(50)) Paralyse(1) - AdjustEarDamage(15) - AdjustEarDeaf(60) + AdjustEarDamage(15, 60) adjustBruteLoss(b_loss) adjustFireLoss(f_loss) diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 654e9e27af3..a4b783e08fb 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -46,14 +46,6 @@ else if(eye_blurry) //blurry eyes heal slowly AdjustEyeBlurry(-1) - //Ears - if(disabilities & DEAF) //disabled-deaf, doesn't get better on its own - EarDeaf(1) - else if(ear_deaf) //deafness, heals slowly over time - AdjustEarDeaf(-1) - else if(ear_damage < 25) //ear damage heals slowly under this threshold. - AdjustEarDamage(-0.05) - if(stuttering) AdjustStuttering(-1) diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm index c64318d804b..0f7d4230587 100644 --- a/code/modules/mob/living/carbon/brain/brain.dm +++ b/code/modules/mob/living/carbon/brain/brain.dm @@ -108,8 +108,5 @@ I'm using this for Stat to give it a more nifty interface to work with /mob/living/carbon/brain/can_safely_leave_loc() return 0 //You're not supposed to be ethereal jaunting, brains -/mob/living/carbon/brain/SetEarDamage() // no ears to damage or heal - return - -/mob/living/carbon/brain/SetEarDeaf() - return +/mob/living/carbon/brain/can_hear() + . = TRUE diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 0a8f6fb3b83..03675f282e5 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -19,12 +19,6 @@ var/mmi_icon = 'icons/obj/assemblies.dmi' var/mmi_icon_state = "mmi_full" -/obj/item/organ/internal/brain/surgeryize() - if(!owner) - return - owner.SetEarDeaf(0) - owner.SetEarDamage(0) //Yeah, didn't you...hear? The ears are totally inside the brain. - /obj/item/organ/internal/brain/xeno name = "xenomorph brain" desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 731380b68d4..7ffceaceef6 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -7,6 +7,7 @@ var/obj/item/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(loc) + icon = null // This is now handled by overlays -- we just keep an icon for the sake of the map editor. if(length(args) > 1) log_runtime(EXCEPTION("human/New called with more than 1 argument (REPORT THIS ENTIRE RUNTIME TO A CODER)")) . = ..() @@ -264,8 +265,7 @@ else valid_limbs -= processing_dismember if(!istype(l_ear, /obj/item/clothing/ears/earmuffs) && !istype(r_ear, /obj/item/clothing/ears/earmuffs)) - AdjustEarDamage(30) - AdjustEarDeaf(120) + AdjustEarDamage(30, 120) if(prob(70) && !shielded) Paralyse(10) @@ -289,8 +289,7 @@ else valid_limbs -= processing_dismember if(!istype(l_ear, /obj/item/clothing/ears/earmuffs) && !istype(r_ear, /obj/item/clothing/ears/earmuffs)) - AdjustEarDamage(15) - AdjustEarDeaf(60) + AdjustEarDamage(15, 60) if(prob(50) && !shielded) Paralyse(10) @@ -1527,8 +1526,9 @@ var/obj/item/organ/external/head/head_organ = get_organ("head") var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style] var/icon/hair = new /icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - - return image(get_icon_difference(get_eyecon(), hair), layer = LIGHTING_LAYER + 1) //Cut the hair's pixels from the eyes icon so eyes covered by bangs stay hidden even while on a higher layer. + var/mutable_appearance/MA = mutable_appearance(get_icon_difference(get_eyecon(), hair), layer = LIGHTING_LAYER + 1) + MA.plane = LIGHTING_PLANE + return MA //Cut the hair's pixels from the eyes icon so eyes covered by bangs stay hidden even while on a higher layer. /*Used to check if eyes should shine in the dark. Returns the image of the eyes on the layer where they will appear to shine. Eyes need to have significantly high darksight to shine unless the mob has the XRAY vision mutation. Eyes will not shine if they are covered in any way.*/ diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index f13d948842c..ce1d9a7f56e 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -786,20 +786,6 @@ AdjustEyeBlurry(-1) - //Ears - if(disabilities & DEAF) //disabled-deaf, doesn't get better on its own - EarDeaf(1) - - else if(ear_deaf) //deafness, heals slowly over time - AdjustEarDeaf(-1) - - else if(istype(l_ear, /obj/item/clothing/ears/earmuffs) || istype(r_ear, /obj/item/clothing/ears/earmuffs)) //resting your ears with earmuffs heals ear damage faster - AdjustEarDamage(-0.15) - EarDeaf(1) - - else if(ear_damage < 25) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs - AdjustEarDamage(-0.05) - if(flying) animate(src, pixel_y = pixel_y + 5 , time = 10, loop = 1, easing = SINE_EASING) animate(pixel_y = pixel_y - 5, time = 10, loop = 1, easing = SINE_EASING) diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index 90088f49926..3912e73a373 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -153,6 +153,9 @@ "l_foot" = list("path" = /obj/item/organ/external/foot), "r_foot" = list("path" = /obj/item/organ/external/foot/right)) + // Mutant pieces + var/obj/item/organ/internal/ears/mutantears = /obj/item/organ/internal/ears + /datum/species/New() //If the species has eyes, they are the default vision organ if(!vision_organ && has_organ["eyes"]) @@ -165,7 +168,6 @@ return species_language.get_random_name(gender) /datum/species/proc/create_organs(mob/living/carbon/human/H) //Handles creation of mob organs. - QDEL_LIST(H.internal_organs) QDEL_LIST(H.bodyparts) @@ -184,12 +186,21 @@ // organ new code calls `insert` on its own new organ(H) + create_mutant_organs(H) + for(var/name in H.bodyparts_by_name) H.bodyparts |= H.bodyparts_by_name[name] for(var/obj/item/organ/external/O in H.bodyparts) O.owner = H +/datum/species/proc/create_mutant_organs(mob/living/carbon/human/H) + var/obj/item/organ/internal/ears/ears = H.get_int_organ(/obj/item/organ/internal/ears) + if(ears) + qdel(ears) + + ears = new mutantears(H) + /datum/species/proc/breathe(mob/living/carbon/human/H) if((NO_BREATHE in species_traits) || (BREATHLESS in H.mutations)) return TRUE diff --git a/code/modules/mob/living/carbon/human/species/human.dm b/code/modules/mob/living/carbon/human/species/human.dm index 2a161ab9318..7009af295ac 100644 --- a/code/modules/mob/living/carbon/human/species/human.dm +++ b/code/modules/mob/living/carbon/human/species/human.dm @@ -17,4 +17,11 @@ worlds tumultous at best." reagent_tag = PROCESS_ORG - //Has standard darksight of 2. \ No newline at end of file + //Has standard darksight of 2. + +/datum/species/human/cat + name = "Felinid" + name_plural = "Felinids" + blurb = "CATGIRLS OMG" + + mutantears = /obj/item/organ/internal/ears/cat \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 8dff1863061..4357584a18e 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -105,68 +105,20 @@ Please contact me on #coderbus IRC. ~Carn x /mob/living/carbon/human var/list/overlays_standing[TOTAL_LAYERS] - var/list/misc_effect_overlays = list() //Overlays that are applied at a custom layer (defined in each image's .layer property) outside of standard overlay application. Updated in update_misc_effects() var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed var/icon/skeleton var/list/cached_standing_overlays = list() // List of everything currently in a human's actual overlays -//UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING -//this proc is messy as I was forced to include some old laggy cloaking code to it so that I don't break cloakers -//I'll work on removing that stuff by rewriting some of the cloaking stuff at a later date. -/mob/living/carbon/human/update_icons() - var/stealth = 0 - var/obj/item/clothing/suit/armor/abductor/vest/V // Begin the most snowflakey bullshit code I've ever written. I'm so sorry, but there was no other way. +/mob/living/carbon/human/proc/apply_overlay(cache_index) + if((. = overlays_standing[cache_index])) + add_overlay(.) - for(V in list(wear_suit)) - if(V.stealth_active) - stealth = 1 - break +/mob/living/carbon/human/proc/remove_overlay(cache_index) + var/I = overlays_standing[cache_index] + if(I) + cut_overlay(I) + overlays_standing[cache_index] = null - if(stealth) - icon = V.disguise.icon //if the suit is active, reference the suit's current loaded icon and overlays; this does not include hand overlays - overlays.Cut() - cached_standing_overlays.Cut() // Make sure the cache gets rebuilt once the disguise is gone - - for(var/thing in V.disguise.overlays) - if(thing) - overlays += thing - - var/image/I = overlays_standing[L_HAND_LAYER] //manually add both left and right hand, so its independently updated - if(istype(I)) - overlays += I - I = overlays_standing[R_HAND_LAYER] - if(istype(I)) - overlays += I - else - icon = stand_icon - var/list/new_overlays = list() - var/list/old_overlays = cached_standing_overlays - - // Totally regenerate if something touched our overlays - if(overlays.len != old_overlays.len) - overlays.Cut() - old_overlays.Cut() - - for(var/i in 1 to TOTAL_LAYERS) - var/image/I = overlays_standing[i] - if(I) - if(istype(I)) - // Since we avoid full overlay rebuilds, we have to reorganize the layers manually - I.layer = (-2 - (TOTAL_LAYERS - i)) // Highest layer gets -2, each prior layer is 1 lower - new_overlays += I - - update_misc_effects() - if(misc_effect_overlays) - new_overlays += misc_effect_overlays - - if(frozen) // Admin freeze overlay - new_overlays += frozen - - overlays += (new_overlays - old_overlays) - overlays -= (old_overlays - new_overlays) - cached_standing_overlays = new_overlays - - update_transform() var/global/list/damage_icon_parts = list() @@ -185,38 +137,42 @@ var/global/list/damage_icon_parts = list() previous_damage_appearance = damage_appearance - var/icon/standing = new /icon(dna.species.damage_overlays, "00") - - var/image/standing_image = new /image("icon" = standing) + remove_overlay(H_DAMAGE_LAYER) + var/mutable_appearance/damage_overlay = mutable_appearance(dna.species.damage_overlays, "00", layer = -H_DAMAGE_LAYER) + overlays_standing[H_DAMAGE_LAYER] = damage_overlay // blend the individual damage states with our icons - for(var/obj/item/organ/external/O in bodyparts) - O.update_icon() - if(O.damage_state == "00") continue + for(var/D in bodyparts) + var/obj/item/organ/external/E = D + E.update_icon() + if(E.damage_state == "00") + continue + var/icon/DI - var/cache_index = "[O.damage_state]/[O.icon_name]/[dna.species.blood_color]/[dna.species.name]" + var/cache_index = "[E.damage_state]/[E.icon_name]/[dna.species.blood_color]/[dna.species.name]" if(damage_icon_parts[cache_index] == null) - DI = new /icon(dna.species.damage_overlays, O.damage_state) // the damage icon for whole human - DI.Blend(new /icon(dna.species.damage_mask, O.icon_name), ICON_MULTIPLY) // mask with this organ's pixels + DI = new /icon(dna.species.damage_overlays, E.damage_state) // the damage icon for whole human + DI.Blend(new /icon(dna.species.damage_mask, E.icon_name), ICON_MULTIPLY) // mask with this organ's pixels DI.Blend(dna.species.blood_color, ICON_MULTIPLY) damage_icon_parts[cache_index] = DI else DI = damage_icon_parts[cache_index] - standing_image.overlays += DI + damage_overlay.overlays += DI - overlays_standing[H_DAMAGE_LAYER] = standing_image + apply_overlay(H_DAMAGE_LAYER) - if(update_icons) update_icons() //BASE MOB SPRITE /mob/living/carbon/human/proc/update_body(var/update_icons=1, var/rebuild_base=0) + remove_overlay(BODY_LAYER) + remove_overlay(LIMBS_LAYER) // So we don't get the old species' sprite splatted on top of the new one's + remove_overlay(UNDERWEAR_LAYER) - var/husk_color_mod = rgb(96,88,80) - var/hulk_color_mod = rgb(48,224,40) + var/husk_color_mod = rgb(96, 88, 80) + var/hulk_color_mod = rgb(48, 224, 40) var/husk = (HUSK in mutations) - var/fat = (FAT in mutations) var/hulk = (HULK in mutations) var/skeleton = (SKELETON in mutations) @@ -228,42 +184,18 @@ var/global/list/damage_icon_parts = list() //Create a new, blank icon for our mob to use. if(stand_icon) qdel(stand_icon) - stand_icon = new(dna.species.icon_template ? dna.species.icon_template : 'icons/mob/human.dmi',"blank") - var/icon_key = "" - var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) - if(eyes) - icon_key += "[eyes.eye_colour]" - else - icon_key += "#000000" + update_misc_effects() + stand_icon = new (dna.species.icon_template ? dna.species.icon_template : 'icons/mob/human.dmi', "blank") + var/list/standing = list() + var/icon_key = generate_icon_render_key() - for(var/organ_tag in dna.species.has_limbs) - var/obj/item/organ/external/part = bodyparts_by_name[organ_tag] - if(isnull(part)) - icon_key += "0" - else if(part.is_robotic()) - icon_key += "2[part.model ? "-[part.model]": ""]" - else if(part.status & ORGAN_DEAD) - icon_key += "3" - else - icon_key += "1" - - if(part) - var/datum/species/S = GLOB.all_species[part.dna.species.name] //This has to reference the species datums from round start, since they're global and unchanging - icon_key += "[S.race_key]" - icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]" - icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" - if(part.s_col) - icon_key += "[part.s_col]" - if(part.s_tone) - icon_key += "[part.s_tone]" - - icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]" - - var/icon/base_icon + var/mutable_appearance/base if(human_icon_cache[icon_key] && !rebuild_base) - base_icon = human_icon_cache[icon_key] + base = human_icon_cache[icon_key] + standing += base else + var/icon/base_icon //BEGIN CACHED ICON GENERATION. var/obj/item/organ/external/chest = get_organ("chest") base_icon = chest.get_icon(skeleton) @@ -272,7 +204,7 @@ var/global/list/damage_icon_parts = list() var/icon/temp = part.get_icon(skeleton) //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST //And no change in rendering for other parts (they icon_position is 0, so goes to 'else' part) - if(part.icon_position&(LEFT|RIGHT)) + if(part.icon_position & (LEFT | RIGHT)) var/icon/temp2 = new('icons/mob/human.dmi',"blank") temp2.Insert(new/icon(temp,dir=NORTH),dir=NORTH) temp2.Insert(new/icon(temp,dir=SOUTH),dir=SOUTH) @@ -304,19 +236,16 @@ var/global/list/damage_icon_parts = list() husk_over.Blend(mask, ICON_ADD) base_icon.Blend(husk_over, ICON_OVERLAY) - human_icon_cache[icon_key] = base_icon + var/mutable_appearance/new_base = mutable_appearance(base_icon, layer = -LIMBS_LAYER) + human_icon_cache[icon_key] = new_base + standing += new_base + //END CACHED ICON GENERATION. - //END CACHED ICON GENERATION. - stand_icon.Blend(base_icon,ICON_OVERLAY) - if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the user's species is flagged to have a tail that needs to be overlapped by limbs... (having a non-tail body accessory like the snake body will override this) - overlays_standing[LIMBS_LAYER] = image(stand_icon) // Diverts limbs to their own layer so they can overlay things (i.e. tails). - else - overlays_standing[LIMBS_LAYER] = null // So we don't get the old species' sprite splatted on top of the new one's + overlays_standing[LIMBS_LAYER] = standing + apply_overlay(LIMBS_LAYER) //Underwear - overlays_standing[UNDERWEAR_LAYER] = null - var/icon/underwear_standing = new/icon('icons/mob/underwear.dmi',"nude") - + var/icon/underwear_standing = new /icon('icons/mob/underwear.dmi', "nude") if(underwear && dna.species.clothing_flags & HAS_UNDERWEAR) var/datum/sprite_accessory/underwear/U = GLOB.underwear_list[underwear] if(U) @@ -327,27 +256,25 @@ var/global/list/damage_icon_parts = list() if(U2) underwear_standing.Blend(new /icon(U2.icon, "us_[U2.icon_state]_s"), ICON_OVERLAY) - if(socks && dna.species.clothing_flags & HAS_SOCKS) var/datum/sprite_accessory/socks/U3 = GLOB.socks_list[socks] if(U3) underwear_standing.Blend(new /icon(U3.icon, "sk_[U3.icon_state]_s"), ICON_OVERLAY) if(underwear_standing) - overlays_standing[UNDERWEAR_LAYER] = image(underwear_standing) - - - if(update_icons) - update_icons() + overlays_standing[UNDERWEAR_LAYER] = mutable_appearance(underwear_standing, layer = -UNDERWEAR_LAYER) + apply_overlay(UNDERWEAR_LAYER) if(lip_style && (LIPS in dna.species.species_traits)) - var/icon/lips = icon("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[lip_style]_s") + var/icon/lips = icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "lips_[lip_style]_s") lips.Blend(lip_color, ICON_ADD) + standing += mutable_appearance(lips, layer = -BODY_LAYER) - stand_icon.Blend(lips, ICON_OVERLAY) - + overlays_standing[BODY_LAYER] = standing + apply_overlay(BODY_LAYER) //tail update_tail_layer(0) + update_int_organs() //head accessory update_head_accessory(0) //markings @@ -360,10 +287,10 @@ var/global/list/damage_icon_parts = list() //MARKINGS OVERLAY /mob/living/carbon/human/proc/update_markings(var/update_icons=1) //Reset our markings. - overlays_standing[MARKINGS_LAYER] = null + remove_overlay(MARKINGS_LAYER) //Base icon. - var/icon/markings_standing = new/icon('icons/mob/body_accessory.dmi',"accessory_none_s") + var/icon/markings_standing = icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "accessory_none_s") //Body markings. var/obj/item/organ/external/chest/chest_organ = get_organ("chest") @@ -371,7 +298,7 @@ var/global/list/damage_icon_parts = list() var/body_marking = m_styles["body"] var/datum/sprite_accessory/body_marking_style = GLOB.marking_styles_list[body_marking] if(body_marking_style && body_marking_style.species_allowed && (dna.species.name in body_marking_style.species_allowed)) - var/icon/b_marking_s = new/icon("icon" = body_marking_style.icon, "icon_state" = "[body_marking_style.icon_state]_s") + var/icon/b_marking_s = icon("icon" = body_marking_style.icon, "icon_state" = "[body_marking_style.icon_state]_s") if(body_marking_style.do_colouration) b_marking_s.Blend(m_colours["body"], ICON_ADD) markings_standing.Blend(b_marking_s, ICON_OVERLAY) @@ -381,33 +308,30 @@ var/global/list/damage_icon_parts = list() var/head_marking = m_styles["head"] var/datum/sprite_accessory/head_marking_style = GLOB.marking_styles_list[head_marking] if(head_marking_style && head_marking_style.species_allowed && (head_organ.dna.species.name in head_marking_style.species_allowed)) - var/icon/h_marking_s = new/icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s") + var/icon/h_marking_s = icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s") if(head_marking_style.do_colouration) h_marking_s.Blend(m_colours["head"], ICON_ADD) markings_standing.Blend(h_marking_s, ICON_OVERLAY) - overlays_standing[MARKINGS_LAYER] = image(markings_standing) - - if(update_icons) update_icons() + overlays_standing[MARKINGS_LAYER] = mutable_appearance(markings_standing, layer = -MARKINGS_LAYER) + apply_overlay(MARKINGS_LAYER) //HEAD ACCESSORY OVERLAY /mob/living/carbon/human/proc/update_head_accessory(var/update_icons=1) //Reset our head accessory - overlays_standing[HEAD_ACCESSORY_LAYER] = null - overlays_standing[HEAD_ACC_OVER_LAYER] = null + remove_overlay(HEAD_ACCESSORY_LAYER) + remove_overlay(HEAD_ACC_OVER_LAYER) var/obj/item/organ/external/head/head_organ = get_organ("head") if(!head_organ) - if(update_icons) update_icons() return //masks and helmets can obscure our head accessory if((head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR))) - if(update_icons) update_icons() return //base icons - var/icon/head_accessory_standing = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") + var/icon/head_accessory_standing = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") if(head_organ.ha_style && (head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY)) var/datum/sprite_accessory/head_accessory/head_accessory_style = GLOB.head_accessory_styles_list[head_organ.ha_style] if(head_accessory_style && head_accessory_style.species_allowed) @@ -419,38 +343,33 @@ var/global/list/damage_icon_parts = list() //Having it this way preserves animations. Useful for animated antennae. if(head_accessory_style.over_hair) //Select which layer to use based on the properties of the head accessory style. - overlays_standing[HEAD_ACC_OVER_LAYER] = image(head_accessory_standing) + overlays_standing[HEAD_ACC_OVER_LAYER] = mutable_appearance(head_accessory_standing, layer = -HEAD_ACC_OVER_LAYER) + apply_overlay(HEAD_ACC_OVER_LAYER) else - overlays_standing[HEAD_ACCESSORY_LAYER] = image(head_accessory_standing) + overlays_standing[HEAD_ACCESSORY_LAYER] = mutable_appearance(head_accessory_standing, layer = -HEAD_ACCESSORY_LAYER) + apply_overlay(HEAD_ACCESSORY_LAYER) else //warning("Invalid ha_style for [species.name]: [ha_style]") - if(update_icons) update_icons() //HAIR OVERLAY /mob/living/carbon/human/proc/update_hair(var/update_icons=1) //Reset our hair - overlays_standing[HAIR_LAYER] = null + remove_overlay(HAIR_LAYER) var/obj/item/organ/external/head/head_organ = get_organ("head") if(!head_organ) - if(update_icons) update_icons() return //masks and helmets can obscure our hair, unless we're a synthetic if((head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR))) - if(update_icons) update_icons() return //base icons var/icon/hair_standing = new /icon('icons/mob/human_face.dmi',"bald_s") - //var/icon/debrained_s = new /icon("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s") - if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic()))) var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style] - //if(!src.get_int_organ(/obj/item/organ/internal/brain) && !ismachine(src))//make it obvious we have NO BRAIN - // hair_standing.Blend(debrained_s, ICON_OVERLAY) if(hair_style && hair_style.species_allowed) if((head_organ.dna.species.name in hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") @@ -471,30 +390,26 @@ var/global/list/damage_icon_parts = list() //warning("Invalid h_style for [species.name]: [h_style]") //hair_standing.Blend(debrained_s, ICON_OVERLAY)//how does i overlay for fish? - overlays_standing[HAIR_LAYER] = image(hair_standing) - - if(update_icons) update_icons() + overlays_standing[HAIR_LAYER] = mutable_appearance(hair_standing, layer = -HAIR_LAYER) + apply_overlay(HAIR_LAYER) //FACIAL HAIR OVERLAY /mob/living/carbon/human/proc/update_fhair(var/update_icons=1) //Reset our facial hair - overlays_standing[FHAIR_LAYER] = null - overlays_standing[FHAIR_OVER_LAYER] = null + remove_overlay(FHAIR_LAYER) + remove_overlay(FHAIR_OVER_LAYER) var/obj/item/organ/external/head/head_organ = get_organ("head") if(!head_organ) - if(update_icons) update_icons() return //masks and helmets can obscure our facial hair, unless we're a synthetic if((head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR))) - if(update_icons) update_icons() return //base icons var/icon/face_standing = new /icon('icons/mob/human_face.dmi',"bald_s") - if(head_organ.f_style) var/datum/sprite_accessory/facial_hair/facial_hair_style = GLOB.facial_hair_styles_list[head_organ.f_style] if(facial_hair_style && facial_hair_style.species_allowed) @@ -514,46 +429,49 @@ var/global/list/damage_icon_parts = list() face_standing.Blend(facial_s, ICON_OVERLAY) if(facial_hair_style.over_hair) //Select which layer to use based on the properties of the facial hair style. - overlays_standing[FHAIR_OVER_LAYER] = image(face_standing) + overlays_standing[FHAIR_OVER_LAYER] = mutable_appearance(face_standing, layer = -FHAIR_OVER_LAYER) + apply_overlay(FHAIR_OVER_LAYER) else - overlays_standing[FHAIR_LAYER] = image(face_standing) + overlays_standing[FHAIR_LAYER] = mutable_appearance(face_standing, layer = -FHAIR_LAYER) + apply_overlay(FHAIR_LAYER) else //warning("Invalid f_style for [species.name]: [f_style]") - if(update_icons) update_icons() + /mob/living/carbon/human/update_mutations(var/update_icons=1) + remove_overlay(MUTATIONS_LAYER) var/fat if(FAT in mutations) fat = "fat" - var/image/standing = image("icon" = 'icons/effects/genetics.dmi') + var/mutable_appearance/standing = mutable_appearance('icons/effects/genetics.dmi', layer = -MUTATIONS_LAYER) var/add_image = 0 var/g = "m" - if(gender == FEMALE) g = "f" + if(gender == FEMALE) + g = "f" // DNA2 - Drawing underlays. for(var/datum/dna/gene/gene in dna_genes) if(!gene.block) continue if(gene.is_active(src)) - var/underlay=gene.OnDrawUnderlays(src,g,fat) + var/underlay = gene.OnDrawUnderlays(src, g, fat) if(underlay) standing.underlays += underlay add_image = 1 for(var/mut in mutations) switch(mut) if(LASER) - standing.overlays += "lasereyes_s" + standing.overlays += "lasereyes_s" add_image = 1 if((COLDRES in mutations) && (HEATRES in mutations)) - standing.underlays -= "cold[fat]_s" - standing.underlays -= "fire[fat]_s" - standing.underlays += "coldfire[fat]_s" + standing.underlays -= "cold[fat]_s" + standing.underlays -= "fire[fat]_s" + standing.underlays += "coldfire[fat]_s" + if(add_image) - overlays_standing[MUTATIONS_LAYER] = standing - else - overlays_standing[MUTATIONS_LAYER] = null - if(update_icons) update_icons() + overlays_standing[MUTATIONS_LAYER] = standing + apply_overlay(MUTATIONS_LAYER) /mob/living/carbon/human/proc/update_mutantrace(var/update_icons=1) @@ -566,17 +484,14 @@ var/global/list/damage_icon_parts = list() update_hair(0) update_fhair(0) - if(update_icons) update_icons() /mob/living/carbon/human/update_fire() + remove_overlay(FIRE_LAYER) if(on_fire) if(!overlays_standing[FIRE_LAYER]) - overlays_standing[FIRE_LAYER] = image("icon"=fire_dmi, "icon_state"=fire_sprite) - update_icons() - else - overlays_standing[FIRE_LAYER] = null - update_icons() + overlays_standing[FIRE_LAYER] = mutable_appearance(fire_dmi, fire_sprite, layer = -FIRE_LAYER) + apply_overlay(FIRE_LAYER) /* --------------------------------------- */ //For legacy support. @@ -617,7 +532,7 @@ var/global/list/damage_icon_parts = list() //vvvvvv UPDATE_INV PROCS vvvvvv /mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1) - + remove_overlay(UNIFORM_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_w_uniform] if(inv) @@ -630,9 +545,10 @@ var/global/list/damage_icon_parts = list() client.screen += w_uniform //Either way, add the item to the HUD var/t_color = w_uniform.item_color - if(!t_color) t_color = icon_state - var/image/standing = image("icon_state" = "[t_color]_s") + if(!t_color) + t_color = icon_state + var/mutable_appearance/standing = mutable_appearance('icons/mob/uniform.dmi', "[t_color]_s", layer = -UNIFORM_LAYER) if(FAT in mutations) if(w_uniform.flags_size & ONESIZEFITSALL) standing.icon = 'icons/mob/uniform_fat.dmi' @@ -640,8 +556,6 @@ var/global/list/damage_icon_parts = list() to_chat(src, "You burst out of \the [w_uniform]!") unEquip(w_uniform) return - else - standing.icon = 'icons/mob/uniform.dmi' if(w_uniform.icon_override) standing.icon = w_uniform.icon_override @@ -650,13 +564,14 @@ var/global/list/damage_icon_parts = list() if(w_uniform.blood_DNA) var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "uniformblood") - bloodsies.color = w_uniform.blood_color - standing.overlays += bloodsies + bloodsies.color = w_uniform.blood_color + standing.overlays += bloodsies - if(w_uniform:accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE. + if(w_uniform:accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE. // oh my god kys whoever made this if statement jfc :gun: for(var/obj/item/clothing/accessory/A in w_uniform:accessories) var/tie_color = A.item_color - if(!tie_color) tie_color = A.icon_state + if(!tie_color) + tie_color = A.icon_state if(A.icon_override) standing.overlays += image("icon" = A.icon_override, "icon_state" = "[A.icon_state]") else if(A.sprite_sheets && A.sprite_sheets[dna.species.name]) @@ -664,25 +579,24 @@ var/global/list/damage_icon_parts = list() else standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]") - overlays_standing[UNIFORM_LAYER] = standing + overlays_standing[UNIFORM_LAYER] = standing else - overlays_standing[UNIFORM_LAYER] = null // Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY - for( var/obj/item/thing in list(r_store, l_store, wear_id, wear_pda, belt) ) // - if(thing) // - unEquip(thing) // - if(client) // - client.screen -= thing // - // + for(var/obj/item/thing in list(r_store, l_store, wear_id, wear_pda, belt)) // whoever made this + if(thing) // you're a piece of fucking garbage + unEquip(thing) // why the fuck would you goddamn do this motherfucking shit + if(client) // INVENTORY CODE IN FUCKING ICON CODE + client.screen -= thing // WHAT THE FUCKING FUCK BAY GODDAMNIT + // **I FUCKING HATE YOU AAAAAAAAAA** if(thing) // thing.loc = loc // thing.dropped(src) // thing.layer = initial(thing.layer) thing.plane = initial(thing.plane) - if(update_icons) update_icons() + apply_overlay(UNIFORM_LAYER) /mob/living/carbon/human/update_inv_wear_id(var/update_icons=1) - + remove_overlay(ID_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_id] if(inv) @@ -694,16 +608,11 @@ var/global/list/damage_icon_parts = list() client.screen += wear_id if(w_uniform && w_uniform:displays_id) - overlays_standing[ID_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "id") - else - overlays_standing[ID_LAYER] = null - else - overlays_standing[ID_LAYER] = null - - if(update_icons) update_icons() + overlays_standing[ID_LAYER] = mutable_appearance('icons/mob/mob.dmi', "id", layer = -ID_LAYER) + apply_overlay(ID_LAYER) /mob/living/carbon/human/update_inv_gloves(var/update_icons=1) - + remove_overlay(GLOVES_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_gloves] if(inv) @@ -718,32 +627,30 @@ var/global/list/damage_icon_parts = list() var/t_state = gloves.item_state if(!t_state) t_state = gloves.icon_state - var/image/standing + var/mutable_appearance/standing if(gloves.icon_override) - standing = image("icon" = gloves.icon_override, "icon_state" = "[t_state]") + standing = mutable_appearance(gloves.icon_override, "[t_state]", layer = -GLOVES_LAYER) else if(gloves.sprite_sheets && gloves.sprite_sheets[dna.species.name]) - standing = image("icon" = gloves.sprite_sheets[dna.species.name], "icon_state" = "[t_state]") + standing = mutable_appearance(gloves.sprite_sheets[dna.species.name], "[t_state]", layer = -GLOVES_LAYER) else - standing = image("icon" = 'icons/mob/hands.dmi', "icon_state" = "[t_state]") + standing = mutable_appearance('icons/mob/hands.dmi', "[t_state]", layer = -GLOVES_LAYER) if(gloves.blood_DNA) var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "bloodyhands") bloodsies.color = gloves.blood_color - standing.overlays += bloodsies + standing.overlays += bloodsies overlays_standing[GLOVES_LAYER] = standing else if(blood_DNA) - var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "bloodyhands") + var/mutable_appearance/bloodsies = mutable_appearance(dna.species.blood_mask, "bloodyhands", layer = -GLOVES_LAYER) bloodsies.color = hand_blood_color overlays_standing[GLOVES_LAYER] = bloodsies - else - overlays_standing[GLOVES_LAYER] = null - if(update_icons) update_icons() + apply_overlay(GLOVES_LAYER) /mob/living/carbon/human/update_inv_glasses(var/update_icons=1) - overlays_standing[GLASSES_LAYER] = null - overlays_standing[GLASSES_OVER_LAYER] = null + remove_overlay(GLASSES_LAYER) + remove_overlay(GLASSES_OVER_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_glasses] @@ -751,7 +658,7 @@ var/global/list/damage_icon_parts = list() inv.update_icon() if(glasses) - var/image/new_glasses + var/mutable_appearance/new_glasses var/obj/item/organ/external/head/head_organ = get_organ("head") if(client && hud_used && hud_used.hud_shown) if(hud_used.inventory_shown) //if the inventory is open ... @@ -759,22 +666,23 @@ var/global/list/damage_icon_parts = list() client.screen += glasses //Either way, add the item to the HUD if(glasses.icon_override) - new_glasses = image("icon" = glasses.icon_override, "icon_state" = "[glasses.icon_state]") + new_glasses = mutable_appearance(glasses.icon_override, "[glasses.icon_state]", layer = -GLASSES_LAYER) else if(glasses.sprite_sheets && glasses.sprite_sheets[head_organ.dna.species.name]) - new_glasses = image("icon" = glasses.sprite_sheets[head_organ.dna.species.name], "icon_state" = "[glasses.icon_state]") + new_glasses = mutable_appearance(glasses.sprite_sheets[head_organ.dna.species.name], "[glasses.icon_state]", layer = -GLASSES_LAYER) else - new_glasses = image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]") + new_glasses = mutable_appearance('icons/mob/eyes.dmi', "[glasses.icon_state]", layer = -GLASSES_LAYER) var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style] if(hair_style && hair_style.glasses_over) //Select which layer to use based on the properties of the hair style. Hair styles with hair that don't overhang the arms of the glasses should have glasses_over set to a positive value. + new_glasses.layer = -GLASSES_OVER_LAYER overlays_standing[GLASSES_OVER_LAYER] = new_glasses + apply_overlay(GLASSES_OVER_LAYER) else overlays_standing[GLASSES_LAYER] = new_glasses - - if(update_icons) update_icons() + apply_overlay(GLASSES_LAYER) /mob/living/carbon/human/update_inv_ears(var/update_icons=1) - + remove_overlay(EARS_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_l_ear] if(inv) @@ -795,12 +703,12 @@ var/global/list/damage_icon_parts = list() var/t_type = l_ear.icon_state if(l_ear.icon_override) t_type = "[t_type]_l" - overlays_standing[EARS_LAYER] = image("icon" = l_ear.icon_override, "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = mutable_appearance(l_ear.icon_override, "[t_type]", layer = -EARS_LAYER) else if(l_ear.sprite_sheets && l_ear.sprite_sheets[dna.species.name]) t_type = "[t_type]_l" - overlays_standing[EARS_LAYER] = image("icon" = l_ear.sprite_sheets[dna.species.name], "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = mutable_appearance(l_ear.sprite_sheets[dna.species.name], "[t_type]", layer = -EARS_LAYER) else - overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = mutable_appearance('icons/mob/ears.dmi', "[t_type]", layer = -EARS_LAYER) if(r_ear) if(client && hud_used && hud_used.hud_shown) @@ -811,19 +719,16 @@ var/global/list/damage_icon_parts = list() var/t_type = r_ear.icon_state if(r_ear.icon_override) t_type = "[t_type]_r" - overlays_standing[EARS_LAYER] = image("icon" = r_ear.icon_override, "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = mutable_appearance(r_ear.icon_override, "[t_type]", layer = -EARS_LAYER) else if(r_ear.sprite_sheets && r_ear.sprite_sheets[dna.species.name]) t_type = "[t_type]_r" - overlays_standing[EARS_LAYER] = image("icon" = r_ear.sprite_sheets[dna.species.name], "icon_state" = "[t_type]") + overlays_standing[EARS_LAYER] = mutable_appearance(r_ear.sprite_sheets[dna.species.name], "[t_type]", layer = -EARS_LAYER) else - overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") - - else - overlays_standing[EARS_LAYER] = null - if(update_icons) update_icons() + overlays_standing[EARS_LAYER] = mutable_appearance('icons/mob/ears.dmi', "[t_type]", layer = -EARS_LAYER) + apply_overlay(EARS_LAYER) /mob/living/carbon/human/update_inv_shoes(var/update_icons=1) - + remove_overlay(SHOES_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_shoes] if(inv) @@ -835,13 +740,13 @@ var/global/list/damage_icon_parts = list() shoes.screen_loc = ui_shoes //...draw the item in the inventory screen client.screen += shoes //Either way, add the item to the HUD - var/image/standing + var/mutable_appearance/standing if(shoes.icon_override) - standing = image("icon" = shoes.icon_override, "icon_state" = "[shoes.icon_state]") + standing = mutable_appearance(shoes.icon_override, "[shoes.icon_state]", layer = -SHOES_LAYER) else if(shoes.sprite_sheets && shoes.sprite_sheets[dna.species.name]) - standing = image("icon" = shoes.sprite_sheets[dna.species.name], "icon_state" = "[shoes.icon_state]") + standing = mutable_appearance(shoes.sprite_sheets[dna.species.name], "[shoes.icon_state]", layer = -SHOES_LAYER) else - standing = image("icon" = 'icons/mob/feet.dmi', "icon_state" = "[shoes.icon_state]") + standing = mutable_appearance('icons/mob/feet.dmi', "[shoes.icon_state]", layer = -SHOES_LAYER) if(shoes.blood_DNA) @@ -851,15 +756,13 @@ var/global/list/damage_icon_parts = list() overlays_standing[SHOES_LAYER] = standing else if(feet_blood_DNA) - var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "shoeblood") + var/mutable_appearance/bloodsies = mutable_appearance(dna.species.blood_mask, "shoeblood", layer = -SHOES_LAYER) bloodsies.color = feet_blood_color overlays_standing[SHOES_LAYER] = bloodsies - else - overlays_standing[SHOES_LAYER] = null - if(update_icons) update_icons() + apply_overlay(SHOES_LAYER) /mob/living/carbon/human/update_inv_s_store(var/update_icons=1) - + remove_overlay(SUIT_STORE_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_s_store] if(inv) @@ -874,42 +777,37 @@ var/global/list/damage_icon_parts = list() if(!t_state) t_state = s_store.icon_state var/dmi='icons/mob/belt_mirror.dmi' - overlays_standing[SUIT_STORE_LAYER] = image("icon" = dmi, "icon_state" = "[t_state]") + overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(dmi, "[t_state]", layer = -SUIT_STORE_LAYER) s_store.screen_loc = ui_sstore1 //TODO - else - overlays_standing[SUIT_STORE_LAYER] = null - if(update_icons) update_icons() + apply_overlay(SUIT_STORE_LAYER) /mob/living/carbon/human/update_inv_head(var/update_icons=1) ..() + remove_overlay(HEAD_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_head] if(inv) inv.update_icon() if(head) - var/image/standing + var/mutable_appearance/standing if(head.icon_override) - standing = image("icon" = head.icon_override, "icon_state" = "[head.icon_state]") + standing = mutable_appearance(head.icon_override, "[head.icon_state]", layer = -HEAD_LAYER) else if(head.sprite_sheets && head.sprite_sheets[dna.species.name]) - standing = image("icon" = head.sprite_sheets[dna.species.name], "icon_state" = "[head.icon_state]") + standing = mutable_appearance(head.sprite_sheets[dna.species.name], "[head.icon_state]", layer = -HEAD_LAYER) else - standing = image("icon" = 'icons/mob/head.dmi', "icon_state" = "[head.icon_state]") + standing = mutable_appearance('icons/mob/head.dmi', "[head.icon_state]", layer = -HEAD_LAYER) if(head.blood_DNA) var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "helmetblood") bloodsies.color = head.blood_color - standing.overlays += bloodsies - overlays_standing[HEAD_LAYER] = standing - - - else - overlays_standing[HEAD_LAYER] = null - if(update_icons) update_icons() + standing.overlays += bloodsies + overlays_standing[HEAD_LAYER] = standing + apply_overlay(HEAD_LAYER) /mob/living/carbon/human/update_inv_belt(var/update_icons=1) - + remove_overlay(BELT_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_belt] if(inv) @@ -921,21 +819,21 @@ var/global/list/damage_icon_parts = list() if(belt) var/t_state = belt.item_state - if(!t_state) t_state = belt.icon_state + if(!t_state) + t_state = belt.icon_state if(belt.icon_override) t_state = "[t_state]_be" - overlays_standing[BELT_LAYER] = image("icon" = belt.icon_override, "icon_state" = "[t_state]") + overlays_standing[BELT_LAYER] = mutable_appearance(belt.icon_override, "[t_state]", layer = -BELT_LAYER) else if(belt.sprite_sheets && belt.sprite_sheets[dna.species.name]) - overlays_standing[BELT_LAYER] = image("icon" = belt.sprite_sheets[dna.species.name], "icon_state" = "[t_state]") + overlays_standing[BELT_LAYER] = mutable_appearance(belt.sprite_sheets[dna.species.name], "[t_state]", layer = -BELT_LAYER) else - overlays_standing[BELT_LAYER] = image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[t_state]") - else - overlays_standing[BELT_LAYER] = null - if(update_icons) update_icons() + overlays_standing[BELT_LAYER] = mutable_appearance('icons/mob/belt.dmi', "[t_state]", layer = -BELT_LAYER) + apply_overlay(BELT_LAYER) /mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) + remove_overlay(SUIT_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit] if(inv) @@ -947,47 +845,37 @@ var/global/list/damage_icon_parts = list() wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen client.screen += wear_suit //Either way, add the item to the HUD - var/image/standing + var/mutable_appearance/standing if(wear_suit.icon_override) - standing = image("icon" = wear_suit.icon_override, "icon_state" = "[wear_suit.icon_state]") + standing = mutable_appearance(wear_suit.icon_override, "[wear_suit.icon_state]", layer = -SUIT_LAYER) else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[dna.species.name]) - standing = image("icon" = wear_suit.sprite_sheets[dna.species.name], "icon_state" = "[wear_suit.icon_state]") + standing = mutable_appearance(wear_suit.sprite_sheets[dna.species.name], "[wear_suit.icon_state]", layer = -SUIT_LAYER) else if(FAT in mutations) if(wear_suit.flags_size & ONESIZEFITSALL) - standing = image("icon" = 'icons/mob/suit_fat.dmi', "icon_state" = "[wear_suit.icon_state]") + standing = mutable_appearance('icons/mob/suit_fat.dmi', "[wear_suit.icon_state]", layer = -SUIT_LAYER) else to_chat(src, "You burst out of \the [wear_suit]!") unEquip(wear_suit) return else - standing = image("icon" = 'icons/mob/suit.dmi', "icon_state" = "[wear_suit.icon_state]") - + standing = mutable_appearance('icons/mob/suit.dmi', "[wear_suit.icon_state]", layer = -SUIT_LAYER) if(wear_suit.breakouttime) drop_l_hand() drop_r_hand() - if(wear_suit.blood_DNA) var/obj/item/clothing/suit/S = wear_suit var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "[S.blood_overlay_type]blood") bloodsies.color = wear_suit.blood_color - standing.overlays += bloodsies + standing.overlays += bloodsies + overlays_standing[SUIT_LAYER] = standing - overlays_standing[SUIT_LAYER] = standing - - update_tail_layer(0) - - else - overlays_standing[SUIT_LAYER] = null - - update_tail_layer(0) - + apply_overlay(SUIT_LAYER) + update_tail_layer(0) update_collar(0) - if(update_icons) update_icons() - /mob/living/carbon/human/update_inv_pockets() if(client && hud_used) var/obj/screen/inventory/inv @@ -1021,6 +909,7 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_inv_wear_mask(var/update_icons = 1) ..() + remove_overlay(FACEMASK_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_mask] if(inv) @@ -1031,107 +920,94 @@ var/global/list/damage_icon_parts = list() if(head_organ.alt_head && head_organ.alt_head != "None") alternate_head = GLOB.alt_heads_list[head_organ.alt_head] - var/image/standing + var/mutable_appearance/standing var/icon/mask_icon = new(wear_mask.icon) if(wear_mask.icon_override) mask_icon = new(wear_mask.icon_override) - standing = image("icon" = wear_mask.icon_override, "icon_state" = "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]") + standing = mutable_appearance(wear_mask.icon_override, "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]", layer = -FACEMASK_LAYER) else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[dna.species.name]) mask_icon = new(wear_mask.sprite_sheets[dna.species.name]) - standing = image("icon" = wear_mask.sprite_sheets[dna.species.name], "icon_state" = "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]") + standing = mutable_appearance(wear_mask.sprite_sheets[dna.species.name], "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]", layer = -FACEMASK_LAYER) else - standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]") + standing = mutable_appearance('icons/mob/mask.dmi', "[wear_mask.icon_state][(alternate_head && ("[wear_mask.icon_state]_[alternate_head.suffix]" in mask_icon.IconStates())) ? "_[alternate_head.suffix]" : ""]", layer = -FACEMASK_LAYER) if(!istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA) var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "maskblood") bloodsies.color = wear_mask.blood_color standing.overlays += bloodsies - overlays_standing[FACEMASK_LAYER] = standing - else - overlays_standing[FACEMASK_LAYER] = null - if(update_icons) update_icons() + overlays_standing[FACEMASK_LAYER] = standing + apply_overlay(FACEMASK_LAYER) /mob/living/carbon/human/update_inv_back(var/update_icons=1) ..() + remove_overlay(BACK_LAYER) if(back) //determine the icon to use - var/icon/standing + var/mutable_appearance/standing if(back.icon_override) - standing = image("icon" = back.icon_override, "icon_state" = "[back.icon_state]") + standing = mutable_appearance(back.icon_override, "[back.icon_state]", layer = -BACK_LAYER) else if(istype(back, /obj/item/rig)) //If this is a rig and a mob_icon is set, it will take species into account in the rig update_icon() proc. var/obj/item/rig/rig = back standing = rig.mob_icon else if(back.sprite_sheets && back.sprite_sheets[dna.species.name]) - standing = image("icon" = back.sprite_sheets[dna.species.name], "icon_state" = "[back.icon_state]") + standing = mutable_appearance(back.sprite_sheets[dna.species.name], "[back.icon_state]", layer = -BACK_LAYER) else - standing = image("icon" = 'icons/mob/back.dmi', "icon_state" = "[back.icon_state]") + standing = mutable_appearance('icons/mob/back.dmi', "[back.icon_state]", layer = -BACK_LAYER) //create the image overlays_standing[BACK_LAYER] = standing - else - overlays_standing[BACK_LAYER] = null - - if(update_icons) update_icons() + apply_overlay(BACK_LAYER) /mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1) - overlays_standing[HANDCUFF_LAYER] = null + remove_overlay(HANDCUFF_LAYER) if(handcuffed) if(istype(handcuffed, /obj/item/restraints/handcuffs/pinkcuffs)) - overlays_standing[HANDCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "pinkcuff1") + overlays_standing[HANDCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "pinkcuff1", layer = -HANDCUFF_LAYER) else - overlays_standing[HANDCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "handcuff1") - - if(update_icons) - update_icons() + overlays_standing[HANDCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "handcuff1", layer = -HANDCUFF_LAYER) + apply_overlay(HANDCUFF_LAYER) /mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1) + remove_overlay(LEGCUFF_LAYER) clear_alert("legcuffed") if(legcuffed) - overlays_standing[LEGCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "legcuff1") + overlays_standing[LEGCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "legcuff1", layer = -LEGCUFF_LAYER) throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = legcuffed) if(m_intent != MOVE_INTENT_WALK) m_intent = MOVE_INTENT_WALK if(hud_used && hud_used.move_intent) hud_used.move_intent.icon_state = "walking" - - else - overlays_standing[LEGCUFF_LAYER] = null - if(update_icons) - update_icons() + apply_overlay(LEGCUFF_LAYER) /mob/living/carbon/human/update_inv_r_hand(var/update_icons=1) ..() + remove_overlay(R_HAND_LAYER) if(r_hand) var/t_state = r_hand.item_state if(!t_state) t_state = r_hand.icon_state - var/image/I = image("icon" = r_hand.righthand_file, "icon_state" = "[t_state]") + var/mutable_appearance/I = mutable_appearance(r_hand.righthand_file, "[t_state]", layer = -R_HAND_LAYER) I = center_image(I, r_hand.inhand_x_dimension, r_hand.inhand_y_dimension) overlays_standing[R_HAND_LAYER] = I - else - overlays_standing[R_HAND_LAYER] = null - if(update_icons) - update_icons() + apply_overlay(R_HAND_LAYER) /mob/living/carbon/human/update_inv_l_hand(var/update_icons=1) ..() + remove_overlay(L_HAND_LAYER) if(l_hand) var/t_state = l_hand.item_state if(!t_state) t_state = l_hand.icon_state - var/image/I = image("icon" = l_hand.lefthand_file, "icon_state" = "[t_state]") + var/mutable_appearance/I = mutable_appearance(l_hand.lefthand_file, "[t_state]", layer = -L_HAND_LAYER) I = center_image(I, l_hand.inhand_x_dimension, l_hand.inhand_y_dimension) overlays_standing[L_HAND_LAYER] = I - else - overlays_standing[L_HAND_LAYER] = null - if(update_icons) - update_icons() + apply_overlay(L_HAND_LAYER) //human HUD updates for items in our inventory @@ -1157,10 +1033,11 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/proc/update_tail_layer(var/update_icons=1) - overlays_standing[TAIL_UNDERLIMBS_LAYER] = null // SEW direction icons, overlayed by LIMBS_LAYER. - overlays_standing[TAIL_LAYER] = null /* This will be one of two things: - If the species' tail is overlapped by limbs, this will be only the N direction icon so tails can still appear on the outside of uniforms and such. - Otherwise, since the user's tail isn't overlapped by limbs, it will be a full icon with all directions. */ + remove_overlay(TAIL_UNDERLIMBS_LAYER) // SEW direction icons, overlayed by LIMBS_LAYER. + remove_overlay(TAIL_LAYER) /* This will be one of two things: + If the species' tail is overlapped by limbs, this will be only the N direction icon so tails + can still appear on the outside of uniforms and such. + Otherwise, since the user's tail isn't overlapped by limbs, it will be a full icon with all directions. */ var/icon/tail_marking_icon var/datum/sprite_accessory/body_markings/tail/tail_marking_style @@ -1184,16 +1061,25 @@ var/global/list/damage_icon_parts = list() under.Insert(new/icon(accessory_s, dir=EAST), dir=EAST) under.Insert(new/icon(accessory_s, dir=WEST), dir=WEST) - overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(under, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) + var/mutable_appearance/underlimbs = mutable_appearance(under, layer = -TAIL_UNDERLIMBS_LAYER) + underlimbs.pixel_x = body_accessory.pixel_x_offset + underlimbs.pixel_y = body_accessory.pixel_y_offset + overlays_standing[TAIL_UNDERLIMBS_LAYER] = underlimbs // Creates a blank icon, and copies accessory_s' north direction sprite into it // before passing that to the tail layer that overlays uniforms and such. var/icon/over = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "accessory_none_s") over.Insert(new/icon(accessory_s, dir=NORTH), dir=NORTH) - overlays_standing[TAIL_LAYER] = image(over, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) + var/mutable_appearance/tail = mutable_appearance(over, layer = -TAIL_LAYER) + tail.pixel_x = body_accessory.pixel_x_offset + tail.pixel_y = body_accessory.pixel_y_offset + overlays_standing[TAIL_LAYER] = tail else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation. - overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) + var/mutable_appearance/tail = mutable_appearance(accessory_s, layer = -TAIL_LAYER) + tail.pixel_x = body_accessory.pixel_x_offset + tail.pixel_y = body_accessory.pixel_y_offset + overlays_standing[TAIL_LAYER] = tail else if(tail && dna.species.bodyflags & HAS_TAIL) //no tailless tajaran if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) @@ -1209,25 +1095,24 @@ var/global/list/damage_icon_parts = list() under.Insert(new/icon(tail_s, dir=EAST), dir=EAST) under.Insert(new/icon(tail_s, dir=WEST), dir=WEST) - overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(under) + overlays_standing[TAIL_UNDERLIMBS_LAYER] = mutable_appearance(under, layer = -TAIL_UNDERLIMBS_LAYER) // Creates a blank icon, and copies accessory_s' north direction sprite into it before passing that to the tail layer that overlays uniforms and such. var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "blank") over.Insert(new/icon(tail_s, dir=NORTH), dir=NORTH) - overlays_standing[TAIL_LAYER] = image(over) + overlays_standing[TAIL_LAYER] = mutable_appearance(over, layer = -TAIL_LAYER) else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation. - overlays_standing[TAIL_LAYER] = image(tail_s) - - if(update_icons) - update_icons() - + overlays_standing[TAIL_LAYER] = mutable_appearance(tail_s, layer = -TAIL_LAYER) + apply_overlay(TAIL_LAYER) + apply_overlay(TAIL_UNDERLIMBS_LAYER) /mob/living/carbon/human/proc/start_tail_wagging(var/update_icons=1) - overlays_standing[TAIL_UNDERLIMBS_LAYER] = null // SEW direction icons, overlayed by LIMBS_LAYER. - overlays_standing[TAIL_LAYER] = null /* This will be one of two things: - If the species' tail is overlapped by limbs, this will be only the N direction icon so tails can still appear on the outside of uniforms and such. - Otherwise, since the user's tail isn't overlapped by limbs, it will be a full icon with all directions. */ + remove_overlay(TAIL_UNDERLIMBS_LAYER) // SEW direction icons, overlayed by LIMBS_LAYER. + remove_overlay(TAIL_LAYER) /* This will be one of two things: + If the species' tail is overlapped by limbs, this will be only the N direction icon so tails + can still appear on the outside of uniforms and such. + Otherwise, since the user's tail isn't overlapped by limbs, it will be a full icon with all directions. */ var/icon/tail_marking_icon var/datum/sprite_accessory/body_markings/tail/tail_marking_style @@ -1252,7 +1137,10 @@ var/global/list/damage_icon_parts = list() under.Insert(new/icon(accessory_s, dir=EAST), dir=EAST) under.Insert(new/icon(accessory_s, dir=WEST), dir=WEST) - overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(under, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) + var/mutable_appearance/underlimbs = mutable_appearance(under, layer = -TAIL_UNDERLIMBS_LAYER) + underlimbs.pixel_x = body_accessory.pixel_x_offset + underlimbs.pixel_y = body_accessory.pixel_y_offset + overlays_standing[TAIL_UNDERLIMBS_LAYER] = underlimbs // Creates a blank icon, and copies accessory_s' north direction sprite into it before passing that to the tail layer that overlays uniforms and such. var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "Vulpkanin_tail_delay") @@ -1260,9 +1148,15 @@ var/global/list/damage_icon_parts = list() over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") over.Insert(new/icon(accessory_s, dir=NORTH), dir=NORTH) - overlays_standing[TAIL_LAYER] = image(over, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) + var/mutable_appearance/tail = mutable_appearance(over, layer = -TAIL_LAYER) + tail.pixel_x = body_accessory.pixel_x_offset + tail.pixel_y = body_accessory.pixel_y_offset + overlays_standing[TAIL_LAYER] = tail else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation. - overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset) + var/mutable_appearance/tail = mutable_appearance(accessory_s, layer = -TAIL_LAYER) + tail.pixel_x = body_accessory.pixel_x_offset + tail.pixel_y = body_accessory.pixel_y_offset + overlays_standing[TAIL_LAYER] = tail else if(tail && dna.species.bodyflags & HAS_TAIL) var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]w_s") @@ -1277,25 +1171,36 @@ var/global/list/damage_icon_parts = list() under.Insert(new/icon(tailw_s, dir=EAST), dir=EAST) under.Insert(new/icon(tailw_s, dir=WEST), dir=WEST) - overlays_standing[TAIL_UNDERLIMBS_LAYER] = image(under) + overlays_standing[TAIL_UNDERLIMBS_LAYER] = mutable_appearance(under, layer = -TAIL_UNDERLIMBS_LAYER) // Creates a blank icon, and copies accessory_s' north direction sprite into it before passing that to the tail layer that overlays uniforms and such. var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") over.Insert(new/icon(tailw_s, dir=NORTH), dir=NORTH) - overlays_standing[TAIL_LAYER] = image(over) + overlays_standing[TAIL_LAYER] = mutable_appearance(over, layer = -TAIL_LAYER) else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation. - overlays_standing[TAIL_LAYER] = image(tailw_s) - - if(update_icons) - update_icons() + overlays_standing[TAIL_LAYER] = mutable_appearance(tailw_s, layer = -TAIL_LAYER) + apply_overlay(TAIL_LAYER) + apply_overlay(TAIL_UNDERLIMBS_LAYER) /mob/living/carbon/human/proc/stop_tail_wagging(var/update_icons=1) - overlays_standing[TAIL_UNDERLIMBS_LAYER] = null - overlays_standing[TAIL_LAYER] = null - + remove_overlay(TAIL_UNDERLIMBS_LAYER) + remove_overlay(TAIL_LAYER) update_tail_layer(update_icons) //just trigger a full update for normal stationary sprites +/mob/living/carbon/human/proc/update_int_organs() + remove_overlay(INTORGAN_LAYER) + + var/list/standing = list() + for(var/organ in internal_organs) + var/obj/item/organ/internal/I = organ + var/render = I.render() + if(render) + standing += render + + overlays_standing[INTORGAN_LAYER] = standing + apply_overlay(INTORGAN_LAYER) + /mob/living/carbon/human/handle_transform_change() ..() update_tail_layer() @@ -1304,8 +1209,9 @@ var/global/list/damage_icon_parts = list() // Suit needs an identically named sprite in icons/mob/collar.dmi // For suits with species_fit and sprite_sheets, an identically named sprite needs to exist in a file like this icons/mob/species/[species_name_here]/collar.dmi. /mob/living/carbon/human/proc/update_collar(var/update_icons=1) + remove_overlay(COLLAR_LAYER) var/icon/C = new('icons/mob/collar.dmi') - var/image/standing = null + var/mutable_appearance/standing = null if(wear_suit) if(wear_suit.icon_override) @@ -1314,28 +1220,39 @@ var/global/list/damage_icon_parts = list() if(fexists(icon_path)) //Just ensuring the nonexistance of a file with the above path won't cause a runtime. var/icon/icon_file = new(icon_path) if(wear_suit.icon_state in icon_file.IconStates()) - standing = image("icon" = icon_file, "icon_state" = "[wear_suit.icon_state]") + standing = mutable_appearance(icon_file, "[wear_suit.icon_state]", layer = -COLLAR_LAYER) else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[dna.species.name]) var/icon_path = "[wear_suit.sprite_sheets[dna.species.name]]" icon_path = "[copytext(icon_path, 1, findtext(icon_path, "/suit.dmi"))]/collar.dmi" //If this file doesn't exist, the end result is that COLLAR_LAYER will be unchanged (empty). if(fexists(icon_path)) //Just ensuring the nonexistance of a file with the above path won't cause a runtime. var/icon/icon_file = new(icon_path) if(wear_suit.icon_state in icon_file.IconStates()) - standing = image("icon" = icon_file, "icon_state" = "[wear_suit.icon_state]") + standing = mutable_appearance(icon_file, "[wear_suit.icon_state]", layer = -COLLAR_LAYER) else if(wear_suit.icon_state in C.IconStates()) - standing = image("icon" = C, "icon_state" = "[wear_suit.icon_state]") + standing = mutable_appearance(C, "[wear_suit.icon_state]", layer = -COLLAR_LAYER) - overlays_standing[COLLAR_LAYER] = standing - - if(update_icons) update_icons() + overlays_standing[COLLAR_LAYER] = standing + apply_overlay(COLLAR_LAYER) /mob/living/carbon/human/proc/update_misc_effects() - misc_effect_overlays.Cut() + remove_overlay(MISC_LAYER) //Begin appending miscellaneous effects. if(eyes_shine()) - misc_effect_overlays += get_eye_shine() //Image layer is specified in get_eye_shine() proc as LIGHTING_LAYER + 1. + overlays_standing[MISC_LAYER] = get_eye_shine() //Image layer is specified in get_eye_shine() proc as LIGHTING_LAYER + 1. + + apply_overlay(MISC_LAYER) + +/mob/living/carbon/human/admin_Freeze(client/admin, skip_overlays = TRUE) + . = ..() + overlays_standing[FROZEN_LAYER] = mutable_appearance(frozen, layer = -FROZEN_LAYER) + apply_overlay(FROZEN_LAYER) + +/mob/living/carbon/human/admin_unFreeze(client/admin, skip_overlays = TRUE) + . = ..() + remove_overlay(FROZEN_LAYER) + /mob/living/carbon/human/proc/force_update_limbs() for(var/obj/item/organ/external/O in bodyparts) @@ -1350,3 +1267,40 @@ var/global/list/damage_icon_parts = list() continue out += overlays_standing[i] return out + +/mob/living/carbon/human/proc/generate_icon_render_key() + var/husk = (HUSK in mutations) + var/fat = (FAT in mutations) + var/hulk = (HULK in mutations) + var/skeleton = (SKELETON in mutations) + + . = "" + + var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) + if(eyes) + . += "[eyes.eye_colour]" + else + . += "#000000" + + for(var/organ_tag in dna.species.has_limbs) + var/obj/item/organ/external/part = bodyparts_by_name[organ_tag] + if(isnull(part)) + . += "0" + else if(part.is_robotic()) + . += "2[part.model ? "-[part.model]" : ""]" + else if(part.status & ORGAN_DEAD) + . += "3" + else + . += "1" + + if(part) + var/datum/species/S = GLOB.all_species[part.dna.species.name] + . += "[S.race_key]" + . += "[part.dna.GetUIState(DNA_UI_GENDER)]" + . += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" + if(part.s_col) + . += "[part.s_col]" + if(part.s_tone) + . += "[part.s_tone]" + + . = "[.][!!husk][!!fat][!!hulk][!!skeleton]" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/slime/life.dm b/code/modules/mob/living/carbon/slime/life.dm index 2f2c05c9452..649ec7b3f00 100644 --- a/code/modules/mob/living/carbon/slime/life.dm +++ b/code/modules/mob/living/carbon/slime/life.dm @@ -218,15 +218,8 @@ if(src.eye_blind) src.SetEyeBlind(0) - if(src.ear_deaf > 0) SetEarDeaf(0) - if(src.ear_damage < 25) - SetEarDamage(0) - src.density = !( src.lying ) - if(src.disabilities & DEAF) - EarDeaf(1) - if(src.eye_blurry > 0) SetEyeBlurry(0) diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm index be25de1ac14..914c810da27 100644 --- a/code/modules/mob/living/carbon/slime/slime.dm +++ b/code/modules/mob/living/carbon/slime/slime.dm @@ -489,4 +489,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 if(istype(toEat, /obj/item/reagent_containers/food/drinks)) return 1 to_chat(user, "This creature does not seem to have a mouth!") - return 0 \ No newline at end of file + return 0 + +/mob/living/carbon/slime/can_hear() + . = TRUE //honestly fuck slimes and organ bullshit \ No newline at end of file diff --git a/code/modules/mob/living/carbon/update_status.dm b/code/modules/mob/living/carbon/update_status.dm index 63d34788a98..22030c78f4b 100644 --- a/code/modules/mob/living/carbon/update_status.dm +++ b/code/modules/mob/living/carbon/update_status.dm @@ -27,3 +27,9 @@ setStaminaLoss(health - 2) handle_hud_icons_health() return + +/mob/living/carbon/can_hear() + . = FALSE + var/obj/item/organ/internal/ears/ears = get_int_organ(/obj/item/organ/internal/ears) + if(istype(ears) && !ears.deaf) + . = TRUE \ No newline at end of file diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 032f46d42dd..d365f30d7d0 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -170,15 +170,6 @@ else if(eye_blurry) //blurry eyes heal slowly AdjustEyeBlurry(-1) - //Ears - if(disabilities & DEAF) //disabled-deaf, doesn't get better on its own - EarDeaf(1) - else - // deafness heals slowly over time, unless ear_damage is over 100 - if(ear_damage < 100) - AdjustEarDamage(-0.05) - AdjustEarDeaf(-1) - //this handles hud updates. Calls update_vision() and handle_hud_icons() /mob/living/proc/handle_regular_hud_updates() if(!client) return 0 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 2a384dec214..bf49d5b2598 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -404,8 +404,7 @@ CureNervous() SetEyeBlind(0) SetEyeBlurry(0) - SetEarDamage(0) - SetEarDeaf(0) + RestoreEars() heal_overall_damage(1000, 1000) ExtinguishMob() fire_stacks = 0 diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index b667dbd15bd..e5bc8582de8 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -330,9 +330,5 @@ return 1 /////////////////////////////////// EAR DAMAGE //////////////////////////////////// - -/mob/living/silicon/SetEarDamage() - return - -/mob/living/silicon/SetEarDeaf() - return +/mob/living/silicon/can_hear() + . = TRUE \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 046d55c4566..df3f185dad4 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -578,9 +578,5 @@ if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates. return -/mob/living/simple_animal/SetEarDamage() - return - -/mob/living/simple_animal/SetEarDeaf() - return - +/mob/living/simple_animal/can_hear() + . = TRUE \ No newline at end of file diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index e9253f78d59..4e5c778b7fb 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -43,10 +43,6 @@ A trippy overlay appears. * Drunk * Essentially what your "BAC" is - the higher it is, the more alcohol you have in you - * EarDamage * - Doesn't do much, but if it's 25+, you go deaf. Heals much slower than other statuses - 0.05 normally - * EarDeaf * - You cannot hear. Prevents EarDamage from healing naturally. * EyeBlind * You cannot see. Prevents EyeBlurry from healing naturally. * EyeBlurry * @@ -115,8 +111,6 @@ var/drowsyness = 0 var/druggy = 0 var/drunk = 0 - var/ear_damage = 0 - var/ear_deaf = 0 var/eye_blind = 0 var/eye_blurry = 0 var/hallucination = 0 @@ -233,30 +227,6 @@ var/new_value = directional_bounded_sum(druggy, amount, bound_lower, bound_upper) return SetDruggy(new_value, updating) -// EAR_DAMAGE - -/mob/living/EarDamage(amount) - SetEarDamage(max(ear_damage, amount)) - -/mob/living/SetEarDamage(amount) - ear_damage = max(amount, 0) - -/mob/living/AdjustEarDamage(amount, bound_lower = 0, bound_upper = INFINITY) - var/new_value = directional_bounded_sum(ear_damage, amount, bound_lower, bound_upper) - SetEarDamage(new_value) - -// EAR_DEAF - -/mob/living/EarDeaf(amount) - SetEarDeaf(max(ear_deaf, amount)) - -/mob/living/SetEarDeaf(amount) - ear_deaf = max(amount, 0) - -/mob/living/AdjustEarDeaf(amount, bound_lower = 0, bound_upper = INFINITY) - var/new_value = directional_bounded_sum(ear_deaf, amount, bound_lower, bound_upper) - SetEarDeaf(new_value) - // EYE_BLIND /mob/living/EyeBlind(amount, updating = TRUE) diff --git a/code/modules/mob/living/update_status.dm b/code/modules/mob/living/update_status.dm index 40d4cdc9cb2..94769baf94b 100644 --- a/code/modules/mob/living/update_status.dm +++ b/code/modules/mob/living/update_status.dm @@ -41,7 +41,7 @@ // Whether the mob can hear things /mob/living/can_hear() - return !(ear_deaf || (disabilities & DEAF)) + . = !(disabilities & DEAF) // Whether the mob is able to see // `information_only` is for stuff that's purely informational - like understanding nonverbal languages, or blindness overlays @@ -137,10 +137,6 @@ SetEyeBlind(eye_blind) if("eye_blurry") SetEyeBlurry(eye_blurry) - if("ear_deaf") - SetEarDeaf(ear_deaf) - if("ear_damage") - SetEarDamage(ear_damage) if("druggy") SetDruggy(druggy) if("maxHealth") diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index bdf93fbd4eb..8beb5352b6a 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -48,7 +48,7 @@ var/gender = NEUTER //Determines if the accessory will be skipped or included in random hair generations // Restrict some styles to specific species - var/list/species_allowed = list("Human", "Slime People") + var/list/species_allowed = list("Human", "Felinid", "Slime People") var/list/models_allowed = list() //Specifies which, if any, hairstyles or markings can be accessed by which prosthetics. Should equal the manufacturing company name in robolimbs.dm. var/list/heads_allowed = null //Specifies which, if any, alt heads a head marking, hairstyle or facial hair style is compatible with. var/list/tails_allowed = null //Specifies which, if any, tails a tail marking is compatible with. @@ -75,7 +75,7 @@ /datum/sprite_accessory/hair/bald name = "Bald" icon_state = "bald" - species_allowed = list("Human", "Unathi", "Vox", "Diona", "Kidan", "Grey", "Plasmaman", "Skeleton", "Vulpkanin", "Tajaran") + species_allowed = list("Human", "Felinid", "Unathi", "Vox", "Diona", "Kidan", "Grey", "Plasmaman", "Skeleton", "Vulpkanin", "Tajaran") glasses_over = 1 /datum/sprite_accessory/hair/short @@ -169,7 +169,7 @@ name = "Pompadour" icon_state = "hair_pompadour" gender = MALE - species_allowed = list("Human", "Slime People", "Unathi") + species_allowed = list("Human", "Felinid", "Slime People", "Unathi") glasses_over = 1 /datum/sprite_accessory/hair/quiff @@ -194,19 +194,19 @@ name = "Beehive" icon_state = "hair_beehive" gender = FEMALE - species_allowed = list("Human", "Slime People", "Unathi") + species_allowed = list("Human", "Felinid", "Slime People", "Unathi") /datum/sprite_accessory/hair/bobcurl name = "Bobcurl" icon_state = "hair_bobcurl" gender = FEMALE - species_allowed = list("Human", "Slime People", "Unathi") + species_allowed = list("Human", "Felinid", "Slime People", "Unathi") /datum/sprite_accessory/hair/bob name = "Bob" icon_state = "hair_bobcut" gender = FEMALE - species_allowed = list("Human", "Slime People", "Unathi") + species_allowed = list("Human", "Felinid", "Slime People", "Unathi") /datum/sprite_accessory/hair/bowl name = "Bowl" @@ -234,7 +234,7 @@ name = "Buzzcut" icon_state = "hair_buzzcut" gender = MALE - species_allowed = list("Human", "Slime People", "Unathi") + species_allowed = list("Human", "Felinid", "Slime People", "Unathi") glasses_over = 1 /datum/sprite_accessory/hair/crew @@ -303,7 +303,7 @@ /datum/sprite_accessory/hair/mohawk name = "Mohawk" icon_state = "hair_d" - species_allowed = list("Human", "Slime People", "Unathi") + species_allowed = list("Human", "Felinid", "Slime People", "Unathi") glasses_over = 1 /datum/sprite_accessory/hair/jensen @@ -338,7 +338,7 @@ /datum/sprite_accessory/hair/spiky name = "Spiky" icon_state = "hair_spikey" - species_allowed = list("Human", "Slime People", "Unathi") + species_allowed = list("Human", "Felinid", "Slime People", "Unathi") glasses_over = 1 /datum/sprite_accessory/hair/kusanagi @@ -1535,7 +1535,7 @@ name = "Shaved" icon_state = "bald" gender = NEUTER - species_allowed = list("Human", "Unathi", "Tajaran", "Skrell", "Vox", "Diona", "Kidan", "Greys", "Vulpkanin", "Slime People") + species_allowed = list("Human", "Felinid", "Unathi", "Tajaran", "Skrell", "Vox", "Diona", "Kidan", "Greys", "Vulpkanin", "Slime People") /datum/sprite_accessory/facial_hair/watson name = "Watson Mustache" @@ -1576,7 +1576,7 @@ /datum/sprite_accessory/facial_hair/elvis name = "Elvis Sideburns" icon_state = "facial_elvis" - species_allowed = list("Human", "Slime People", "Unathi") + species_allowed = list("Human", "Felinid", "Slime People", "Unathi") /datum/sprite_accessory/facial_hair/abe name = "Abraham Lincoln Beard" @@ -1813,7 +1813,7 @@ /datum/sprite_accessory/skin/human name = "Default human skin" icon_state = "default" - species_allowed = list("Human") + species_allowed = list("Human", "Felinid") /datum/sprite_accessory/skin/human/human_tatt01 name = "Tatt01 human skin" @@ -1848,13 +1848,13 @@ /////////////////////////// /datum/sprite_accessory/underwear icon = 'icons/mob/underwear.dmi' - species_allowed = list("Human", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask") + species_allowed = list("Human", "Felinid", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask") gender = NEUTER /datum/sprite_accessory/underwear/nude name = "Nude" icon_state = null - species_allowed = list("Human", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask", "Vox") + species_allowed = list("Human", "Felinid", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask", "Vox") /datum/sprite_accessory/underwear/male gender = MALE @@ -1974,13 +1974,13 @@ //////////////////////////// /datum/sprite_accessory/undershirt icon = 'icons/mob/underwear.dmi' - species_allowed = list("Human", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask") + species_allowed = list("Human", "Felinid", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask") gender = NEUTER /datum/sprite_accessory/undershirt/nude name = "Nude" icon_state = null - species_allowed = list("Human", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask", "Vox") + species_allowed = list("Human", "Felinid", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask", "Vox") //plain color shirts /datum/sprite_accessory/undershirt/shirt_white @@ -2210,13 +2210,13 @@ /////////////////////// /datum/sprite_accessory/socks icon = 'icons/mob/underwear.dmi' - species_allowed = list("Human", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask") + species_allowed = list("Human", "Felinid", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask") gender = NEUTER /datum/sprite_accessory/socks/nude name = "Nude" icon_state = null - species_allowed = list("Human", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask", "Vox") + species_allowed = list("Human", "Felinid", "Unathi", "Diona", "Vulpkanin", "Tajaran", "Kidan", "Grey", "Plasmaman", "Machine", "Skrell", "Slime People", "Skeleton", "Drask", "Vox") /datum/sprite_accessory/socks/white_norm name = "Normal White" @@ -2342,7 +2342,7 @@ /datum/sprite_accessory/head_accessory/none name = "None" - species_allowed = list("Human", "Unathi", "Diona", "Grey", "Kidan", "Machine", "Tajaran", "Vulpkanin", "Skrell", "Slime People", "Skeleton", "Vox") + species_allowed = list("Human", "Felinid", "Unathi", "Diona", "Grey", "Kidan", "Machine", "Tajaran", "Vulpkanin", "Skrell", "Slime People", "Skeleton", "Vox") icon_state = "accessory_none" /datum/sprite_accessory/head_accessory/unathi @@ -2595,7 +2595,7 @@ /datum/sprite_accessory/body_markings/none name = "None" - species_allowed = list("Human", "Unathi", "Diona", "Grey", "Machine", "Tajaran", "Vulpkanin", "Skrell", "Slime People", "Skeleton", "Vox", "Kidan") + species_allowed = list("Human", "Felinid", "Unathi", "Diona", "Grey", "Machine", "Tajaran", "Vulpkanin", "Skrell", "Slime People", "Skeleton", "Vox", "Kidan") icon_state = "accessory_none" /datum/sprite_accessory/body_markings/tiger @@ -2863,7 +2863,7 @@ models_allowed = list("Xion Manufacturing Group alt.") /datum/sprite_accessory/body_markings/tattoo // Tattoos applied post-round startup with tattoo guns in item_defines.dm - species_allowed = list("Human", "Unathi", "Vulpkanin", "Tajaran", "Skrell") + species_allowed = list("Human", "Felinid", "Unathi", "Vulpkanin", "Tajaran", "Skrell") icon_state = "accessory_none" /datum/sprite_accessory/body_markings/tattoo/elliot @@ -2873,7 +2873,7 @@ /datum/sprite_accessory/body_markings/tattoo/tiger_body name = "Tiger-stripe Tattoo" - species_allowed = list("Human", "Unathi", "Vulpkanin", "Tajaran", "Skrell") + species_allowed = list("Human", "Felinid", "Unathi", "Vulpkanin", "Tajaran", "Skrell") icon_state = "markings_tiger" /datum/sprite_accessory/body_markings/tattoo/heart diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index 4cbbe9c51c9..f6e6e07673f 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -52,23 +52,13 @@ return -/mob/proc/EarDamage() - return - -/mob/proc/SetEarDamage() +/mob/proc/RestoreEars() return /mob/proc/AdjustEarDamage() return - -/mob/proc/EarDeaf() - return - -/mob/proc/SetEarDeaf() - return - -/mob/proc/AdjustEarDeaf() +/mob/proc/MinimumDeafTicks() return diff --git a/code/modules/mob/update_status.dm b/code/modules/mob/update_status.dm index 52a6fb7769d..446c2aaed8f 100644 --- a/code/modules/mob/update_status.dm +++ b/code/modules/mob/update_status.dm @@ -35,7 +35,7 @@ // Procs that give information about the status of the mob /mob/proc/can_hear() - return 1 + . = 1 /mob/proc/has_vision(information_only = FALSE) return 1 diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index 7007643e652..7a211780446 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -543,21 +543,23 @@ /datum/reagent/medicine/oculine/on_mob_life(mob/living/M) var/update_flags = STATUS_UPDATE_NONE if(prob(80)) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes) + if(iscarbon(M)) + var/mob/living/carbon/C = M + var/obj/item/organ/internal/eyes/E = C.get_int_organ(/obj/item/organ/internal/eyes) if(istype(E)) E.heal_internal_damage(1) + var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears) + if(istype(ears)) + ears.AdjustEarDamage(-1) + if(ears.ear_damage < 25 && prob(30)) + ears.deaf = 0 update_flags |= M.AdjustEyeBlurry(-1, FALSE) - update_flags |= M.AdjustEarDamage(-1, FALSE) + update_flags |= M.AdjustEarDamage(-1) if(prob(50)) update_flags |= M.CureNearsighted(FALSE) if(prob(30)) update_flags |= M.CureBlind(FALSE) update_flags |= M.SetEyeBlind(0, FALSE) - if(M.ear_damage <= 25) - if(prob(30)) - M.SetEarDeaf(0) return ..() | update_flags /datum/reagent/medicine/atropine diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 7dcdd1e81b6..8739acc9664 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -283,16 +283,19 @@ datum/chemical_reaction/flash_powder if(!ear_safety) M.Stun(max(10/distance, 3)) M.Weaken(max(10/distance, 3)) - M.AdjustEarDamage(rand(0, 5)) - M.EarDeaf(15) - if(M.ear_damage >= 15) - to_chat(M, "Your ears start to ring badly!") - if(prob(M.ear_damage - 5)) - to_chat(M, "You can't hear anything!") - M.disabilities |= DEAF - else - if(M.ear_damage >= 5) - to_chat(M, "Your ears start to ring!") + M.AdjustEarDamage(rand(0, 5), 15) + if(iscarbon(M)) + var/mob/living/carbon/C = M + var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears) + if(istype(ears)) + if(ears.ear_damage >= 15) + to_chat(M, "Your ears start to ring badly!") + if(prob(ears.ear_damage - 5)) + to_chat(M, "You can't hear anything!") + M.BecomeDeaf() + else + if(ears.ear_damage >= 5) + to_chat(M, "Your ears start to ring!") holder.remove_reagent("sonic_powder", created_volume) /datum/chemical_reaction/sonic_powder_deafen @@ -318,16 +321,20 @@ datum/chemical_reaction/flash_powder if(!ear_safety) M.Stun(max(10/distance, 3)) M.Weaken(max(10/distance, 3)) - M.AdjustEarDamage(rand(0, 5)) - M.EarDeaf(15) - if(M.ear_damage >= 15) - to_chat(M, "Your ears start to ring badly!") - if(prob(M.ear_damage - 5)) - to_chat(M, "You can't hear anything!") - M.BecomeDeaf() - else - if(M.ear_damage >= 5) - to_chat(M, "Your ears start to ring!") + M.AdjustEarDamage(rand(0, 5), 15) + if(iscarbon(M)) + var/mob/living/carbon/C = M + var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears) + if(istype(ears)) + if(ears.ear_damage >= 15) + to_chat(M, "Your ears start to ring badly!") + if(prob(ears.ear_damage - 5)) + to_chat(M, "You can't hear anything!") + M.BecomeDeaf() + else + if(ears.ear_damage >= 5) + to_chat(M, "Your ears start to ring!") + /datum/chemical_reaction/phlogiston name = "phlogiston" diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm new file mode 100644 index 00000000000..20179905f23 --- /dev/null +++ b/code/modules/surgery/organs/ears.dm @@ -0,0 +1,76 @@ +/obj/item/organ/internal/ears + name = "ears" + icon_state = "ears" + gender = PLURAL + organ_tag = "ears" + parent_organ = "head" + slot = "ears" + + // `deaf` measures "ticks" of deafness. While > 0, the person is deaf. + var/deaf = 0 + + // `ear_damage` measures long term damage to the ears, if too high, + // the person will not have either `deaf` or `ear_damage` decrease + // without external aid (earmuffs, drugs) + var/ear_damage = 0 + +/obj/item/organ/internal/ears/on_life() + if(!iscarbon(owner)) + return + var/mob/living/carbon/C = owner + // genetic deafness prevents the body from using the ears, even if healthy + if(C.disabilities & DEAF) + deaf = max(deaf, 1) + else + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if((H.l_ear && H.l_ear.flags_2 & HEALS_EARS_2) || (H.r_ear && H.r_ear.flags_2 & HEALS_EARS_2)) + deaf = max(deaf - 1, 1) + ear_damage = max(ear_damage - 0.10, 0) + // if higher than UNHEALING_EAR_DAMAGE, no natural healing occurs. + if(ear_damage < UNHEALING_EAR_DAMAGE) + ear_damage = max(ear_damage - 0.05, 0) + deaf = max(deaf - 1, 0) + +/obj/item/organ/internal/ears/proc/RestoreEars() + deaf = 0 + ear_damage = 0 + + var/mob/living/carbon/C = owner + if(istype(C) && C.disabilities & DEAF) + deaf = 1 + +/obj/item/organ/internal/ears/proc/AdjustEarDamage(ddmg, ddeaf) + ear_damage = max(ear_damage + ddmg, 0) + deaf = max(deaf + ddeaf, 0) + +/obj/item/organ/internal/ears/proc/MinimumDeafTicks(value) + deaf = max(deaf, value) + +// Mob procs +/mob/living/carbon/RestoreEars() + var/obj/item/organ/internal/ears/ears = get_int_organ(/obj/item/organ/internal/ears) + if(ears) + ears.RestoreEars() + +/mob/living/carbon/AdjustEarDamage(ddmg, ddeaf) + var/obj/item/organ/internal/ears/ears = get_int_organ(/obj/item/organ/internal/ears) + if(ears) + ears.AdjustEarDamage(ddmg, ddeaf) + +/mob/living/carbon/MinimumDeafTicks(value) + var/obj/item/organ/internal/ears/ears = get_int_organ(/obj/item/organ/internal/ears) + if(ears) + ears.MinimumDeafTicks(value) + + +// Kitty ears!! +/obj/item/organ/internal/ears/cat + name = "cat ears" + icon = 'icons/obj/clothing/hats.dmi' + icon_state = "kitty" + color = "#aa4444" + transform = matrix(0.7, 0, 0, 0, 0.7, 0) + +/obj/item/organ/internal/ears/cat/render() + . = mutable_appearance('icons/mob/head.dmi', "kitty", layer = -HEAD_ACC_OVER_LAYER) \ No newline at end of file diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 4858435cc5f..2dbf85a3b45 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -64,6 +64,7 @@ log_runtime(EXCEPTION("[src] attempted to remove from a [parent_organ], but [parent_organ] didn't exist! [atom_loc_line(M)]"), src) else parent.internal_organs -= src + H.update_int_organs() for(var/X in actions) var/datum/action/A = X @@ -105,6 +106,10 @@ insert(H) return 1 +// Rendering! +/obj/item/organ/internal/proc/render() + return + /obj/item/reagent_containers/food/snacks/organ name = "appendix" icon_state = "appendix" @@ -247,7 +252,7 @@ to_chat(owner, "HONK") owner.SetSleeping(0) owner.Stuttering(20) - owner.AdjustEarDeaf(30) + owner.MinimumDeafTicks(30) owner.Weaken(3) owner << 'sound/items/AirHorn.ogg' if(prob(30)) diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index c13c4da83f6..eedcb52be00 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -122,7 +122,7 @@ var/static/regex/multispin_words = regex("like a record baby") var/mob/living/list/listeners = list() for(var/mob/living/L in get_mobs_in_view(8, owner, TRUE)) - if(!L.ear_deaf && !L.null_rod_check() && L != owner && L.stat != DEAD) + if(L.can_hear() && !L.null_rod_check() && L != owner && L.stat != DEAD) if(ishuman(L)) var/mob/living/carbon/human/H = L if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs)) diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 6a2114514665b92cd19c24006c1bdcafeeda5df9..4ff367c4cc399dbc73ab2ede199eb0400289aa19 100644 GIT binary patch delta 17424 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 delta 16831 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 NNh!T4lrZ%Ee*m2uq<;Va diff --git a/paradise.dme b/paradise.dme index dfe436fd566..f49173cf856 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2244,6 +2244,7 @@ #include "code\modules\surgery\organs\autoimplanter.dm" #include "code\modules\surgery\organs\blood.dm" #include "code\modules\surgery\organs\body_egg.dm" +#include "code\modules\surgery\organs\ears.dm" #include "code\modules\surgery\organs\eyes.dm" #include "code\modules\surgery\organs\heart.dm" #include "code\modules\surgery\organs\helpers.dm"