|
37 | 37 | var/e_colour = "#000000" //Eye color
|
38 | 38 | var/alt_head = "None" //Alt head style.
|
39 | 39 | var/species = "Human"
|
| 40 | + /// Used for DNA species to allow select species to imitate / morph into different species. |
| 41 | + var/species_subtype = "None" |
40 | 42 | var/language = "None" //Secondary language
|
41 | 43 | var/autohiss_mode = AUTOHISS_OFF //Species autohiss level. OFF, BASIC, FULL.
|
42 | 44 | /// If a spawned cyborg should have an MMI, a positronic, or a robobrain. MMI by default
|
|
202 | 204 | runechat_color=:runechat_color,
|
203 | 205 | cyborg_brain_type=:cyborg_brain_type,
|
204 | 206 | body_type=:body_type,
|
205 |
| - pda_ringtone=:pda_ringtone |
| 207 | + pda_ringtone=:pda_ringtone, |
| 208 | + species_subtype=:species_subtype |
206 | 209 | WHERE ckey=:ckey
|
207 | 210 | AND slot=:slot"}, list(
|
208 | 211 | // OH GOD SO MANY PARAMETERS
|
|
266 | 269 | "runechat_color" = runechat_color,
|
267 | 270 | "cyborg_brain_type" = cyborg_brain_type,
|
268 | 271 | "pda_ringtone" = pda_ringtone,
|
| 272 | + "species_subtype" = species_subtype, |
269 | 273 | "ckey" = C.ckey,
|
270 | 274 | "slot" = slot_number
|
271 | 275 | ))
|
|
306 | 310 | player_alt_titles,
|
307 | 311 | disabilities, organ_data, rlimb_data, nanotrasen_relation, physique, height, speciesprefs,
|
308 | 312 | socks, body_accessory, gear, autohiss,
|
309 |
| - hair_gradient, hair_gradient_offset, hair_gradient_colour, hair_gradient_alpha, custom_emotes, runechat_color, cyborg_brain_type, body_type, pda_ringtone) |
| 313 | + hair_gradient, hair_gradient_offset, hair_gradient_colour, hair_gradient_alpha, custom_emotes, runechat_color, cyborg_brain_type, body_type, pda_ringtone, species_subtype) |
310 | 314 | VALUES
|
311 | 315 | (:ckey, :slot, :metadata, :name, :be_random_name, :gender,
|
312 | 316 | :age, :species, :language,
|
|
333 | 337 | :playertitlelist,
|
334 | 338 | :disabilities, :organ_list, :rlimb_list, :nanotrasen_relation, :physique, :height, :speciesprefs,
|
335 | 339 | :socks, :body_accessory, :gearlist, :autohiss_mode,
|
336 |
| - :h_grad_style, :h_grad_offset, :h_grad_colour, :h_grad_alpha, :custom_emotes, :runechat_color, :cyborg_brain_type, :body_type, :pda_ringtone) |
| 340 | + :h_grad_style, :h_grad_offset, :h_grad_colour, :h_grad_alpha, :custom_emotes, :runechat_color, :cyborg_brain_type, :body_type, :pda_ringtone, :species_subtype) |
337 | 341 | "}, list(
|
338 | 342 | // This has too many params for anyone to look at this without going insae
|
339 | 343 | "ckey" = C.ckey,
|
|
397 | 401 | "custom_emotes" = json_encode(custom_emotes),
|
398 | 402 | "runechat_color" = runechat_color,
|
399 | 403 | "cyborg_brain_type" = cyborg_brain_type,
|
400 |
| - "pda_ringtone" = pda_ringtone |
| 404 | + "pda_ringtone" = pda_ringtone, |
| 405 | + "species_subtype" = species_subtype |
401 | 406 | ))
|
402 | 407 |
|
403 | 408 | if(!query.warn_execute())
|
|
422 | 427 | age = text2num(query.item[5])
|
423 | 428 | species = query.item[6]
|
424 | 429 | language = query.item[7]
|
425 |
| - |
426 | 430 | h_colour = query.item[8]
|
427 | 431 | h_sec_colour = query.item[9]
|
428 | 432 | f_colour = query.item[10]
|
|
493 | 497 | cyborg_brain_type = query.item[59]
|
494 | 498 | body_type = query.item[60]
|
495 | 499 | pda_ringtone = query.item[61]
|
496 |
| - |
| 500 | + species_subtype = query.item[62] |
497 | 501 | //Sanitize
|
498 | 502 | var/datum/species/SP = GLOB.all_species[species]
|
499 | 503 | if(!SP)
|
|
507 | 511 | species = "Human"
|
508 | 512 | stack_trace("Character doesn't have a species, character name is [real_name]. Defaulting to human.")
|
509 | 513 |
|
| 514 | + if(isnull(species_subtype)) |
| 515 | + species_subtype = "None" |
| 516 | + |
510 | 517 | if(isnull(language))
|
511 | 518 | language = "None"
|
512 | 519 |
|
|
830 | 837 | //Icon-based species colour.
|
831 | 838 | var/coloured_tail
|
832 | 839 | if(current_species)
|
833 |
| - if(current_species.bodyflags & HAS_ICON_SKIN_TONE) //Handling species-specific icon-based skin tones by flagged race. |
834 |
| - var/mob/living/carbon/human/fake/H = new |
835 |
| - H.dna.species = current_species |
| 840 | + var/mob/living/carbon/human/fake/H = new |
| 841 | + H.dna.species = current_species |
| 842 | + if(species_subtype != "None" && current_species.bodyflags & HAS_SPECIES_SUBTYPE) |
| 843 | + var/datum/species/subtype_species = GLOB.all_species[species_subtype] |
| 844 | + if(subtype_species) // Take certain attributes from our subtype to apply to our current species. |
| 845 | + H.dna.species.updatespeciessubtype(H, subtype_species) |
| 846 | + current_species = H.dna.species |
| 847 | + else if(current_species.bodyflags & HAS_ICON_SKIN_TONE) //Handling species-specific icon-based skin tones by flagged race. |
836 | 848 | H.s_tone = s_tone
|
837 | 849 | H.dna.species.updatespeciescolor(H, 0) //The mob's species wasn't set, so it's almost certainly different than the character's species at the moment. Thus, we need to be owner-insensitive.
|
838 |
| - var/obj/item/organ/external/chest/C = H.get_organ("chest") |
839 |
| - icobase = C.icobase ? C.icobase : C.dna.species.icobase |
840 | 850 | if(H.dna.species.bodyflags & HAS_TAIL)
|
841 | 851 | coloured_tail = H.tail ? H.tail : H.dna.species.tail
|
842 |
| - |
843 |
| - qdel(H) |
844 |
| - else |
845 |
| - icobase = current_species.icobase |
| 852 | + icobase = current_species.icobase |
| 853 | + qdel(H) |
846 | 854 | else
|
847 | 855 | icobase = 'icons/mob/human_races/r_human.dmi'
|
848 | 856 |
|
849 | 857 | preview_icon = new /icon(icobase, "torso_[g]")
|
850 | 858 | preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY)
|
851 |
| - var/head = "head" |
852 |
| - if(alt_head && current_species.bodyflags & HAS_ALT_HEADS) |
853 |
| - var/datum/sprite_accessory/alt_heads/H = GLOB.alt_heads_list[alt_head] |
854 |
| - if(H.icon_state) |
855 |
| - head = H.icon_state |
856 |
| - preview_icon.Blend(new /icon(icobase, "[head]_[g]"), ICON_OVERLAY) |
857 |
| - |
858 | 859 | for(var/name in list("chest", "groin", "head", "r_arm", "r_hand", "r_leg", "r_foot", "l_leg", "l_foot", "l_arm", "l_hand"))
|
859 |
| - if(organ_data[name] == "amputated") continue |
860 |
| - if(organ_data[name] == "cyborg") |
| 860 | + if(organ_data[name] == "amputated") |
| 861 | + continue |
| 862 | + var/icon/bodypart = new /icon(icobase, "[name]") |
| 863 | + if(name == "head") // Head nonsense. |
| 864 | + var/head = "head" |
| 865 | + if(alt_head && current_species.bodyflags & HAS_ALT_HEADS) |
| 866 | + var/datum/sprite_accessory/alt_heads/H = GLOB.alt_heads_list[alt_head] |
| 867 | + if(H.icon_state) |
| 868 | + head = H.icon_state |
| 869 | + bodypart = new /icon(icobase, "[head]_[g]") // head_state _ gender |
| 870 | + if(name in list("chest", "groin")) // Groin and Chest nonsense |
| 871 | + if(name == "chest") |
| 872 | + name = "torso" |
| 873 | + bodypart = new /icon(icobase, "[name]_[g]") // groin/torso _ gender |
| 874 | + if(organ_data[name] == "cyborg") // Robotic limbs. |
861 | 875 | var/datum/robolimb/R
|
862 | 876 | if(rlimb_data[name]) R = GLOB.all_robolimbs[rlimb_data[name]]
|
863 | 877 | if(!R) R = GLOB.basic_robolimb
|
864 | 878 | if(name == "chest")
|
865 | 879 | name = "torso"
|
866 |
| - preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic. |
| 880 | + if(length(R.sprite_sheets) && R.sprite_sheets[current_species.sprite_sheet_name]) // Species specific augmented limbs |
| 881 | + R.icon = R.sprite_sheets[current_species.sprite_sheet_name] |
| 882 | + bodypart.Blend(new /icon(R.icon, "[name]"), ICON_OVERLAY) |
| 883 | + preview_icon.Blend(bodypart, ICON_OVERLAY) |
867 | 884 | continue
|
868 |
| - preview_icon.Blend(new /icon(icobase, "[name]"), ICON_OVERLAY) |
869 |
| - |
870 |
| - // Skin color |
871 |
| - if(current_species && (current_species.bodyflags & HAS_SKIN_COLOR)) |
872 |
| - preview_icon.Blend(s_colour, ICON_ADD) |
873 |
| - |
874 |
| - // Skin tone |
875 |
| - if(current_species && (current_species.bodyflags & HAS_SKIN_TONE)) |
876 |
| - if(s_tone >= 0) |
877 |
| - preview_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) |
| 885 | + if(istype(current_species, /datum/species/slime) && current_species.species_subtype != "None") // Applies to limbs that are not robotic. |
| 886 | + bodypart.GrayScale() |
| 887 | + bodypart.Blend("[s_colour]DC", ICON_AND) //DC = 220 alpha. |
878 | 888 | else
|
879 |
| - preview_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) |
| 889 | + // Skin color |
| 890 | + if(current_species && (current_species.bodyflags & HAS_SKIN_COLOR)) |
| 891 | + bodypart.Blend(s_colour, ICON_ADD) |
| 892 | + // Skin tone |
| 893 | + if(current_species && (current_species.bodyflags & HAS_SKIN_TONE)) |
| 894 | + if(s_tone >= 0) |
| 895 | + bodypart.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) |
| 896 | + else |
| 897 | + bodypart.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) |
| 898 | + preview_icon.Blend(bodypart, ICON_OVERLAY) |
880 | 899 |
|
881 | 900 | // Body accessory
|
882 | 901 | if(current_species && (current_species.bodyflags & HAS_BODY_ACCESSORY))
|
|
1831 | 1850 | /datum/character_save/proc/copy_to(mob/living/carbon/human/character)
|
1832 | 1851 | var/datum/species/S = GLOB.all_species[species]
|
1833 | 1852 | character.set_species(S.type, delay_icon_update = TRUE) // Yell at me if this causes everything to melt
|
| 1853 | + var/datum/species/subtype = GLOB.all_species[species_subtype] |
| 1854 | + if(!isnull(subtype)) |
| 1855 | + character.dna.species.updatespeciessubtype(character, new subtype.type(), TRUE, FALSE) |
| 1856 | + else |
| 1857 | + character.species_subtype = "None" |
1834 | 1858 | if(be_random_name)
|
1835 | 1859 | real_name = random_name(gender, species)
|
1836 | 1860 |
|
|
0 commit comments