Tail Overhaul 2 (#15577)
* Tail Styles * sql migration * finishing touches * cl * accidentally left this in * credit spriter * animated cloth * cl fix * update migration * updated SQL & changelog, merge conflicts resolved * adds checks for species type in standard.dm * the above but better * Applies Suggestions --------- Co-authored-by: Geeves <ggrobler447@gmail.com> Co-authored-by: Werner <1331699+Arrow768@users.noreply.github.com> Co-authored-by: SleepyGemmy <99297919+SleepyGemmy@users.noreply.github.com>
@@ -0,0 +1,7 @@
|
||||
--
|
||||
-- Implemented in PR #15577.
|
||||
-- Adds the ability for players to select their species' tail, instead of each species only having one stock type of tail.
|
||||
--
|
||||
|
||||
ALTER TABLE `ss13_characters`
|
||||
ADD COLUMN `tail_style` varchar(20) DEFAULT NULL AFTER `skin_colour`
|
||||
@@ -1567,6 +1567,7 @@
|
||||
#include "code\modules\clothing\chameleon.dm"
|
||||
#include "code\modules\clothing\clothing.dm"
|
||||
#include "code\modules\clothing\clothing_accessories.dm"
|
||||
#include "code\modules\clothing\tail_accessory.dm"
|
||||
#include "code\modules\clothing\ears\antennae.dm"
|
||||
#include "code\modules\clothing\ears\bandanna.dm"
|
||||
#include "code\modules\clothing\ears\bulwark.dm"
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
#define slot_shoes_str "slot_shoes"
|
||||
#define slot_wrists_str "slot_wrists"
|
||||
#define slot_gloves_str "slot_gloves"
|
||||
#define slot_tail_str "slot_tail"
|
||||
|
||||
//itemstate suffixes. Used for containedsprite worn items
|
||||
#define WORN_LHAND "_lh"
|
||||
@@ -226,4 +227,4 @@
|
||||
#define SUIT_SENSOR_OFF 0
|
||||
#define SUIT_SENSOR_BINARY 1
|
||||
#define SUIT_SENSOR_VITAL 2
|
||||
#define SUIT_SENSOR_TRACKING 3
|
||||
#define SUIT_SENSOR_TRACKING 3
|
||||
|
||||
@@ -130,3 +130,47 @@
|
||||
if(. && istype(loc, /obj/item/clothing/head/helmet))
|
||||
var/obj/item/clothing/head/helmet/helmet = loc
|
||||
helmet.update_clothing_icon()
|
||||
|
||||
/obj/item/storage/internal/tail
|
||||
name = "tail storage"
|
||||
storage_slots = 1
|
||||
max_storage_space = 2
|
||||
max_w_class = ITEMSIZE_SMALL
|
||||
use_sound = null
|
||||
|
||||
/obj/item/storage/internal/tail/can_be_inserted(obj/item/clothing/tail_accessory/TA, stop_messages)
|
||||
if(!istype(TA))
|
||||
return FALSE
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
var/obj/item/organ/external/E = loc
|
||||
if(!istype(E))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/human/H = E.owner
|
||||
if(!istype(H))
|
||||
return FALSE
|
||||
|
||||
if(!TA.compatible_with_human(H))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
// we can generally assume user has all the proper groin stuff here, otherwise the above block of code is busted
|
||||
/obj/item/storage/internal/tail/handle_item_insertion(obj/item/W, prevent_warning, mob/living/carbon/human/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
user.update_tail_showing()
|
||||
|
||||
/obj/item/storage/internal/tail/remove_from_storage(obj/item/W, atom/new_location)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/obj/item/organ/external/E = loc
|
||||
if(!istype(E))
|
||||
return
|
||||
var/mob/living/carbon/human/H = E.owner
|
||||
if(!istype(H))
|
||||
return
|
||||
H.update_tail_showing()
|
||||
@@ -565,7 +565,7 @@
|
||||
return
|
||||
|
||||
W.add_fingerprint(user)
|
||||
return handle_item_insertion(W)
|
||||
return handle_item_insertion(W, null, user)
|
||||
|
||||
/obj/item/storage/dropped(mob/user as mob)
|
||||
return
|
||||
|
||||
@@ -21,6 +21,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
S["skin_red"] >> pref.r_skin
|
||||
S["skin_green"] >> pref.g_skin
|
||||
S["skin_blue"] >> pref.b_skin
|
||||
S["tail_style_name"] >> pref.tail_style
|
||||
S["hair_style_name"] >> pref.h_style
|
||||
S["facial_style_name"] >> pref.f_style
|
||||
S["grad_style_name"] >> pref.g_style
|
||||
@@ -47,6 +48,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
S["skin_red"] << pref.r_skin
|
||||
S["skin_green"] << pref.g_skin
|
||||
S["skin_blue"] << pref.b_skin
|
||||
S["tail_style_name"] << pref.tail_style
|
||||
S["hair_style_name"] << pref.h_style
|
||||
S["facial_style_name"] << pref.f_style
|
||||
S["grad_style_name"] << pref.g_style
|
||||
@@ -69,6 +71,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
"grad_colour",
|
||||
"skin_tone" = "s_tone",
|
||||
"skin_colour",
|
||||
"tail_style",
|
||||
"hair_style" = "h_style",
|
||||
"facial_style" = "f_style",
|
||||
"gradient_style" = "g_style",
|
||||
@@ -95,6 +98,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
"grad_colour",
|
||||
"skin_tone",
|
||||
"skin_colour",
|
||||
"tail_style",
|
||||
"hair_style",
|
||||
"facial_style",
|
||||
"gradient_style",
|
||||
@@ -116,7 +120,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
"facial_colour" = rgb(pref.r_facial, pref.g_facial, pref.b_facial),
|
||||
"grad_colour" = rgb(pref.r_grad, pref.g_grad, pref.b_grad),
|
||||
"skin_tone" = pref.s_tone,
|
||||
"skin_colour" = rgb(pref.r_skin, pref.g_skin, pref.b_skin) ,
|
||||
"skin_colour" = rgb(pref.r_skin, pref.g_skin, pref.b_skin),
|
||||
"tail_style" = pref.tail_style,
|
||||
"hair_style" = pref.h_style,
|
||||
"facial_style" = pref.f_style,
|
||||
"gradient_style"= pref.g_style,
|
||||
@@ -179,6 +184,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
log_debug("DISABILITIES: Caught [e]. Initial value: [before]")
|
||||
pref.disabilities = list()
|
||||
|
||||
var/datum/species/mob_species = all_species[pref.species]
|
||||
|
||||
pref.r_hair = sanitize_integer(pref.r_hair, 0, 255, initial(pref.r_hair))
|
||||
pref.g_hair = sanitize_integer(pref.g_hair, 0, 255, initial(pref.g_hair))
|
||||
pref.b_hair = sanitize_integer(pref.b_hair, 0, 255, initial(pref.b_hair))
|
||||
@@ -189,6 +196,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
pref.r_skin = sanitize_integer(pref.r_skin, 0, 255, initial(pref.r_skin))
|
||||
pref.g_skin = sanitize_integer(pref.g_skin, 0, 255, initial(pref.g_skin))
|
||||
pref.b_skin = sanitize_integer(pref.b_skin, 0, 255, initial(pref.b_skin))
|
||||
pref.tail_style = sanitize_inlist(pref.tail_style, mob_species.selectable_tails, mob_species.tail)
|
||||
pref.h_style = sanitize_inlist(pref.h_style, hair_styles_list, initial(pref.h_style))
|
||||
pref.f_style = sanitize_inlist(pref.f_style, facial_hair_styles_list, initial(pref.f_style))
|
||||
pref.g_style = sanitize_inlist(pref.g_style, hair_gradient_styles_list, initial(pref.g_style))
|
||||
@@ -293,7 +301,13 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
out += "<br><a href='?src=\ref[src];toggle_preview_value=[EQUIP_PREVIEW_JOB]'>[pref.equip_preview_mob & EQUIP_PREVIEW_JOB ? "Hide job gear" : "Show job gear"]</a>"
|
||||
out += "</td></tr></table>"
|
||||
|
||||
out += "<b>Hair</b><br>"
|
||||
var/tail_spacing = FALSE
|
||||
if(length(mob_species.selectable_tails))
|
||||
out += "<b>Tail</b><br>"
|
||||
out += "<a href='?src=\ref[src];tail_style=1'>[pref.tail_style ? "Style: [pref.tail_style]" : "Style: None"]</a><br>"
|
||||
tail_spacing = TRUE
|
||||
|
||||
out += "[tail_spacing ? "<br>" : ""]<b>Hair</b><br>"
|
||||
if(has_flag(mob_species, HAS_HAIR_COLOR))
|
||||
out += "<a href='?src=\ref[src];hair_color=1'>Change Color</a> [HTML_RECT(rgb(pref.r_hair, pref.g_hair, pref.b_hair))] "
|
||||
out += " Style: <a href='?src=\ref[src];hair_style=1'>[pref.h_style]</a><br>"
|
||||
@@ -303,7 +317,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
out += "<a href='?src=\ref[src];facial_color=1'>Change Color</a> [HTML_RECT(rgb(pref.r_facial, pref.g_facial, pref.b_facial))] "
|
||||
out += " Style: <a href='?src=\ref[src];facial_style=1'>[pref.f_style]</a><br>"
|
||||
|
||||
out += "<b>Gradient</b><br>"
|
||||
out += "<br><b>Gradient</b><br>"
|
||||
if(has_flag(mob_species, HAS_HAIR_COLOR))
|
||||
out += "<a href='?src=\ref[src];gradient_color=1'>Change Color</a> [HTML_RECT(rgb(pref.r_grad, pref.g_grad, pref.b_grad))] "
|
||||
out += " Style: <a href='?src=\ref[src];gradient_style=1'>[pref.g_style]</a><br>"
|
||||
@@ -396,6 +410,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
else // Species has no hair, or something fucked up.
|
||||
pref.h_style = hair_styles_list["Bald"]
|
||||
|
||||
if(length(mob_species.selectable_tails))
|
||||
pref.tail_style = pick(mob_species.selectable_tails)
|
||||
else
|
||||
pref.tail_style = null
|
||||
|
||||
//grab one of the valid facial hair styles for the newly chosen species
|
||||
var/list/valid_facialhairstyles = list()
|
||||
for(var/facialhairstyle in facial_hair_styles_list)
|
||||
@@ -470,6 +489,14 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
pref.b_grad = GetBluePart(new_grad)
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["tail_style"])
|
||||
if(!length(mob_species.selectable_tails))
|
||||
return
|
||||
var/new_tail_style = input(user, "Choose your character's tail style:", "Character Preference", pref.tail_style) as null|anything in mob_species.selectable_tails
|
||||
if(new_tail_style && CanUseTopic(user))
|
||||
pref.tail_style = new_tail_style
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["hair_style"])
|
||||
if(mob_species.bald)
|
||||
return
|
||||
|
||||
@@ -428,6 +428,12 @@
|
||||
charm["holy sun rosette"] = /obj/item/clothing/accessory/tajaran/srendarr
|
||||
gear_tweaks += new /datum/gear_tweak/path(charm)
|
||||
|
||||
/datum/gear/tail_cloth
|
||||
display_name = "tail cloth"
|
||||
path = /obj/item/clothing/tail_accessory/tail_cloth
|
||||
sort_category = "Xenowear - Tajara"
|
||||
flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION | GEAR_HAS_COLOR_SELECTION
|
||||
|
||||
/datum/gear/accessory/dpra_party_pin
|
||||
display_name = "democratic peoples republic party pins selection"
|
||||
description = "A selection of DPRA party pins."
|
||||
|
||||
@@ -48,6 +48,7 @@ datum/preferences
|
||||
var/pda_choice = OUTFIT_TAB_PDA
|
||||
var/headset_choice = OUTFIT_HEADSET
|
||||
var/primary_radio_slot = "Left Ear"
|
||||
var/tail_style = null
|
||||
var/h_style = "Bald" //Hair type
|
||||
var/hair_colour = "#000000" //Hair colour hex value, for SQL loading
|
||||
var/r_hair = 0 //Hair color
|
||||
@@ -440,6 +441,8 @@ datum/preferences
|
||||
character.g_eyes = g_eyes
|
||||
character.b_eyes = b_eyes
|
||||
|
||||
character.set_tail_style(tail_style)
|
||||
|
||||
character.h_style = h_style
|
||||
character.r_hair = r_hair
|
||||
character.g_hair = g_hair
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/obj/item/clothing/tail_accessory
|
||||
name = "tail accessory"
|
||||
desc = DESC_PARENT
|
||||
w_class = ITEMSIZE_SMALL
|
||||
|
||||
var/list/compatible_species_type = list()
|
||||
var/list/compatible_tail_type = list()
|
||||
var/list/compatible_animated_tail = list()
|
||||
|
||||
/obj/item/clothing/tail_accessory/proc/compatible_with_human(var/mob/living/carbon/human/H)
|
||||
if(!is_type_in_list(H.species, compatible_species_type))
|
||||
to_chat(H, SPAN_WARNING("\The [src] doesn't fit on your tail!"))
|
||||
return FALSE
|
||||
|
||||
if(!(H.tail_style in compatible_tail_type))
|
||||
to_chat(H, SPAN_WARNING("\The [src] doesn't fit on your tail!"))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/tail_accessory/tail_cloth
|
||||
name = "tail cloth"
|
||||
desc = "A simple cloth that can be wrapped around the tail."
|
||||
icon = 'icons/clothing/tail/tajtailcloth.dmi'
|
||||
icon_state = "tail_cloth"
|
||||
|
||||
compatible_species_type = list(/datum/species/tajaran)
|
||||
compatible_tail_type = list("Tail")
|
||||
compatible_animated_tail = list("Tail")
|
||||
@@ -16,6 +16,7 @@
|
||||
if(current_species.appearance_flags & HAS_SKIN_COLOR)
|
||||
randomize_skin_color(current_species)
|
||||
|
||||
tail_style = length(current_species.selectable_tails) ? pick(current_species.selectable_tails) : null
|
||||
h_style = random_hair_style(gender, species)
|
||||
f_style = random_facial_hair_style(gender, species)
|
||||
randomize_hair_color("hair")
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/mob/living/carbon/human
|
||||
// Tail Style
|
||||
var/tail_style = null
|
||||
|
||||
//Hair colour and style
|
||||
var/r_hair = 0
|
||||
var/g_hair = 0
|
||||
|
||||
@@ -408,3 +408,21 @@
|
||||
|
||||
/mob/living/carbon/human/get_stutter_verbs()
|
||||
return species.stutter_verbs
|
||||
|
||||
/mob/living/carbon/human/proc/set_tail_style(var/new_style)
|
||||
tail_style = new_style
|
||||
if(tail_style)
|
||||
verbs |= /mob/living/carbon/human/proc/open_tail_storage
|
||||
else
|
||||
verbs -= /mob/living/carbon/human/proc/open_tail_storage
|
||||
|
||||
/mob/living/carbon/human/proc/get_tail_accessory()
|
||||
var/obj/item/organ/external/groin/G = organs_by_name[BP_GROIN]
|
||||
if(!G)
|
||||
return
|
||||
if(!G.tail_storage)
|
||||
return
|
||||
|
||||
if(length(G.tail_storage.contents))
|
||||
return G.tail_storage.contents[1]
|
||||
return null
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
/mob/living/carbon/human/set_dir(var/new_dir, ignore_facing_dir = FALSE)
|
||||
. = ..()
|
||||
if(. && species.tail)
|
||||
if(. && tail_style)
|
||||
update_tail_showing(1)
|
||||
|
||||
/mob/living/carbon/human/Move()
|
||||
|
||||
@@ -835,7 +835,7 @@ mob/living/carbon/human/proc/change_monitor()
|
||||
earpain(3, TRUE, 1)
|
||||
else if (T in range(src, 2))
|
||||
earpain(2, TRUE, 2)
|
||||
|
||||
|
||||
for (var/mob/living/carbon/human/T in hearers(2, src) - src)
|
||||
if(T.get_hearing_protection() >= EAR_PROTECTION_MAJOR)
|
||||
continue
|
||||
@@ -1320,3 +1320,18 @@ mob/living/carbon/human/proc/change_monitor()
|
||||
if (is_listening())
|
||||
visible_message("<b>[src]</b> stops listening intently.")
|
||||
intent_listener -= src
|
||||
|
||||
/mob/living/carbon/human/proc/open_tail_storage()
|
||||
set name = "Tail Accessories"
|
||||
set desc = "Opens the tail accessory slot."
|
||||
set category = "Abilities"
|
||||
|
||||
var/obj/item/organ/external/groin/G = organs_by_name[BP_GROIN]
|
||||
if(!G)
|
||||
to_chat(usr, SPAN_WARNING("You have no tail!"))
|
||||
return
|
||||
if(!G.tail_storage)
|
||||
to_chat(usr, SPAN_WARNING("Your tail storage is missing!"))
|
||||
return
|
||||
|
||||
G.tail_storage.open(usr)
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
var/tail // Name of tail state in species effects icon file.
|
||||
var/tail_animation // If set, the icon to obtain tail animation states from.
|
||||
var/tail_hair
|
||||
var/list/selectable_tails
|
||||
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
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
brute_mod = 0.9
|
||||
oxy_mod = 0.9
|
||||
hydration_loss_factor = 1.1
|
||||
tail = "axiori_tail"
|
||||
tail = "Tail"
|
||||
tail_animation = 'icons/mob/species/skrell/tail.dmi'
|
||||
selectable_tails = list("Tail")
|
||||
eyes = "skrell_axiori_eyes_s"
|
||||
|
||||
sprint_speed_factor = 0.7 // Species default 0.8
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
deform = 'icons/mob/human_races/tajara/r_def_tajaran.dmi'
|
||||
preview_icon = 'icons/mob/human_races/tajara/tajaran_preview.dmi'
|
||||
bandages_icon = 'icons/mob/bandage.dmi'
|
||||
tail = "tajtail"
|
||||
tail = "Tail"
|
||||
tail_animation = 'icons/mob/species/tajaran/tail.dmi'
|
||||
selectable_tails = list("Tail", "Hakh'jar Tail")
|
||||
unarmed_types = list(
|
||||
/datum/unarmed_attack/stomp,
|
||||
/datum/unarmed_attack/kick,
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
deform = 'icons/mob/human_races/unathi/r_def_unathi.dmi'
|
||||
preview_icon = 'icons/mob/human_races/unathi/unathi_preview.dmi'
|
||||
bandages_icon = 'icons/mob/bandage.dmi'
|
||||
tail = "unathtail"
|
||||
tail = "Tail"
|
||||
tail_animation = 'icons/mob/species/unathi/tail.dmi'
|
||||
selectable_tails = list("Tail")
|
||||
unarmed_types = list(
|
||||
/datum/unarmed_attack/stomp,
|
||||
/datum/unarmed_attack/kick,
|
||||
|
||||
@@ -86,45 +86,48 @@ There are several things that need to be remembered:
|
||||
|
||||
// Human Overlays Indexes //
|
||||
// Layer 1 intentionally left empty.
|
||||
#define FIRE_LAYER_LOWER 2
|
||||
#define MUTATIONS_LAYER 3
|
||||
#define DAMAGE_LAYER 4
|
||||
#define SURGERY_LAYER 5
|
||||
#define UNDERWEAR_LAYER 6
|
||||
#define TAIL_SOUTH_LAYER 7
|
||||
#define SHOES_LAYER_ALT 8
|
||||
#define UNIFORM_LAYER 9
|
||||
#define ID_LAYER 10
|
||||
#define SHOES_LAYER 11
|
||||
#define GLOVES_LAYER 12
|
||||
#define BELT_LAYER 13
|
||||
#define WRISTS_LAYER_ALT 14
|
||||
#define SUIT_LAYER 15
|
||||
#define ID_LAYER_ALT 16
|
||||
#define TAIL_NORTH_LAYER 17
|
||||
#define HAIR_LAYER_ALT 18
|
||||
#define GLASSES_LAYER 19
|
||||
#define BELT_LAYER_ALT 20
|
||||
#define SUIT_STORE_LAYER 21
|
||||
#define BACK_LAYER 22
|
||||
#define HAIR_LAYER 23
|
||||
#define GLASSES_LAYER_ALT 24
|
||||
#define L_EAR_LAYER 25
|
||||
#define R_EAR_LAYER 26
|
||||
#define FACEMASK_LAYER 27
|
||||
#define HEAD_LAYER 28
|
||||
#define COLLAR_LAYER 29
|
||||
#define HANDCUFF_LAYER 30
|
||||
#define LEGCUFF_LAYER 31
|
||||
#define L_HAND_LAYER 32
|
||||
#define R_HAND_LAYER 33
|
||||
#define WRISTS_LAYER 34
|
||||
#define FIRE_LAYER_UPPER 35
|
||||
#define TOTAL_LAYERS 35
|
||||
#define FIRE_LAYER_LOWER 2
|
||||
#define MUTATIONS_LAYER 3
|
||||
#define DAMAGE_LAYER 4
|
||||
#define SURGERY_LAYER 5
|
||||
#define UNDERWEAR_LAYER 6
|
||||
#define TAIL_SOUTH_LAYER 7
|
||||
#define TAIL_SOUTH_ACC_LAYER 8
|
||||
#define SHOES_LAYER_ALT 9
|
||||
#define UNIFORM_LAYER 10
|
||||
#define ID_LAYER 11
|
||||
#define SHOES_LAYER 12
|
||||
#define GLOVES_LAYER 13
|
||||
#define BELT_LAYER 14
|
||||
#define WRISTS_LAYER_ALT 15
|
||||
#define SUIT_LAYER 16
|
||||
#define ID_LAYER_ALT 17
|
||||
#define TAIL_NORTH_LAYER 18
|
||||
#define TAIL_NORTH_ACC_LAYER 19
|
||||
#define HAIR_LAYER_ALT 20
|
||||
#define GLASSES_LAYER 21
|
||||
#define BELT_LAYER_ALT 22
|
||||
#define SUIT_STORE_LAYER 23
|
||||
#define BACK_LAYER 24
|
||||
#define HAIR_LAYER 25
|
||||
#define GLASSES_LAYER_ALT 26
|
||||
#define L_EAR_LAYER 27
|
||||
#define R_EAR_LAYER 28
|
||||
#define FACEMASK_LAYER 29
|
||||
#define HEAD_LAYER 30
|
||||
#define COLLAR_LAYER 31
|
||||
#define HANDCUFF_LAYER 32
|
||||
#define LEGCUFF_LAYER 33
|
||||
#define L_HAND_LAYER 34
|
||||
#define R_HAND_LAYER 35
|
||||
#define WRISTS_LAYER 36
|
||||
#define FIRE_LAYER_UPPER 37
|
||||
#define TOTAL_LAYERS 37
|
||||
////////////////////////////
|
||||
|
||||
#define GET_BODY_TYPE (cached_bodytype || (cached_bodytype = species.get_bodytype()))
|
||||
#define GET_TAIL_LAYER (dir == NORTH ? TAIL_NORTH_LAYER : TAIL_SOUTH_LAYER)
|
||||
#define GET_TAIL_ACC_LAYER (dir == NORTH ? TAIL_NORTH_ACC_LAYER : TAIL_SOUTH_ACC_LAYER)
|
||||
|
||||
/proc/overlay_image(icon,icon_state,color,flags)
|
||||
var/image/ret = image(icon,icon_state)
|
||||
@@ -1287,8 +1290,9 @@ There are several things that need to be remembered:
|
||||
|
||||
if(species.tail && NOT_FLAG(mutations, HUSK) && NOT_FLAG(mutations, SKELETON) && !(wear_suit && wear_suit.flags_inv & HIDETAIL))
|
||||
var/icon/tail_s = get_tail_icon()
|
||||
overlays_raw[tail_layer] = image(tail_s, icon_state = "[species.tail]_s")
|
||||
animate_tail_reset(0)
|
||||
overlays_raw[tail_layer] = image(tail_s, icon_state = "[tail_style]_s")
|
||||
animate_tail_reset()
|
||||
update_tail_accessory(FALSE)
|
||||
|
||||
if(update_icons)
|
||||
update_icon()
|
||||
@@ -1305,7 +1309,7 @@ There are several things that need to be remembered:
|
||||
tail_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
|
||||
// The following will not work with animated tails.
|
||||
if(species.tail_hair)
|
||||
var/icon/hair_icon = icon('icons/effects/species.dmi', "[species.tail]_[species.tail_hair]")
|
||||
var/icon/hair_icon = icon('icons/effects/species.dmi', "[tail_style]_[species.tail_hair]")
|
||||
hair_icon.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD)
|
||||
tail_icon.Blend(hair_icon, ICON_OVERLAY)
|
||||
SSicon_cache.tail_icon_cache[icon_key] = tail_icon
|
||||
@@ -1313,16 +1317,20 @@ There are several things that need to be remembered:
|
||||
return tail_icon
|
||||
|
||||
/mob/living/carbon/human/proc/set_tail_state(var/mob_state)
|
||||
if (!species.tail)
|
||||
if(!tail_style)
|
||||
return
|
||||
|
||||
var/tail_layer = GET_TAIL_LAYER
|
||||
|
||||
var/image/tail_overlay = overlays_raw[tail_layer]
|
||||
|
||||
var/obj/item/clothing/tail_accessory/TA = get_tail_accessory()
|
||||
if(TA && !(tail_style in TA.compatible_animated_tail))
|
||||
mob_state = "[tail_style]_static"
|
||||
|
||||
if(tail_overlay && species.tail_animation)
|
||||
if (tail_overlay.icon_state != mob_state)
|
||||
if(tail_overlay.icon_state != mob_state)
|
||||
tail_overlay.icon_state = mob_state
|
||||
update_tail_accessory()
|
||||
update_icon()
|
||||
return tail_overlay
|
||||
return null
|
||||
@@ -1330,7 +1338,7 @@ There are several things that need to be remembered:
|
||||
//Not really once, since BYOND can't do that.
|
||||
//Update this if the ability to flick() images or make looping animation start at the first frame is ever added.
|
||||
/mob/living/carbon/human/proc/animate_tail_once()
|
||||
var/mob_state = "[species.tail]_once"
|
||||
var/mob_state = "[tail_style]_once"
|
||||
|
||||
var/tail_layer = GET_TAIL_LAYER
|
||||
|
||||
@@ -1345,23 +1353,42 @@ There are several things that need to be remembered:
|
||||
/mob/living/carbon/human/proc/end_animate_tail_once(image/tail_overlay)
|
||||
//check that the animation hasn't changed in the meantime
|
||||
var/tail_layer = GET_TAIL_LAYER
|
||||
if(overlays_raw[tail_layer] == tail_overlay && tail_overlay.icon_state == "[species.tail]_once")
|
||||
if(overlays_raw[tail_layer] == tail_overlay && tail_overlay.icon_state == "[tail_style]_once")
|
||||
animate_tail_stop()
|
||||
update_tail_accessory()
|
||||
|
||||
/mob/living/carbon/human/proc/animate_tail_start()
|
||||
set_tail_state("[species.tail]_slow[rand(0,9)]")
|
||||
set_tail_state("[tail_style]_slow")
|
||||
|
||||
/mob/living/carbon/human/proc/animate_tail_fast()
|
||||
set_tail_state("[species.tail]_loop[rand(0,9)]")
|
||||
set_tail_state("[tail_style]_loop")
|
||||
|
||||
/mob/living/carbon/human/proc/animate_tail_reset()
|
||||
if(stat != DEAD && !lying)
|
||||
set_tail_state("[species.tail]_idle[rand(0,9)]")
|
||||
set_tail_state("[tail_style]_idle")
|
||||
else
|
||||
set_tail_state("[species.tail]_static")
|
||||
set_tail_state("[tail_style]_static")
|
||||
|
||||
/mob/living/carbon/human/proc/animate_tail_stop(var/update_icons=1)
|
||||
set_tail_state("[species.tail]_static")
|
||||
set_tail_state("[tail_style]_static")
|
||||
|
||||
/mob/living/carbon/human/proc/update_tail_accessory(var/update_icons=1)
|
||||
overlays_raw[TAIL_NORTH_ACC_LAYER] = null
|
||||
overlays_raw[TAIL_SOUTH_ACC_LAYER] = null
|
||||
|
||||
var/obj/item/clothing/tail_accessory/TA = get_tail_accessory()
|
||||
if(!TA)
|
||||
return
|
||||
|
||||
var/image/tail_overlay = overlays_raw[GET_TAIL_LAYER]
|
||||
if(!tail_overlay)
|
||||
return
|
||||
|
||||
overlays_raw[GET_TAIL_ACC_LAYER] = TA.get_mob_overlay(src, TA.icon, "[tail_overlay.icon_state]_to", slot_tail_str)
|
||||
|
||||
if(update_icons)
|
||||
update_icon()
|
||||
|
||||
|
||||
//Adds a collar overlay above the helmet layer if the suit has one
|
||||
// Suit needs an identically named sprite in icons/mob/collar.dmi
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
. = ..()
|
||||
addtimer(CALLBACK(src, PROC_REF(setup_storage)), 3 SECONDS)
|
||||
|
||||
/obj/item/organ/external/head/skrell/Destroy()
|
||||
QDEL_NULL(storage)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/external/head/skrell/proc/setup_storage()
|
||||
storage = new /obj/item/storage/internal/skrell(src)
|
||||
if(owner)
|
||||
@@ -56,4 +60,4 @@
|
||||
|
||||
/obj/item/organ/internal/liver/skrell/neaera
|
||||
|
||||
/obj/item/organ/internal/brain/skrell/neaera
|
||||
/obj/item/organ/internal/brain/skrell/neaera
|
||||
|
||||
@@ -43,6 +43,24 @@
|
||||
gendered_icon = 1
|
||||
augment_limit = 3
|
||||
|
||||
var/obj/item/storage/internal/tail/tail_storage
|
||||
|
||||
/obj/item/organ/external/groin/Initialize()
|
||||
. = ..()
|
||||
if(owner.species.tail)
|
||||
tail_storage = new /obj/item/storage/internal/tail(src)
|
||||
|
||||
/obj/item/organ/external/groin/Destroy()
|
||||
if(owner?.species.tail)
|
||||
QDEL_NULL(tail_storage)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/external/groin/removed()
|
||||
. = ..()
|
||||
if(owner?.species.tail)
|
||||
for(var/thing in tail_storage)
|
||||
tail_storage.remove_from_storage(thing, get_turf(src))
|
||||
|
||||
/obj/item/organ/external/groin/body_part_class()
|
||||
return UPPER_TORSO
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
author: Geeves, Kyres1, Ramke
|
||||
|
||||
delete-after: True
|
||||
|
||||
changes:
|
||||
- rscadd: "Added a new shorter tail type for Tajara."
|
||||
- rscadd: "Added a colorable tail cloth accessory for the standard Tajara tail."
|
||||
|
After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 395 B |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 3.1 KiB |