Reworks on-mob overlay icon generation. (#8920)

* Porting species equip_adjust from Neb.

* get_species() => get_species_name(), adds correct get_species() impl

* sprite_sheets is now crudely lazylisted.

* Adds returns to add_blood and add_accessories.

* apply_addblends now uses an overlay.

* Renames the various worn overlay procs to be more informative.

* Debugging/refining overlay gen.

* Adding handling for string icon paths.

* Refining/debugging offset overlay gen.

* Getting the offset system working.

* Commenting out Teshari offsets for the time being.
This commit is contained in:
MistakeNot4892
2023-02-16 13:22:42 +11:00
committed by GitHub
parent 781fe82a78
commit 9a84667323
25 changed files with 268 additions and 143 deletions

View File

@@ -111,24 +111,27 @@
#define MAX_SUPPLIED_LAW_NUMBER 50
//default item on-mob icons
#define INV_HEAD_DEF_ICON 'icons/mob/head.dmi'
#define INV_BACK_DEF_ICON 'icons/mob/back.dmi'
#define INV_L_HAND_DEF_ICON 'icons/mob/items/lefthand.dmi'
#define INV_R_HAND_DEF_ICON 'icons/mob/items/righthand.dmi'
#define INV_W_UNIFORM_DEF_ICON "icons/mob/uniform"
#define INV_W_UNIFORM_DEF_STRING "icons/mob/uniform"
#define INV_SUIT_DEF_STRING "icons/mob/suit"
#define INV_HEAD_DEF_ICON 'icons/mob/head.dmi'
#define INV_BACK_DEF_ICON 'icons/mob/back.dmi'
#define INV_L_HAND_DEF_ICON 'icons/mob/items/lefthand.dmi'
#define INV_R_HAND_DEF_ICON 'icons/mob/items/righthand.dmi'
#define INV_W_UNIFORM_DEF_ICON 'icons/mob/uniform.dmi'
#define INV_ACCESSORIES_DEF_ICON 'icons/mob/ties.dmi'
#define INV_TIE_DEF_ICON 'icons/mob/ties.dmi'
#define INV_SUIT_DEF_ICON "icons/mob/suit"
#define INV_SPACESUIT_DEF_ICON 'icons/mob/spacesuit.dmi'
#define INV_WEAR_ID_DEF_ICON 'icons/mob/mob.dmi'
#define INV_GLOVES_DEF_ICON 'icons/mob/hands.dmi'
#define INV_EYES_DEF_ICON 'icons/mob/eyes.dmi'
#define INV_EARS_DEF_ICON 'icons/mob/ears.dmi'
#define INV_FEET_DEF_ICON 'icons/mob/feet.dmi'
#define INV_BELT_DEF_ICON 'icons/mob/belt.dmi'
#define INV_MASK_DEF_ICON 'icons/mob/mask.dmi'
#define INV_HCUFF_DEF_ICON 'icons/mob/mob.dmi'
#define INV_LCUFF_DEF_ICON 'icons/mob/mob.dmi'
#define INV_TIE_DEF_ICON 'icons/mob/ties.dmi'
#define INV_SUIT_DEF_ICON 'icons/mob/suit.dmi'
#define INV_SPACESUIT_DEF_ICON 'icons/mob/spacesuit.dmi'
#define INV_WEAR_ID_DEF_ICON 'icons/mob/mob.dmi'
#define INV_GLOVES_DEF_ICON 'icons/mob/hands.dmi'
#define INV_EYES_DEF_ICON 'icons/mob/eyes.dmi'
#define INV_EARS_DEF_ICON 'icons/mob/ears.dmi'
#define INV_FEET_DEF_ICON 'icons/mob/feet.dmi'
#define INV_BELT_DEF_ICON 'icons/mob/belt.dmi'
#define INV_MASK_DEF_ICON 'icons/mob/mask.dmi'
#define INV_HCUFF_DEF_ICON 'icons/mob/mob.dmi'
#define INV_LCUFF_DEF_ICON 'icons/mob/mob.dmi'
// Character's economic class
#define CLASS_UPPER "Wealthy"

View File

@@ -1033,3 +1033,21 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
//Animate it growing
animate(img, alpha = 0, transform = matrix()*grow_to, time = anim_duration, loop = loops)
// For checking if we have a specific state, for inventory icons and nonhumanoid species.
// Cached cause asking icons is expensive. This is still expensive, so avoid using it if
// you can reasonably expect the icon_state to exist beforehand, or if you can cache the
// value somewhere.
var/global/list/_icon_state_cache = list()
/proc/check_state_in_icon(var/checkstate, var/checkicon, var/high_accuracy = FALSE)
// isicon() is apparently quite expensive so short-circuit out early if we can.
if(!istext(checkstate) || isnull(checkicon) || !(isfile(checkicon) || isicon(checkicon)))
return FALSE
var/checkkey = "\ref[checkicon]"
var/list/check = global._icon_state_cache[checkkey]
if(!check)
check = list()
for(var/istate in icon_states(checkicon))
check[istate] = TRUE
global._icon_state_cache[checkkey] = check
. = check[checkstate]

View File

@@ -341,7 +341,7 @@ var/global/list/PDA_Manifest = list()
G.fields["p_stat"] = "Active"
G.fields["m_stat"] = "Stable"
G.fields["sex"] = gender2text(H.gender)
G.fields["species"] = H.get_species()
G.fields["species"] = H.get_species_name()
G.fields["home_system"] = H.home_system
G.fields["citizenship"] = H.citizenship
G.fields["faction"] = H.personal_faction
@@ -387,7 +387,7 @@ var/global/list/PDA_Manifest = list()
L.fields["b_dna"] = H.dna.unique_enzymes
L.fields["enzymes"] = H.dna.SE // Used in respawning
L.fields["identity"] = H.dna.UI // "
L.fields["species"] = H.get_species()
L.fields["species"] = H.get_species_name()
L.fields["home_system"] = H.home_system
L.fields["citizenship"] = H.citizenship
L.fields["faction"] = H.personal_faction

View File

@@ -72,7 +72,7 @@
general.fields["name"] = user.real_name
general.fields["sex"] = capitalize(user.gender)
general.fields["species"] = user.get_species()
general.fields["species"] = user.get_species_name()
var/datum/data/record/medical = data_core.CreateMedicalRecord(general.fields["name"], general.fields["id"])
data_core.CreateSecurityRecord(general.fields["name"], general.fields["id"])
@@ -112,4 +112,3 @@
var/datum/event_meta/EM = new(EVENT_LEVEL_MUNDANE, "Fake Radiation Storm", add_to_queue = 0)
new/datum/event/radiation_storm/syndicate(EM)
return 1

View File

@@ -775,11 +775,17 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
return FALSE
//Worn icon generation for on-mob sprites
/obj/item/proc/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer,var/icon/clip_mask = null)
/obj/item/proc/get_worn_overlay(var/mob/living/wearer, var/body_type, var/slot_name, var/inhands, var/default_icon, var/default_layer, var/icon/clip_mask)
//Get the required information about the base icon
var/icon/icon2use = get_worn_icon_file(body_type = body_type, slot_name = slot_name, default_icon = default_icon, inhands = inhands)
var/datum/species/species = wearer.get_species()
var/state2use = get_worn_icon_state(slot_name = slot_name)
var/icon2use = get_worn_icon_file(body_type = body_type, slot_name = slot_name, default_icon = default_icon, inhands = inhands, check_state = state2use)
var/layer2use = get_worn_layer(default_layer = default_layer)
var/using_spritesheet = !inhands && (icon2use == LAZYACCESS(sprite_sheets, body_type))
if(istext(icon2use))
icon2use = resolve_text_icon(icon2use)
//Snowflakey inhand icons in a specific slot
if(inhands && icon2use == icon_override)
@@ -789,60 +795,60 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
if(slot_l_hand_str)
state2use += "_l"
// testing("[src] (\ref[src]) - Slot: [slot_name], Inhands: [inhands], Worn Icon:[icon2use], Worn State:[state2use], Worn Layer:[layer2use]")
var/image/standing
if(!using_spritesheet && species)
standing = species.get_offset_overlay_image(icon2use, state2use, color, slot_name, layer2use)
if(!standing)
standing = overlay_image(icon2use, state2use, color, layer2use, RESET_COLOR)
//Generate the base onmob icon
var/icon/standing_icon = icon(icon = icon2use, icon_state = state2use)
if(alpha != 255)
standing.alpha = alpha
if(!inhands)
apply_custom(standing_icon) //Pre-image overridable proc to customize the thing
apply_addblends(icon2use,standing_icon) //Some items have ICON_ADD blend shaders
var/image/standing = image(standing_icon)
standing.alpha = alpha
standing.color = color
standing.layer = layer2use
apply_custom_to_worn_overlay(standing) // Overridable proc to customize the overlay.
apply_addblends_to_worn_overlay(standing, icon2use) // Some items add overlays/shaders.
if(istype(clip_mask)) //For tails clipping off parts of uniforms and suits.
standing.filters += filter(type = "alpha", icon = clip_mask)
//Apply any special features
if(!inhands)
apply_blood(standing) //Some items show blood when bloodied
apply_accessories(standing) //Some items sport accessories like webbing
apply_blood_to_worn_overlay(standing) //Some items show blood when bloodied
apply_accessories_to_worn_overlay(standing) //Some items sport accessories like webbing
//Return our icon
//testing("[src] (\ref[src]) - Spritesheet: [using_spritesheet], Slot: [slot_name], Inhands: [inhands], Worn Icon:[icon2use], Worn State:[state2use], Worn Layer:[layer2use], Standing:[standing ? "\ref[standing]" : "null"] ([standing?.icon || "no icon"], [standing?.icon_state || "no state"])")
//Return our overlay
return standing
//Returns the icon object that should be used for the worn icon
/obj/item/proc/get_worn_icon_file(var/body_type,var/slot_name,var/default_icon,var/inhands)
/obj/item/proc/get_worn_icon_file(var/body_type, var/slot_name, var/default_icon, var/inhands, var/check_state)
//1: icon_override var
if(icon_override)
return icon_override
//2: species-specific sprite sheets (skipped for inhands)
if(LAZYLEN(sprite_sheets))
var/sheet = sprite_sheets[body_type]
if(sheet && !inhands)
return sheet
if(!inhands)
var/sheet = LAZYACCESS(sprite_sheets, body_type)
if(sheet)
if(!check_state)
return sheet
sheet = resolve_text_icon(sheet)
if(check_state_in_icon(check_state, sheet))
return sheet
//3: slot-specific sprite sheets
if(LAZYLEN(item_icons))
var/sheet = item_icons[slot_name]
if(sheet)
return sheet
var/sheet = LAZYACCESS(item_icons, slot_name)
if(sheet)
return sheet
//4: item's default icon
if(default_worn_icon)
return default_worn_icon
//5: provided default_icon
if(default_icon)
return default_icon
//6: give up
return
return default_icon
//Returns the state that should be used for the worn icon
/obj/item/proc/get_worn_icon_state(var/slot_name)
@@ -872,23 +878,24 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
return BODY_LAYER+default_layer
//Apply the addblend blends onto the icon
/obj/item/proc/apply_addblends(var/source_icon, var/icon/standing_icon)
/obj/item/proc/apply_addblends_to_worn_overlay(var/image/standing, var/icon/source_icon)
//If we have addblends, blend them onto the provided icon
if(addblends && standing_icon && source_icon)
var/addblend_icon = icon("icon" = source_icon, "icon_state" = addblends)
standing_icon.Blend(addblend_icon, ICON_ADD)
//STUB
/obj/item/proc/apply_custom(var/icon/standing_icon)
return standing_icon
//STUB
/obj/item/proc/apply_blood(var/image/standing)
if(addblends && standing && source_icon)
var/image/I = image(source_icon, addblends)
I.blend_mode = BLEND_ADD
standing.overlays += I
return standing
//STUB
/obj/item/proc/apply_accessories(var/image/standing)
/obj/item/proc/apply_custom_to_worn_overlay(var/image/standing)
return standing
//STUB
/obj/item/proc/apply_blood_to_worn_overlay(var/image/standing)
return standing
//STUB
/obj/item/proc/apply_accessories_to_worn_overlay(var/image/standing)
return standing
/obj/item/MouseEntered(location,control,params)

