diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 10294e7b85..7e226508b0 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -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"
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index 85e9073160..ae03c77720 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -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]
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index be959fd596..8987f179a7 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -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
diff --git a/code/datums/uplink/announcements.dm b/code/datums/uplink/announcements.dm
index 612e7c645e..3d5ec18feb 100644
--- a/code/datums/uplink/announcements.dm
+++ b/code/datums/uplink/announcements.dm
@@ -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
-
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index f040241e10..3b09e3ccae 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -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)
diff --git a/code/game/objects/items/paintkit.dm b/code/game/objects/items/paintkit.dm
index ddfd1d7204..18954543c8 100644
--- a/code/game/objects/items/paintkit.dm
+++ b/code/game/objects/items/paintkit.dm
@@ -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 ..()
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 91d14affe7..7bd3e1bd9f 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -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)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 74b7c466aa..4d69794d05 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -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))
diff --git a/code/modules/clothing/clothing_icons.dm b/code/modules/clothing/clothing_icons.dm
index 2adfbfa0b9..75c9af0017 100644
--- a/code/modules/clothing/clothing_icons.dm
+++ b/code/modules/clothing/clothing_icons.dm
@@ -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
diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm
index c179e988e6..9d1216b633 100644
--- a/code/modules/clothing/spacesuits/rig/rig.dm
+++ b/code/modules/clothing/spacesuits/rig/rig.dm
@@ -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)
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
index 53f92c9894..70314cb6b0 100644
--- a/code/modules/clothing/under/accessories/accessory.dm
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -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)
diff --git a/code/modules/clothing/under/accessories/clothing.dm b/code/modules/clothing/under/accessories/clothing.dm
index 2f7358eeef..674e096b12 100644
--- a/code/modules/clothing/under/accessories/clothing.dm
+++ b/code/modules/clothing/under/accessories/clothing.dm
@@ -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)
diff --git a/code/modules/clothing/under/accessories/crafted/poncho.dm b/code/modules/clothing/under/accessories/crafted/poncho.dm
index e164c2f937..13d6616457 100644
--- a/code/modules/clothing/under/accessories/crafted/poncho.dm
+++ b/code/modules/clothing/under/accessories/crafted/poncho.dm
@@ -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
diff --git a/code/modules/clothing/under/accessories/torch.dm b/code/modules/clothing/under/accessories/torch.dm
index 6965056059..37dda95e9f 100644
--- a/code/modules/clothing/under/accessories/torch.dm
+++ b/code/modules/clothing/under/accessories/torch.dm
@@ -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"
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 9f89e5223a..9c66359376 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -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)
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 2c8d4e78fc..14b0335a0b 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -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
diff --git a/code/modules/mob/living/carbon/human/species/species_adjust.dm b/code/modules/mob/living/carbon/human/species/species_adjust.dm
new file mode 100644
index 0000000000..fb2ce01a30
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/species/species_adjust.dm
@@ -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
diff --git a/code/modules/mob/living/carbon/human/species/station/teshari.dm b/code/modules/mob/living/carbon/human/species/station/teshari.dm
index 5c9ac82193..0400cfe30a 100644
--- a/code/modules/mob/living/carbon/human/species/station/teshari.dm
+++ b/code/modules/mob/living/carbon/human/species/station/teshari.dm
@@ -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)
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 1506b84209..a04d0fe59d 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -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)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 4af94ae040..47706d84b5 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -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)
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index d13a11fc54..099c47cfcf 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -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) ..()
diff --git a/code/modules/reagents/reagents/food_drinks.dm b/code/modules/reagents/reagents/food_drinks.dm
index 291730032e..bea39e521f 100644
--- a/code/modules/reagents/reagents/food_drinks.dm
+++ b/code/modules/reagents/reagents/food_drinks.dm
@@ -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
diff --git a/code/modules/virus2/isolator.dm b/code/modules/virus2/isolator.dm
index 792d996085..73ddced46b 100644
--- a/code/modules/virus2/isolator.dm
+++ b/code/modules/virus2/isolator.dm
@@ -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]", \
@@ -108,7 +108,7 @@
var/mob/user = usr
add_fingerprint(user)
-
+
. = TRUE
switch(tgui_modal_act(src, action, params))
if(TGUI_MODAL_ANSWER)
@@ -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 += "[D.get_species()] [B.name]:
[B.data["blood_DNA"]]
"
+ P.info += "[D.get_species_name()] [B.name]:
[B.data["blood_DNA"]]
"
var/list/virus = B.data["virus2"]
P.info += "Pathogens:
"
diff --git a/icons/mob/human_races/template.dmi b/icons/mob/human_races/template.dmi
new file mode 100644
index 0000000000..b90326cdf4
Binary files /dev/null and b/icons/mob/human_races/template.dmi differ
diff --git a/polaris.dme b/polaris.dme
index 09cf6bf067..ec35a918c8 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -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"