View File

@@ -72,7 +72,7 @@
if(istype(I, /obj/item/clothing/accessory/storage/poncho))
var/obj/item/clothing/accessory/storage/poncho/P = I
P.icon_override_state = new_icon_override_file
P.sprite_sheets[SPECIES_TESHARI] = new_icon_override_file /// Will look the same on teshari and other species.
LAZYSET(P.sprite_sheets, SPECIES_TESHARI, new_icon_override_file) /// Will look the same on teshari and other species.
P.item_state = new_icon
to_chat(user, "You set about modifying the poncho into [new_name].")
return ..()
@@ -84,7 +84,7 @@
/obj/item/kit/clothing/customize(var/obj/item/clothing/I, var/mob/user)
if(istype(I) && can_customize(I))
I.sprite_sheets[SPECIES_TESHARI] = new_icon_override_file /// Will look the same on teshari and other species.
LAZYSET(I.sprite_sheets, SPECIES_TESHARI, new_icon_override_file) /// Will look the same on teshari and other species.
I.item_state = new_icon
return ..()

View File

@@ -26,7 +26,7 @@
update_icon()
//Some belts have sprites to show icons
/obj/item/storage/belt/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer = 0,var/icon/clip_mask = null)
/obj/item/storage/belt/get_worn_overlay(var/mob/living/wearer, var/body_type, var/slot_name, var/inhands, var/default_icon, var/default_layer, var/icon/clip_mask)
var/image/standing = ..()
if(!inhands && contents.len)
for(var/obj/item/i in contents)

View File

@@ -1,3 +1,5 @@
var/global/list/light_overlay_cache = list() //see get_worn_overlay() on helmets and /obj/item/clothing/head/update_icon()
/obj/item/clothing
name = "clothing"
siemens_coefficient = 0.9
@@ -153,7 +155,7 @@
//Set icon
if (sprite_sheets_refit && (target_species in sprite_sheets_refit))
sprite_sheets[target_species] = sprite_sheets_refit[target_species]
LAZYSET(sprite_sheets, target_species, sprite_sheets_refit[target_species])
if (sprite_sheets_obj && (target_species in sprite_sheets_obj))
icon = sprite_sheets_obj[target_species]
@@ -174,7 +176,7 @@
//Set icon
if (sprite_sheets_refit && (target_species in sprite_sheets_refit))
sprite_sheets[target_species] = sprite_sheets_refit[target_species]
LAZYSET(sprite_sheets, target_species, sprite_sheets_refit[target_species])
if (sprite_sheets_obj && (target_species in sprite_sheets_obj))
icon = sprite_sheets_obj[target_species]
@@ -514,7 +516,7 @@
// Generate and cache the on-mob icon, which is used in update_inv_head().
var/body_type = (H && H.species.get_bodytype(H))
var/cache_key = "[light_overlay][body_type && sprite_sheets[body_type] ? "_[body_type]" : ""]"
var/cache_key = "[light_overlay][body_type && LAZYACCESS(sprite_sheets, body_type) ? "_[body_type]" : ""]"
if(!light_overlay_cache[cache_key])
var/use_icon = LAZYACCESS(sprite_sheets,body_type) || 'icons/mob/light_overlays.dmi'
light_overlay_cache[cache_key] = image(icon = use_icon, icon_state = "[light_overlay]")
@@ -863,14 +865,15 @@
/obj/item/clothing/under/proc/update_rolldown_status()
var/mob/living/carbon/human/H
if(istype(src.loc, /mob/living/carbon/human))
H = src.loc
if(ishuman(loc))
H = loc
var/icon/under_icon
var/body_type = H?.species.get_bodytype(H)
if(icon_override)
under_icon = icon_override
else if(H && sprite_sheets && sprite_sheets[H.species.get_bodytype(H)])
under_icon = sprite_sheets[H.species.get_bodytype(H)]
else if(body_type && LAZYACCESS(sprite_sheets, body_type))
under_icon = LAZYACCESS(sprite_sheets, body_type)
else if(item_icons && item_icons[slot_w_uniform_str])
under_icon = item_icons[slot_w_uniform_str]
else if ("[worn_state]_s" in cached_icon_states(rolled_down_icon))
@@ -886,20 +889,21 @@
/obj/item/clothing/under/proc/update_rollsleeves_status()
var/mob/living/carbon/human/H
if(istype(src.loc, /mob/living/carbon/human))
H = src.loc
if(ishuman(loc))
H = loc
var/icon/under_icon
var/body_type = H?.species.get_bodytype(H)
if(icon_override)
under_icon = icon_override
else if(H && sprite_sheets && sprite_sheets[H.species.get_bodytype(H)])
under_icon = sprite_sheets[H.species.get_bodytype(H)]
else if(H && LAZYACCESS(sprite_sheets, body_type))
under_icon = LAZYACCESS(sprite_sheets, body_type)
else if(item_icons && item_icons[slot_w_uniform_str])
under_icon = item_icons[slot_w_uniform_str]
else if ("[worn_state]_s" in cached_icon_states(rolled_down_sleeves_icon))
under_icon = rolled_down_sleeves_icon
else if(index)
under_icon = new /icon("[INV_W_UNIFORM_DEF_ICON]_[index].dmi")
under_icon = new /icon("[INV_W_UNIFORM_DEF_STRING]_[index].dmi")
// The _s is because the icon update procs append it.
if((under_icon == rolled_down_sleeves_icon && ("[worn_state]_s" in cached_icon_states(under_icon))) || ("[worn_state]_r_s" in cached_icon_states(under_icon)))
@@ -907,7 +911,8 @@
rolled_sleeves = 0
else
rolled_sleeves = -1
if(H) update_clothing_icon()
if(H)
update_clothing_icon()
/obj/item/clothing/under/update_clothing_icon()
if (ismob(src.loc))

View File

@@ -1,35 +1,36 @@
/obj/item/clothing/apply_accessories(var/image/standing)
/obj/item/clothing/apply_accessories_to_worn_overlay(var/image/standing)
if(LAZYLEN(accessories))
for(var/obj/item/clothing/accessory/A in accessories)
standing.add_overlay(A.get_mob_overlay())
return standing
/obj/item/clothing/apply_blood(var/image/standing)
/obj/item/clothing/apply_blood_to_worn_overlay(var/image/standing)
if(blood_DNA && blood_sprite_state && ishuman(loc))
var/mob/living/carbon/human/H = loc
var/image/bloodsies = image(icon = H.species.get_blood_mask(H), icon_state = blood_sprite_state)
bloodsies.color = blood_color
standing.add_overlay(bloodsies)
return standing
//UNIFORM: Always appends "_s" to iconstate, stupidly.
/obj/item/clothing/under/get_worn_icon_state(var/slot_name)
var/state2use = ..()
state2use += "_s"
return state2use
return "[..()]_s"
//HELMET: May have a lighting overlay
/obj/item/clothing/head/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer = 0,var/icon/clip_mask = null)
/obj/item/clothing/head/get_worn_overlay(var/mob/living/wearer, var/body_type, var/slot_name, var/inhands, var/default_icon, var/default_layer, var/icon/clip_mask)
var/image/standing = ..()
if(on && slot_name == slot_head_str)
if(standing && on && slot_name == slot_head_str)
var/cache_key = "[light_overlay][LAZYACCESS(sprite_sheets,body_type) ? "_[body_type]" : ""]"
if(standing && light_overlay_cache[cache_key])
if(light_overlay_cache[cache_key])
standing.add_overlay(light_overlay_cache[cache_key])
return standing
//SUIT: Blood state is slightly different
/obj/item/clothing/suit/apply_blood(var/image/standing)
/obj/item/clothing/suit/apply_blood_to_worn_overlay(var/image/standing)
if(blood_DNA && blood_sprite_state && ishuman(loc))
var/mob/living/carbon/human/H = loc
blood_sprite_state = "[blood_overlay_type]blood"
var/image/bloodsies = image(icon = H.species.get_blood_mask(H), icon_state = blood_sprite_state)
bloodsies.color = blood_color
standing.add_overlay(bloodsies)
return standing

View File

@@ -200,7 +200,7 @@
M.unEquip(piece)
piece.forceMove(src)
/obj/item/rig/get_worn_icon_file(var/body_type,var/slot_name,var/default_icon,var/inhands)
/obj/item/rig/get_worn_icon_file(var/body_type, var/slot_name, var/default_icon, var/inhands, var/check_state)
if(!inhands && (slot_name == slot_back_str || slot_name == slot_belt_str))
if(icon_override)
return icon_override
@@ -589,8 +589,9 @@
var/species_icon = 'icons/mob/rig_back.dmi'
// Since setting mob_icon will override the species checks in
// update_inv_wear_suit(), handle species checks here.
if(wearer && sprite_sheets && sprite_sheets[wearer.species.get_bodytype(wearer)])
species_icon = sprite_sheets[wearer.species.get_bodytype(wearer)]
var/body_type = wearer?.species.get_bodytype(wearer)
if(wearer && LAZYACCESS(sprite_sheets, body_type))
species_icon = LAZYACCESS(sprite_sheets, body_type)
mob_icon = icon(icon = species_icon, icon_state = "[icon_state]")
if(installed_modules.len)

View File

@@ -53,12 +53,13 @@
else if(on_rolled["rolled"] && C.rolled_sleeves > 0)
tmp_icon_state = on_rolled["rolled"]
var/body_type = wearer.species.get_bodytype(wearer)
if(icon_override)
if("[tmp_icon_state]_mob" in cached_icon_states(icon_override))
tmp_icon_state = "[tmp_icon_state]_mob"
mob_overlay = image("icon" = icon_override, "icon_state" = "[tmp_icon_state]")
else if(wearer && sprite_sheets[wearer.species.get_bodytype(wearer)]) //Teshari can finally into webbing, too!
mob_overlay = image("icon" = sprite_sheets[wearer.species.get_bodytype(wearer)], "icon_state" = "[tmp_icon_state]")
else if(wearer && LAZYACCESS(sprite_sheets, body_type)) //Teshari can finally into webbing, too!
mob_overlay = image("icon" = LAZYACCESS(sprite_sheets, body_type), "icon_state" = "[tmp_icon_state]")
else
mob_overlay = image("icon" = INV_ACCESSORIES_DEF_ICON, "icon_state" = "[tmp_icon_state]")
if(addblends)

View File

@@ -68,7 +68,7 @@
var/mob/living/carbon/human/H = loc
if(istype(H) && H.wear_suit == src)
if(H.species.name == SPECIES_TESHARI)
icon_override = sprite_sheets[SPECIES_TESHARI]
icon_override = LAZYACCESS(sprite_sheets, SPECIES_TESHARI)
else if(icon_override_state)
icon_override = icon_override_state
else
@@ -88,7 +88,7 @@
else if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.species.name == SPECIES_TESHARI)
icon_override = sprite_sheets[SPECIES_TESHARI]
icon_override = LAZYACCESS(sprite_sheets, SPECIES_TESHARI)
else
icon_override = initial(icon_override)

View File

@@ -81,7 +81,7 @@
update_icon()
update_clothing_icon()
/obj/item/clothing/accessory/storage/poncho/crafted/make_worn_icon(var/body_type, var/slot_name, var/inhands, var/default_icon, var/default_layer, var/icon/clip_mask = null)
/obj/item/clothing/accessory/storage/poncho/crafted/get_worn_overlay(var/mob/living/wearer, var/body_type, var/slot_name, var/inhands, var/default_icon, var/default_layer, var/icon/clip_mask)
var/image/standing = ..()
if(standing && slot_name == slot_wear_suit_str)
var/use_icon = LAZYACCESS(sprite_sheets, body_type) || icon_override

View File

@@ -223,7 +223,7 @@ badges
if(!istype(H))
return
var/religion = "Unset"
desc = "[initial(desc)]\nName: [H.real_name] ([H.get_species()])\nReligion: [religion]\nBlood type: [H.b_type]"
desc = "[initial(desc)]\nName: [H.real_name] ([H.get_species_name()])\nReligion: [religion]\nBlood type: [H.b_type]"
/obj/item/clothing/accessory/badge/solgov/representative
name = "representative's badge"

View File

@@ -691,7 +691,7 @@
/mob/living/carbon/human/get_species()
if(!species)
set_species()
return species.name
return species
/mob/living/carbon/human/proc/play_xylophone()
if(!src.xylophone)

View File

@@ -11,9 +11,10 @@
var/list/catalogue_data = null // A list of /datum/category_item/catalogue datums, for the cataloguer, or null.
// Icon/appearance vars.
var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set.
var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set.
var/limb_blend = ICON_ADD // Specify a blending mode for limb colourisation.
var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set.
var/icon_template = 'icons/mob/human_races/template.dmi' // Used for mob icon generation.
var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set.
var/limb_blend = ICON_ADD // Specify a blending mode for limb colourisation.
var/speech_bubble_appearance = "normal" // Part of icon_state to use for speech bubbles when talking. See talk.dmi for available icons.
var/fire_icon_state = "humanoid" // The icon_state used inside OnFire.dmi for when on fire.
@@ -39,7 +40,6 @@
var/icon_scale_y = 1 // Makes the icon taller/shorter.
var/race_key = 0 // Used for mob icon cache string.
var/icon/icon_template // Used for mob icon generation for non-32x32 species.
var/mob_size = MOB_MEDIUM
var/show_ssd = "fast asleep"
var/virus_immune

View File

@@ -0,0 +1,52 @@
/*
These are all the things that can be adjusted for equipping stuff and
each one can be in the NORTH, SOUTH, EAST, and WEST direction. Specify
the direction to shift the thing and what direction.
example:
equip_adjust = list(
slot_back_str = list(NORTH = list(SOUTH = 12, EAST = 7), EAST = list(SOUTH = 2, WEST = 12))
)
This would shift back items (backpacks, axes, etc.) when the mob
is facing either north or east.
When the mob faces north the back item icon is shifted 12 pixes down and 7 pixels to the right.
When the mob faces east the back item icon is shifted 2 pixels down and 12 pixels to the left.
The slots that you can use are found in items_clothing.dm and are the inventory slot string ones, so make sure
you use the _str version of the slot.
*/
/datum/species
var/list/equip_adjust = list()
var/list/equip_overlays = list()
/datum/species/proc/get_offset_overlay_image(var/mob_icon, var/mob_state, var/color = COLOR_WHITE, var/slot, var/layer)
// If we don't actually need to offset this, don't bother with any of the generation/caching.
if(!equip_adjust || !length(equip_adjust[slot]))
return
// Check the cache for previously made icons.
var/image_key = "[mob_icon]-[mob_state]-[color]-[slot]"
if(!equip_overlays[image_key])
// Check if we actually have a state to draw.
if(check_state_in_icon(mob_state, mob_icon))
var/icon/final_I = new(icon_template)
var/list/shifts = equip_adjust[slot]
// Apply all pixel shifts for each direction.
for(var/shift_facing in shifts)
var/list/facing_list = shifts[shift_facing]
var/use_dir = text2num(shift_facing)
var/icon/equip = new(mob_icon, icon_state = mob_state, dir = use_dir)
var/icon/canvas = new(icon_template)
canvas.Blend(equip, ICON_OVERLAY, facing_list["x"]+1, facing_list["y"]+1)
final_I.Insert(canvas, dir = use_dir)
equip_overlays[image_key] = overlay_image(final_I, "", color, FLOAT_LAYER, RESET_COLOR)
else
// Store a blank rather than caching the first state in the icon file as icon() does.
equip_overlays[image_key] = new /image
var/image/I = new() // We return a copy of the cached image, in case downstream procs mutate it.
I.appearance = equip_overlays[image_key]
I.layer = layer
return I

View File

@@ -158,6 +158,26 @@
/decl/emote/audible/teshtrill
)
/*
/datum/species/teshari/New()
equip_adjust = list(
slot_l_ear_str = list("[NORTH]" = list("x" = 1, "y" = -5), "[EAST]" = list("x" = -2, "y" = -5), "[SOUTH]" = list("x" = -1, "y" = -4), "[WEST]" = list("x" = 0, "y" = -5)),
slot_r_ear_str = list("[NORTH]" = list("x" = 1, "y" = -4), "[EAST]" = list("x" = 0, "y" = -5), "[SOUTH]" = list("x" = -1, "y" = -5), "[WEST]" = list("x" = 2, "y" = -5)),
slot_l_hand_str = list("[NORTH]" = list("x" = 3, "y" = -3), "[EAST]" = list("x" = 1, "y" = -3), "[SOUTH]" = list("x" = -3, "y" = -3), "[WEST]" = list("x" = -5, "y" = -3)),
slot_r_hand_str = list("[NORTH]" = list("x" = -3, "y" = -3), "[EAST]" = list("x" = 5, "y" = -3), "[SOUTH]" = list("x" = 3, "y" = -3), "[WEST]" = list("x" = -1, "y" = -3)),
slot_head_str = list("[NORTH]" = list("x" = 0, "y" = -5), "[EAST]" = list("x" = 1, "y" = -5), "[SOUTH]" = list("x" = 0, "y" = -5), "[WEST]" = list("x" = -1, "y" = -5)),
slot_wear_mask_str = list("[NORTH]" = list("x" = 0, "y" = -6), "[EAST]" = list("x" = 2, "y" = -6), "[SOUTH]" = list("x" = 0, "y" = -6), "[WEST]" = list("x" = -2, "y" = -6)),
slot_glasses_str = list("[NORTH]" = list("x" = 0, "y" = -6), "[EAST]" = list("x" = 1, "y" = -6), "[SOUTH]" = list("x" = 0, "y" = -6), "[WEST]" = list("x" = -1, "y" = -6)),
slot_back_str = list("[NORTH]" = list("x" = 0, "y" = -6), "[EAST]" = list("x" = 3, "y" = -6), "[SOUTH]" = list("x" = 0, "y" = -6), "[WEST]" = list("x" = -3, "y" = -6)),
slot_w_uniform_str = list("[NORTH]" = list("x" = 0, "y" = -6), "[EAST]" = list("x" = -1, "y" = -6), "[SOUTH]" = list("x" = 0, "y" = -6), "[WEST]" = list("x" = 1, "y" = -6)),
slot_tie_str = list("[NORTH]" = list("x" = 0, "y" = -5), "[EAST]" = list("x" = 0, "y" = -5), "[SOUTH]" = list("x" = 0, "y" = -5), "[WEST]" = list("x" = 0, "y" = -5)),
slot_wear_id_str = list("[NORTH]" = list("x" = 0, "y" = -6), "[EAST]" = list("x" = -1, "y" = -6), "[SOUTH]" = list("x" = 0, "y" = -6), "[WEST]" = list("x" = 1, "y" = -6)),
slot_wear_suit_str = list("[NORTH]" = list("x" = 0, "y" = -6), "[EAST]" = list("x" = -1, "y" = -6), "[SOUTH]" = list("x" = 0, "y" = -6), "[WEST]" = list("x" = 1, "y" = -6)),
slot_belt_str = list("[NORTH]" = list("x" = 0, "y" = -6), "[EAST]" = list("x" = -1, "y" = -6), "[SOUTH]" = list("x" = 0, "y" = -6), "[WEST]" = list("x" = 1, "y" = -6))
)
. = ..()
*/
/datum/species/teshari/equip_survival_gear(var/mob/living/carbon/human/H)
..()
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),slot_shoes)

View File

@@ -5,9 +5,28 @@
var/global/list/human_icon_cache = list() //key is incredibly complex, see update_icons_body()
var/global/list/tail_icon_cache = list() //key is [species.race_key][r_skin][g_skin][b_skin]
var/global/list/wing_icon_cache = list() // See tail.
var/global/list/light_overlay_cache = list() //see make_worn_icon() on helmets
var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
var/global/list/_index_extended_clothing_icon_cache= list()
/proc/overlay_image(icon, icon_state, color, layer, flags)
var/image/ret = image(icon, icon_state)
ret.color = color
ret.appearance_flags = flags
ret.layer = layer
return ret
/proc/resolve_text_icon(var/iconstring)
// Polaris has a system for extending clothing icons for suits and uniforms by an index,
// which requires us to identify an icon string being passed in as the previous system
// used icon() universally. This is pretty problematic as a method but unpicking it is
// going to be a big job and this will work for now.
if(istext(iconstring))
if(!global._index_extended_clothing_icon_cache[iconstring])
global._index_extended_clothing_icon_cache[iconstring] = new /icon(iconstring)
return global._index_extended_clothing_icon_cache[iconstring]
return iconstring
// End string icon path hack.
////////////////////////////////////////////////////////////////////////////////////////////////
// # Human Icon Updating System
//
@@ -220,7 +239,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
//0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic.
//Create a new, blank icon for our mob to use.
var/icon/stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi', icon_state = "blank")
var/icon/stand_icon = new(species.icon_template, icon_state = "blank")
var/g = (gender == MALE ? "male" : "female")
var/icon_key = "[species.get_race_key(src)][g][s_tone][r_skin][g_skin][b_skin]"
@@ -292,7 +311,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
//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))
var/icon/temp2 = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi', icon_state = "blank")
var/icon/temp2 = new(species.icon_template, icon_state = "blank")
temp2.Insert(new/icon(temp,dir=NORTH),dir=NORTH)
temp2.Insert(new/icon(temp,dir=SOUTH),dir=SOUTH)
if(!(part.icon_position & LEFT))
@@ -585,16 +604,16 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
var/uniform_sprite
if(under.index)
uniform_sprite = "[INV_W_UNIFORM_DEF_ICON]_[under.index].dmi"
uniform_sprite = "[INV_W_UNIFORM_DEF_STRING]_[under.index].dmi"
else
uniform_sprite = "[INV_W_UNIFORM_DEF_ICON].dmi"
uniform_sprite = INV_W_UNIFORM_DEF_ICON
//Build a uniform sprite
var/icon/c_mask = tail_style?.clip_mask
if(c_mask)
if((wear_suit?.flags_inv & HIDETAIL)) // Reason to not mask: You're wearing a suit that hides the tail
c_mask = null
overlays_standing[UNIFORM_LAYER] = w_uniform.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_w_uniform_str, default_icon = uniform_sprite, default_layer = UNIFORM_LAYER, clip_mask = c_mask)
overlays_standing[UNIFORM_LAYER] = w_uniform.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_w_uniform_str, default_icon = uniform_sprite, default_layer = UNIFORM_LAYER, clip_mask = c_mask)
apply_layer(UNIFORM_LAYER)
/mob/living/carbon/human/update_inv_wear_id()
@@ -610,7 +629,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(w_uniform && istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
if(U.displays_id)
overlays_standing[ID_LAYER] = wear_id.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_wear_id_str, default_icon = INV_WEAR_ID_DEF_ICON, default_layer = ID_LAYER)
overlays_standing[ID_LAYER] = wear_id.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_wear_id_str, default_icon = INV_WEAR_ID_DEF_ICON, default_layer = ID_LAYER)
apply_layer(ID_LAYER)
@@ -623,7 +642,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!gloves)
return //No gloves, no reason to be here.
overlays_standing[GLOVES_LAYER] = gloves.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_gloves_str, default_icon = INV_GLOVES_DEF_ICON, default_layer = GLOVES_LAYER)
overlays_standing[GLOVES_LAYER] = gloves.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_gloves_str, default_icon = INV_GLOVES_DEF_ICON, default_layer = GLOVES_LAYER)
apply_layer(GLOVES_LAYER)
@@ -636,7 +655,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!glasses)
return //Not wearing glasses, no need to update anything.
overlays_standing[GLASSES_LAYER] = glasses.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_gloves_str, default_icon = INV_EYES_DEF_ICON, default_layer = GLASSES_LAYER)
overlays_standing[GLASSES_LAYER] = glasses.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_gloves_str, default_icon = INV_EYES_DEF_ICON, default_layer = GLASSES_LAYER)
apply_layer(GLASSES_LAYER)
@@ -656,11 +675,11 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
var/image/both = image(icon = 'icons/effects/effects.dmi', icon_state = "nothing", layer = BODY_LAYER+EARS_LAYER)
if(l_ear)
var/image/standing = l_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_l_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER)
var/image/standing = l_ear.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_l_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER)
both.add_overlay(standing)
if(r_ear)
var/image/standing = r_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_r_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER)
var/image/standing = r_ear.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_r_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER)
both.add_overlay(standing)
overlays_standing[EARS_LAYER] = both
@@ -689,7 +708,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
shoe_layer = SHOES_LAYER_ALT
//NB: the use of a var for the layer on this one
overlays_standing[shoe_layer] = shoes.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_shoes_str, default_icon = INV_FEET_DEF_ICON, default_layer = shoe_layer)
overlays_standing[shoe_layer] = shoes.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_shoes_str, default_icon = INV_FEET_DEF_ICON, default_layer = shoe_layer)
apply_layer(SHOES_LAYER)
apply_layer(SHOES_LAYER_ALT)
@@ -721,7 +740,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!head)
return //No head item, why bother.
overlays_standing[HEAD_LAYER] = head.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_head_str, default_icon = INV_HEAD_DEF_ICON, default_layer = HEAD_LAYER)
overlays_standing[HEAD_LAYER] = head.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_head_str, default_icon = INV_HEAD_DEF_ICON, default_layer = HEAD_LAYER)
apply_layer(HEAD_LAYER)
@@ -743,7 +762,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
belt_layer = BELT_LAYER_ALT
//NB: this uses a var from above
overlays_standing[belt_layer] = belt.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_belt_str, default_icon = INV_BELT_DEF_ICON, default_layer = belt_layer)
overlays_standing[belt_layer] = belt.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_belt_str, default_icon = INV_BELT_DEF_ICON, default_layer = belt_layer)
apply_layer(belt_layer)
@@ -766,14 +785,14 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
var/suit_sprite
if(istype(suit) && suit.index)
suit_sprite = "[INV_SUIT_DEF_ICON]_[suit.index].dmi"
suit_sprite = "[INV_SUIT_DEF_STRING]_[suit.index].dmi"
else if(istype(suit, /obj/item/clothing) && !isnull(suit.update_icon_define))
suit_sprite = suit.update_icon_define
else
suit_sprite = "[INV_SUIT_DEF_ICON].dmi"
suit_sprite = INV_SUIT_DEF_ICON
var/icon/c_mask = null
overlays_standing[SUIT_LAYER] = wear_suit.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_wear_suit_str, default_icon = suit_sprite, default_layer = SUIT_LAYER, clip_mask = c_mask)
overlays_standing[SUIT_LAYER] = wear_suit.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_wear_suit_str, default_icon = suit_sprite, default_layer = SUIT_LAYER, clip_mask = c_mask)
apply_layer(SUIT_LAYER)
@@ -789,7 +808,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!wear_mask || (head && head.flags_inv & HIDEMASK))
return //Why bother, nothing in mask slot.
overlays_standing[FACEMASK_LAYER] = wear_mask.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_wear_mask_str, default_icon = INV_MASK_DEF_ICON, default_layer = FACEMASK_LAYER)
overlays_standing[FACEMASK_LAYER] = wear_mask.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_wear_mask_str, default_icon = INV_MASK_DEF_ICON, default_layer = FACEMASK_LAYER)
apply_layer(FACEMASK_LAYER)
@@ -802,7 +821,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!back)
return //Why do anything
overlays_standing[BACK_LAYER] = back.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_back_str, default_icon = INV_BACK_DEF_ICON, default_layer = BACK_LAYER)
overlays_standing[BACK_LAYER] = back.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_back_str, default_icon = INV_BACK_DEF_ICON, default_layer = BACK_LAYER)
apply_layer(BACK_LAYER)
@@ -835,7 +854,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!handcuffed)
return //Not cuffed, why bother
overlays_standing[HANDCUFF_LAYER] = handcuffed.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_handcuffed_str, default_icon = INV_HCUFF_DEF_ICON, default_layer = HANDCUFF_LAYER)
overlays_standing[HANDCUFF_LAYER] = handcuffed.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_handcuffed_str, default_icon = INV_HCUFF_DEF_ICON, default_layer = HANDCUFF_LAYER)
apply_layer(HANDCUFF_LAYER)
@@ -851,7 +870,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = legcuffed)
overlays_standing[LEGCUFF_LAYER] = legcuffed.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_legcuffed_str, default_icon = INV_LCUFF_DEF_ICON, default_layer = LEGCUFF_LAYER)
overlays_standing[LEGCUFF_LAYER] = legcuffed.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), slot_name = slot_legcuffed_str, default_icon = INV_LCUFF_DEF_ICON, default_layer = LEGCUFF_LAYER)
apply_layer(LEGCUFF_LAYER)
@@ -864,7 +883,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!r_hand)
return //No hand, no bother.
overlays_standing[R_HAND_LAYER] = r_hand.make_worn_icon(body_type = species.get_bodytype(src), inhands = TRUE, slot_name = slot_r_hand_str, default_icon = INV_R_HAND_DEF_ICON, default_layer = R_HAND_LAYER)
overlays_standing[R_HAND_LAYER] = r_hand.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), inhands = TRUE, slot_name = slot_r_hand_str, default_layer = R_HAND_LAYER)
apply_layer(R_HAND_LAYER)
@@ -877,7 +896,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!l_hand)
return //No hand, no bother.
overlays_standing[L_HAND_LAYER] = l_hand.make_worn_icon(body_type = species.get_bodytype(src), inhands = TRUE, slot_name = slot_l_hand_str, default_icon = INV_L_HAND_DEF_ICON, default_layer = L_HAND_LAYER)
overlays_standing[L_HAND_LAYER] = l_hand.get_worn_overlay(wearer = src, body_type = species.get_bodytype(src), inhands = TRUE, slot_name = slot_l_hand_str, default_icon = INV_L_HAND_DEF_ICON, default_layer = L_HAND_LAYER)
apply_layer(L_HAND_LAYER)

View File

@@ -584,7 +584,7 @@
/mob/proc/is_mechanical()
if(mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI"))
return 1
return istype(src, /mob/living/silicon) || get_species() == "Machine"
return istype(src, /mob/living/silicon) || get_species_name() == "Machine"
/mob/proc/is_ready()
return client && !!mind
@@ -840,7 +840,11 @@
losebreath = clamp(amount, 0, 25)
/mob/proc/get_species()
return ""
return
/mob/proc/get_species_name()
var/datum/species/my_species = get_species()
return my_species?.name
/mob/proc/flash_weak_pain()
flick("weak_pain",pain)

View File

@@ -605,17 +605,11 @@
return check_rights(R_ADMIN, 0, src)
/mob/new_player/get_species()
var/datum/species/chosen_species
if(client.prefs.species)
chosen_species = GLOB.all_species[client.prefs.species]
if(!chosen_species)
return SPECIES_HUMAN
if(is_alien_whitelisted(chosen_species))
return chosen_species.name
return SPECIES_HUMAN
var/datum/species/chosen_species = GLOB.all_species[client.prefs.species]
if(chosen_species && is_alien_whitelisted(src, chosen_species))
return chosen_species
return GLOB.all_species[SPECIES_HUMAN]
/mob/new_player/get_gender()
if(!client || !client.prefs) ..()

View File

@@ -213,8 +213,8 @@
//Calculates a scaling factor for scalding damage, based on the temperature of the oil and creature's heat resistance
/datum/reagent/nutriment/triglyceride/oil/proc/heatdamage(var/mob/living/carbon/M)
var/threshold = 360//Human heatdamage threshold
var/datum/species/S = M.get_species(1)
if (S && istype(S))
var/datum/species/S = M.get_species()
if (istype(S))
threshold = S.heat_level_1
//If temperature is too low to burn, return a factor of 0. no damage
@@ -223,7 +223,7 @@
//Step = degrees above heat level 1 for 1.0 multiplier
var/step = 60
if (S && istype(S))
if (istype(S))
step = (S.heat_level_2 - S.heat_level_1)*1.5
. = data["temperature"] - threshold

View File

@@ -73,7 +73,7 @@
var/mob/living/carbon/human/D = B.data["donor"]
pathogen_pool.Add(list(list(\
"name" = "[istype(D) ? "[D.get_species()] " : ""][B.name]", \
"name" = "[istype(D) ? "[D.get_species_name()] " : ""][B.name]", \
"dna" = B.data["blood_DNA"], \
"unique_id" = V.uniqueID, \
"reference" = "\ref[V]", \
@@ -162,7 +162,7 @@
for(var/datum/reagent/blood/B in sample.reagents.reagent_list)
var/mob/living/carbon/human/D = B.data["donor"]
P.info += "<large><u>[D.get_species()] [B.name]:</u></large><br>[B.data["blood_DNA"]]<br>"
P.info += "<large><u>[D.get_species_name()] [B.name]:</u></large><br>[B.data["blood_DNA"]]<br>"
var/list/virus = B.data["virus2"]
P.info += "<u>Pathogens:</u> <br>"

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

View File

@@ -2365,6 +2365,7 @@
#include "code\modules\mob\living\carbon\human\descriptors\descriptors_skrell.dm"
#include "code\modules\mob\living\carbon\human\descriptors\descriptors_vox.dm"
#include "code\modules\mob\living\carbon\human\species\species.dm"
#include "code\modules\mob\living\carbon\human\species\species_adjust.dm"
#include "code\modules\mob\living\carbon\human\species\species_attack.dm"
#include "code\modules\mob\living\carbon\human\species\species_getters.dm"
#include "code\modules\mob\living\carbon\human\species\species_helpers.dm"